deceasedSearch.vue 供奉记录页面框架
This commit is contained in:
parent
2a7e874ae3
commit
814d622295
18
api/memorial/memorial.js
Normal file
18
api/memorial/memorial.js
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
// 获取牌位详情
|
||||
export function getMemorialDetail(id) {
|
||||
return request({
|
||||
url: `/app/memorial/${id}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取供奉记录列表
|
||||
export function getEnshrinedList(params) {
|
||||
return request({
|
||||
url: '/app/enshrined/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
|
@ -6,7 +6,8 @@ export const CommonEnum = {
|
|||
BASE_COLOR:"#FAF8F3", //基调颜色
|
||||
SEARCH: "https://api.ccttiot.com/image-1753769500465.png", //通用搜索图标
|
||||
TILE: "https://api.ccttiot.com/image-1753750309203.png", //瓦片图片
|
||||
BOTTOM_TILES:"https://api.ccttiot.com/image-1754446176001.png",//底部瓦片组
|
||||
BOTTOM_TILES:"https://api.ccttiot.com/image-1754446176001.png",//底部瓦片组背景淡黄
|
||||
BOTTOM_TILES_2:" https://api.ccttiot.com/image-1754898426052.png",//底部瓦片组背景纯白
|
||||
FILTER: "https://api.ccttiot.com/image-1753954149098.png", //筛选图标
|
||||
REFRESH:"https://api.ccttiot.com/%E5%AE%B9%E5%99%A8-1754011714179.png", //刷新图标
|
||||
NAV_ARROW:"https://api.ccttiot.com/image-1754127104177.png", //导航箭头
|
||||
|
|
@ -17,7 +18,6 @@ export const CommonEnum = {
|
|||
KongmingLantern:'https://api.ccttiot.com/image-1754376453672.png',//孔明灯
|
||||
Refresh:'https://api.ccttiot.com/image-1754377032112.png',//刷新
|
||||
LotusMeditation:'https://api.ccttiot.com/image-1754377169541.png',//莲坐禅心
|
||||
|
||||
|
||||
CENTER_TILES:"https://api.ccttiot.com/image-1754897751419.png",//腰部瓦片组
|
||||
};
|
||||
export default CommonEnum;
|
||||
14
pages.json
14
pages.json
|
|
@ -155,6 +155,20 @@
|
|||
"enablePullDownRefresh": true,
|
||||
"backgroundTextStyle": "dark"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/memorial/enshrinedList",
|
||||
"style" :
|
||||
{
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/memorial/deceasedSearch",
|
||||
"style" :
|
||||
{
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
],
|
||||
"subPackages": [
|
||||
|
|
|
|||
134
pages/memorial/README.md
Normal file
134
pages/memorial/README.md
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
# 供奉记录页面使用说明
|
||||
|
||||
## 功能概述
|
||||
|
||||
`enshrinedList.vue` 是一个供奉记录展示页面,通过调用两个API接口来获取和展示数据:
|
||||
|
||||
1. **牌位详情API**: `GET /app/memorial/{id}` - 获取牌位基本信息
|
||||
2. **供奉记录API**: `GET /app/enshrined/list` - 获取该牌位的供奉记录列表
|
||||
|
||||
## 页面特性
|
||||
|
||||
### 🎨 界面设计
|
||||
- **牌位信息卡片**: 显示牌位名称和介绍信息
|
||||
- **供奉记录表格**: 展示供奉人、时间、类型等信息
|
||||
- **响应式布局**: 适配不同屏幕尺寸
|
||||
- **传统风格**: 使用佛教主题色彩和设计元素
|
||||
|
||||
### 📱 交互功能
|
||||
- **下拉刷新**: 重新加载最新数据
|
||||
- **上拉加载**: 分页加载更多记录
|
||||
- **姓名脱敏**: 保护用户隐私
|
||||
- **错误处理**: 网络错误时显示重试选项
|
||||
|
||||
### 🔧 技术特性
|
||||
- **并行API调用**: 同时请求两个接口提高加载速度
|
||||
- **数据格式化**: 日期格式化和姓名脱敏处理
|
||||
- **状态管理**: 加载状态、错误状态、空状态处理
|
||||
- **分页支持**: 支持大量数据的分页展示
|
||||
|
||||
## API接口说明
|
||||
|
||||
### 1. 牌位详情接口
|
||||
```javascript
|
||||
GET /app/memorial/{id}
|
||||
```
|
||||
|
||||
**响应数据结构:**
|
||||
```json
|
||||
{
|
||||
"msg": "操作成功",
|
||||
"code": 200,
|
||||
"data": {
|
||||
"id": "16",
|
||||
"name": "牌位名字",
|
||||
"code": "A01",
|
||||
"introduced": "牌位介绍信息",
|
||||
"extinguishTime": "2025-07-16 14:06:58",
|
||||
"state": "1",
|
||||
"contactName": "黄绍春",
|
||||
"address": "广西壮族自治区南宁市西乡塘区"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 供奉记录接口
|
||||
```javascript
|
||||
GET /app/enshrined/list?memorialId={id}&pageNum=1&pageSize=10
|
||||
```
|
||||
|
||||
**响应数据结构:**
|
||||
```json
|
||||
{
|
||||
"total": 2,
|
||||
"rows": [
|
||||
{
|
||||
"id": "1",
|
||||
"memorialId": "16",
|
||||
"worshiperName": "黄绍春",
|
||||
"thaliName": "贡献三天",
|
||||
"startDate": "2025-07-08 00:00:00",
|
||||
"endDate": "2025-07-31 00:00:00",
|
||||
"isShow": "1"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 1. 页面跳转
|
||||
```javascript
|
||||
// 跳转到供奉记录页面
|
||||
uni.navigateTo({
|
||||
url: '/pages/memorial/enshrinedList?id=16'
|
||||
})
|
||||
```
|
||||
|
||||
### 2. 参数说明
|
||||
- `id`: 牌位ID,必填参数
|
||||
|
||||
### 3. 测试页面
|
||||
访问 `/pages/memorial/test-enshrined` 可以测试API调用和页面功能。
|
||||
|
||||
## 文件结构
|
||||
|
||||
```
|
||||
pages/memorial/
|
||||
├── enshrinedList.vue # 主页面
|
||||
├── test-enshrined.vue # 测试页面
|
||||
└── README.md # 说明文档
|
||||
|
||||
api/memorial/
|
||||
└── memorial.js # API接口定义
|
||||
```
|
||||
|
||||
## 样式定制
|
||||
|
||||
### 颜色主题
|
||||
- 主色调: `#A24242` (深红棕色)
|
||||
- 背景色: `#F5F0E7` (米色)
|
||||
- 卡片背景: `#FFF1DD` (浅米色)
|
||||
- 文字颜色: `#522510` (深棕色)
|
||||
|
||||
### 布局调整
|
||||
可以通过修改CSS变量来调整页面样式:
|
||||
```scss
|
||||
// 修改主色调
|
||||
$primary-color: #A24242;
|
||||
$background-color: #F5F0E7;
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **网络请求**: 确保API接口可正常访问
|
||||
2. **参数验证**: 传入的牌位ID必须有效
|
||||
3. **数据格式**: API返回的数据格式必须符合预期
|
||||
4. **错误处理**: 网络错误时会显示重试按钮
|
||||
5. **性能优化**: 大量数据时建议调整分页大小
|
||||
|
||||
## 更新日志
|
||||
|
||||
- **v1.0.0**: 初始版本,支持基本的供奉记录展示
|
||||
- **v1.1.0**: 添加下拉刷新和上拉加载功能
|
||||
- **v1.2.0**: 优化UI设计和错误处理
|
||||
298
pages/memorial/compositons/offeringModal.vue
Normal file
298
pages/memorial/compositons/offeringModal.vue
Normal file
|
|
@ -0,0 +1,298 @@
|
|||
<template>
|
||||
<view class="offering-modal" v-if="visible" @click="handleClose">
|
||||
<view class="modal-overlay" @click="handleClose"></view>
|
||||
<view class="modal-content" @click.stop>
|
||||
<!-- 关闭按钮 -->
|
||||
<view class="close-btn" @click="handleClose">
|
||||
<text class="close-icon">×</text>
|
||||
</view>
|
||||
|
||||
<!-- 标题 -->
|
||||
<view class="modal-title">牌位供奉</view>
|
||||
|
||||
<!-- 供奉时长选择 -->
|
||||
<view class="duration-section">
|
||||
<view class="duration-grid">
|
||||
<view
|
||||
v-for="option in durationOptions"
|
||||
:key="option.value"
|
||||
class="duration-option"
|
||||
:class="{ 'selected': selectedDuration === option.value }"
|
||||
@click="selectDuration(option.value)"
|
||||
>
|
||||
<text class="duration-text">{{ option.label }}</text>
|
||||
<text class="duration-price">¥{{ option.price }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 供奉人信息 -->
|
||||
<view class="offerer-section">
|
||||
<view class="section-label">供奉人</view>
|
||||
<input
|
||||
class="offerer-input"
|
||||
placeholder="请填写供奉人姓名"
|
||||
v-model="offererName"
|
||||
maxlength="20"
|
||||
/>
|
||||
</view>
|
||||
<view class="input-tip">将在供奉名单上展现供奉人的姓名,此为必填</view>
|
||||
|
||||
<!-- 确认按钮 -->
|
||||
<view class="confirm-section">
|
||||
<view class="price-info">
|
||||
<text class="total-price">¥{{ totalPrice }}</text>
|
||||
</view>
|
||||
<view class="confirm-btn" @click="handleConfirm">
|
||||
<text class="btn-text">立即供奉</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'OfferingModal',
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedDuration: '3', // 默认选择3天
|
||||
offererName: '',
|
||||
durationOptions: [
|
||||
{ label: '供奉3天', value: '3', price: '99.9' },
|
||||
{ label: '供奉1周', value: '7', price: '129.9' },
|
||||
{ label: '供奉1月', value: '30', price: '299.9' },
|
||||
{ label: '供奉1年', value: '365', price: '499.9' }
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
totalPrice() {
|
||||
const selectedOption = this.durationOptions.find(option => option.value === this.selectedDuration)
|
||||
if (!selectedOption) return '99.9'
|
||||
|
||||
// 根据设计图,显示的价格可能需要调整
|
||||
// 这里可以根据实际需求调整价格计算逻辑
|
||||
return selectedOption.price
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 关闭弹窗
|
||||
handleClose() {
|
||||
this.$emit('close')
|
||||
},
|
||||
|
||||
// 选择供奉时长
|
||||
selectDuration(value) {
|
||||
this.selectedDuration = value
|
||||
},
|
||||
|
||||
// 确认供奉
|
||||
handleConfirm() {
|
||||
// 验证供奉人姓名
|
||||
if (!this.offererName.trim()) {
|
||||
uni.showToast({
|
||||
title: '请填写供奉人姓名',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 获取选中的时长选项
|
||||
const selectedOption = this.durationOptions.find(option => option.value === this.selectedDuration)
|
||||
|
||||
// 触发确认事件
|
||||
this.$emit('confirm', {
|
||||
duration: this.selectedDuration,
|
||||
durationLabel: selectedOption.label,
|
||||
price: selectedOption.price,
|
||||
offererName: this.offererName.trim()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.offering-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.modal-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
background: #FFFBF5;
|
||||
border-radius: 24rpx 24rpx 0 0;
|
||||
padding: 40rpx 32rpx 60rpx 32rpx;
|
||||
box-sizing: border-box;
|
||||
max-height: 80vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
right: 20rpx;
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.close-icon {
|
||||
font-size: 40rpx;
|
||||
color: #999;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
|
||||
color: #695347;
|
||||
text-align: left;
|
||||
margin-bottom: 40rpx;
|
||||
padding-top: 20rpx;
|
||||
font-weight: 400;
|
||||
font-size: 32rpx;
|
||||
line-height: 44rpx;
|
||||
}
|
||||
|
||||
.duration-section {
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.duration-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.duration-option {
|
||||
background: #FFF1DD;
|
||||
border-radius: 12rpx;
|
||||
padding: 24rpx 20rpx;
|
||||
text-align: center;
|
||||
border: 2rpx solid transparent;
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
|
||||
&.selected {
|
||||
background: #A24242;
|
||||
border-color: #A24242;
|
||||
|
||||
.duration-text,
|
||||
.duration-price {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.duration-text {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
color: #C7A26D;
|
||||
margin-bottom: 8rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.duration-price {
|
||||
display: block;
|
||||
font-size: 32rpx;
|
||||
color: #C7A26D;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.offerer-section {
|
||||
display: flex;
|
||||
margin-bottom: 40rpx;
|
||||
align-items: center;
|
||||
width: 686rpx;
|
||||
height: 112rpx;
|
||||
border-radius: 16rpx 16rpx 16rpx 16rpx;
|
||||
border: 2rpx solid #A24242;
|
||||
}
|
||||
|
||||
.section-label {
|
||||
|
||||
font-size: 32rpx;
|
||||
color: #522510;
|
||||
font-weight: 500;
|
||||
margin:34rpx 70rpx 34rpx 54rpx;
|
||||
width: 196rpx;
|
||||
}
|
||||
|
||||
.offerer-input {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 28rpx;
|
||||
color: #ACACAC;
|
||||
box-sizing: border-box;
|
||||
margin:34rpx 0 34rpx 0;
|
||||
}
|
||||
|
||||
.input-tip {
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #695347;
|
||||
line-height: 38rpx;
|
||||
text-align: center;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.confirm-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx 32rpx;
|
||||
width: 648rpx;
|
||||
height: 90rpx;
|
||||
background: #A24242;
|
||||
border-radius: 45rpx 45rpx 45rpx 45rpx;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.price-info {
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.total-price {
|
||||
font-size: 36rpx;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
flex: 1;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.btn-text {
|
||||
font-size: 32rpx;
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
||||
161
pages/memorial/deceasedSearch.vue
Normal file
161
pages/memorial/deceasedSearch.vue
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
<template>
|
||||
<view class="page">
|
||||
<base-background />
|
||||
<!-- 使用自定义导航栏组件 -->
|
||||
<custom-navbar
|
||||
ref="customNavbar"
|
||||
title="供奉记录"/>
|
||||
<view class="container">
|
||||
<!-- 状态展示 -->
|
||||
<status-display
|
||||
v-if="loading"
|
||||
type="loading"
|
||||
loading-text="加载中..."
|
||||
/>
|
||||
<!-- 搜索框 -->
|
||||
<search-box
|
||||
v-model="searchName"
|
||||
:width="'682rpx'"
|
||||
:search-icon="CommonEnum.SEARCH"
|
||||
placeholder="请输入姓名进行查找"
|
||||
btn-text="搜索"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<view class="body">
|
||||
<view class="center-files">
|
||||
<image :src="CommonEnum.CENTER_TILES" mode="aspectFit" class="files"></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bottom-files">
|
||||
<image :src="CommonEnum.BOTTOM_TILES_2" mode="aspectFit" class="files"></image>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {CommonEnum} from '@/enum/common.js'
|
||||
import SearchBox from "../../components/search-box/search-box.vue"
|
||||
import StatusDisplay from "../../components/status-display/status-display.vue"
|
||||
import EnshrinedList from "./compositons/enshrinedList.vue"
|
||||
import FloorSelector from "./compositons/floorSelector.vue"
|
||||
import StatusBar from "./compositons/statusBar.vue"
|
||||
import BottomButton from "../../components/bottom-button/bottom-button.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
BottomButton,
|
||||
SearchBox,
|
||||
StatusDisplay,
|
||||
EnshrinedList,
|
||||
FloorSelector,
|
||||
StatusBar
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
CommonEnum,
|
||||
searchName: '',
|
||||
loading: false,
|
||||
memorialId: '16', // 默认往生殿ID,可以从路由参数获取
|
||||
// 楼层选择器默认值
|
||||
defaultFloorId: '',
|
||||
defaultAreaId: '',
|
||||
defaultUnitId: '',
|
||||
// 当前选中的楼层信息
|
||||
currentSelection: {
|
||||
floor: null,
|
||||
area: null,
|
||||
unit: null
|
||||
},
|
||||
// 当前选中的单元ID,用于状态栏查询
|
||||
selectedUnitId: ''
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
// 从路由参数获取往生殿ID
|
||||
if (options.id) {
|
||||
this.memorialId = options.id
|
||||
}
|
||||
this.initPage()
|
||||
},
|
||||
methods: {
|
||||
// 初始化页面
|
||||
async initPage() {
|
||||
this.loading = true
|
||||
try {
|
||||
// 页面初始化逻辑
|
||||
console.log('往生殿页面初始化,ID:', this.memorialId)
|
||||
} catch (error) {
|
||||
console.error('页面初始化失败:', error)
|
||||
uni.showToast({
|
||||
title: '页面加载失败',
|
||||
icon: 'none'
|
||||
})
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
|
||||
// 处理搜索
|
||||
handleSearch(value) {
|
||||
console.log('搜索内容:', value)
|
||||
this.searchName = value
|
||||
// 搜索逻辑由 enshrinedList 组件处理
|
||||
},
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page {
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
//min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
padding-bottom: 180rpx;
|
||||
box-sizing: border-box;
|
||||
.body{
|
||||
position: relative;
|
||||
height:1100rpx;
|
||||
left: 0;
|
||||
top: 18rpx;
|
||||
background: #fff;
|
||||
.center-files {
|
||||
position: relative;
|
||||
width: 100%; // 确保占满宽度
|
||||
z-index: 10; // 防止被内容覆盖
|
||||
.files {
|
||||
width: 750rpx; // 图片宽度适配容器
|
||||
height: 47rpx; // 根据设计图调整高度
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.bottom-files {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%; // 确保占满宽度
|
||||
z-index: 10; // 防止被内容覆盖
|
||||
background-color: #ffffff;
|
||||
.files {
|
||||
width: 750rpx; // 图片宽度适配容器
|
||||
height: 90rpx; // 根据设计图调整高度
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
387
pages/memorial/enshrinedList.vue
Normal file
387
pages/memorial/enshrinedList.vue
Normal file
|
|
@ -0,0 +1,387 @@
|
|||
<template>
|
||||
<view class="page">
|
||||
<base-background />
|
||||
<!-- 使用自定义导航栏组件 -->
|
||||
<custom-navbar title="供奉记录" ref="customNavbar"/>
|
||||
|
||||
<view class="header">
|
||||
<!-- 状态展示 -->
|
||||
<status-display
|
||||
v-if="loading"
|
||||
type="loading"
|
||||
loading-text="加载中..."
|
||||
/>
|
||||
|
||||
<!-- 错误状态 -->
|
||||
<status-display
|
||||
v-if="error"
|
||||
type="error"
|
||||
:error-text="error"
|
||||
@retry="fetchData"
|
||||
/>
|
||||
|
||||
<!-- 页面内容 -->
|
||||
<view v-if="!loading && !error" class="content">
|
||||
<!-- 牌位信息卡片 -->
|
||||
<view class="memorial-card">
|
||||
<view class="memorial-info">
|
||||
<view class="info-row">
|
||||
<text class="label">{{ memorialData.name || '暂无' }}</text>
|
||||
<text class="value">{{ memorialData.code || '暂无' }}</text>
|
||||
</view>
|
||||
<view class="memorial-desc" v-if="memorialData.introduced">
|
||||
{{ memorialData.introduced }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 供奉记录列表 -->
|
||||
<view class="records-section">
|
||||
|
||||
|
||||
<!-- 表头 -->
|
||||
<view class="table-header">
|
||||
<view class="header-cell">供奉人</view>
|
||||
<view class="header-cell">供奉时间</view>
|
||||
<view class="header-cell">结束时间</view>
|
||||
<view class="header-cell">供奉类型</view>
|
||||
</view>
|
||||
|
||||
<!-- 记录列表 -->
|
||||
<view class="records-list">
|
||||
<view
|
||||
v-for="(record, index) in enshrinedList"
|
||||
:key="record.id"
|
||||
class="record-item"
|
||||
>
|
||||
<view class="record-cell">
|
||||
<text class="worshiper-name">{{ formatWorshiperName(record.worshiperName) }}</text>
|
||||
</view>
|
||||
<view class="record-cell">
|
||||
<text class="date-text">{{ formatDate(record.startDate) }}</text>
|
||||
</view>
|
||||
<view class="record-cell">
|
||||
<text class="date-text">{{ formatDate(record.endDate) }}</text>
|
||||
</view>
|
||||
<view class="record-cell">
|
||||
<text class="offering-type">{{ record.thaliName }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view v-if="enshrinedList.length === 0" class="empty-state">
|
||||
<text class="empty-text">暂无供奉记录</text>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多提示 -->
|
||||
<view v-if="enshrinedList.length > 0 && enshrinedList.length < total" class="load-more">
|
||||
<text class="load-more-text">上拉加载更多</text>
|
||||
</view>
|
||||
|
||||
<!-- 全部加载完成提示 -->
|
||||
<view v-if="enshrinedList.length > 0 && enshrinedList.length >= total" class="load-complete">
|
||||
<text class="load-complete-text">已加载全部记录</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getMemorialDetail, getEnshrinedList } from '@/api/memorial/memorial.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
error: '',
|
||||
memorialId: '', // 牌位ID
|
||||
memorialData: {}, // 牌位详情数据
|
||||
enshrinedList: [], // 供奉记录列表
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
total: 0
|
||||
}
|
||||
},
|
||||
|
||||
onLoad(options) {
|
||||
// 从路由参数获取牌位ID
|
||||
this.memorialId = options.id || '16'
|
||||
this.fetchData()
|
||||
},
|
||||
|
||||
// 下拉刷新
|
||||
onPullDownRefresh() {
|
||||
this.pageNum = 1
|
||||
this.fetchData().then(() => {
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
},
|
||||
|
||||
// 上拉加载更多
|
||||
onReachBottom() {
|
||||
if (this.enshrinedList.length < this.total) {
|
||||
this.pageNum++
|
||||
this.loadMoreData()
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 获取所有数据
|
||||
async fetchData() {
|
||||
this.loading = true
|
||||
this.error = ''
|
||||
|
||||
try {
|
||||
// 并行请求两个API
|
||||
const [memorialRes, enshrinedRes] = await Promise.all([
|
||||
this.fetchMemorialDetail(),
|
||||
this.fetchEnshrinedList()
|
||||
])
|
||||
|
||||
// 处理牌位详情数据
|
||||
if (memorialRes.code === 200) {
|
||||
this.memorialData = memorialRes.data || {}
|
||||
}
|
||||
|
||||
// 处理供奉记录数据
|
||||
if (enshrinedRes.code === 200) {
|
||||
this.enshrinedList = enshrinedRes.rows || []
|
||||
this.total = enshrinedRes.total || 0
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('获取数据失败:', error)
|
||||
this.error = '网络错误,请重试'
|
||||
uni.showToast({
|
||||
title: '获取数据失败',
|
||||
icon: 'none'
|
||||
})
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
|
||||
// 获取牌位详情
|
||||
async fetchMemorialDetail() {
|
||||
return await getMemorialDetail(this.memorialId)
|
||||
},
|
||||
|
||||
// 获取供奉记录列表
|
||||
async fetchEnshrinedList() {
|
||||
const params = {
|
||||
memorialId: this.memorialId,
|
||||
pageNum: this.pageNum,
|
||||
pageSize: this.pageSize
|
||||
}
|
||||
return await getEnshrinedList(params)
|
||||
},
|
||||
|
||||
// 加载更多数据
|
||||
async loadMoreData() {
|
||||
try {
|
||||
const res = await this.fetchEnshrinedList()
|
||||
if (res.code === 200) {
|
||||
const newRecords = res.rows || []
|
||||
this.enshrinedList = [...this.enshrinedList, ...newRecords]
|
||||
this.total = res.total || 0
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载更多数据失败:', error)
|
||||
this.pageNum-- // 回退页码
|
||||
uni.showToast({
|
||||
title: '加载失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
// 格式化供奉人姓名(脱敏处理)
|
||||
formatWorshiperName(name) {
|
||||
if (!name) return '未知'
|
||||
if (name.length <= 2) return name
|
||||
return name.charAt(0) + '*' + name.charAt(name.length - 1)
|
||||
},
|
||||
|
||||
// 格式化日期
|
||||
formatDate(dateStr) {
|
||||
if (!dateStr) return '未知'
|
||||
const date = new Date(dateStr)
|
||||
if (isNaN(date.getTime())) return '未知'
|
||||
|
||||
const year = date.getFullYear()
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
|
||||
return `${year}-${month}-${day}`
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page {
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.header {
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
padding: 0 30rpx 40rpx 30rpx;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
padding-top: 20rpx;
|
||||
}
|
||||
|
||||
// 牌位信息卡片
|
||||
.memorial-card {
|
||||
|
||||
border-radius: 16rpx;
|
||||
padding: 40rpx;
|
||||
margin-bottom: 40rpx;
|
||||
width: 680rpx;
|
||||
height: 230rpx;
|
||||
background: #FFFBF5;
|
||||
border: 1rpx solid #C7A26D;
|
||||
}
|
||||
|
||||
.memorial-info {
|
||||
.info-row {
|
||||
display: flex;
|
||||
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
.label {
|
||||
font-weight: 500;
|
||||
font-size: 40rpx;
|
||||
color: #522510;
|
||||
line-height: 54rpx;
|
||||
text-align: left;
|
||||
margin-right: 84rpx;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-weight: 500;
|
||||
font-size: 40rpx;
|
||||
color: #522510;
|
||||
line-height: 54rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.memorial-desc {
|
||||
|
||||
border-radius: 8rpx;
|
||||
font-weight: 400;
|
||||
font-size: 32rpx;
|
||||
color: #4C382E;
|
||||
line-height: 44rpx;
|
||||
letter-spacing: 2px;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
// 供奉记录区域
|
||||
.records-section {
|
||||
padding: 46rpx 43rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
background: #FFFBF5;
|
||||
border-radius: 20rpx 20rpx 20rpx 20rpx;
|
||||
border: 1rpx solid #C7A26D;
|
||||
width: 680rpx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 表头
|
||||
.table-header {
|
||||
display: flex;
|
||||
border-radius: 8rpx;
|
||||
margin-bottom: 30rpx;
|
||||
//border:1px red solid;
|
||||
align-items: center;
|
||||
|
||||
.header-cell {
|
||||
flex: 1;
|
||||
|
||||
//border:1px red solid;
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #695347;
|
||||
line-height: 38rpx;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
// 记录列表
|
||||
.records-list {
|
||||
//border:1px red solid;
|
||||
.record-item {
|
||||
//border:1px red solid;
|
||||
display: flex;
|
||||
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
|
||||
.record-cell {
|
||||
flex: 1;
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #522510;
|
||||
line-height: 32rpx;
|
||||
text-align: left;
|
||||
//border:1px red solid;
|
||||
|
||||
.worshiper-name {
|
||||
color: #522510;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.date-text {
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 空状态
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 80rpx 0;
|
||||
|
||||
.empty-text {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
// 加载更多提示
|
||||
.load-more {
|
||||
text-align: center;
|
||||
padding: 40rpx 0;
|
||||
|
||||
.load-more-text {
|
||||
font-size: 26rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
// 加载完成提示
|
||||
.load-complete {
|
||||
text-align: center;
|
||||
padding: 40rpx 0;
|
||||
|
||||
.load-complete-text {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -108,6 +108,13 @@
|
|||
/>
|
||||
</view>
|
||||
|
||||
<!-- 供奉弹窗 -->
|
||||
<OfferingModal
|
||||
:visible="showOfferingModal"
|
||||
@close="closeOfferingModal"
|
||||
@confirm="handleOfferingConfirm"
|
||||
/>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
|
@ -117,9 +124,9 @@ import { getDeceasedList, getMemorialDetail } from '@/api/memorial/index.js'
|
|||
import SearchBox from "../../components/search-box/search-box.vue"
|
||||
import StatusDisplay from "../../components/status-display/status-display.vue"
|
||||
import EnshrinedList from "./compositons/enshrinedList.vue"
|
||||
import FloorSelector from "./compositons/floorSelector.vue"
|
||||
import StatusBar from "./compositons/statusBar.vue"
|
||||
import BottomButton from "../../components/bottom-button/bottom-button.vue";
|
||||
import BottomButton from "../../components/bottom-button/bottom-button.vue"
|
||||
import OfferingModal from "./compositons/offeringModal.vue"
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
|
@ -127,24 +134,14 @@ export default {
|
|||
SearchBox,
|
||||
StatusDisplay,
|
||||
EnshrinedList,
|
||||
FloorSelector,
|
||||
StatusBar
|
||||
StatusBar,
|
||||
OfferingModal
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
CommonEnum,
|
||||
searchName: '',
|
||||
loading: false,
|
||||
// 楼层选择器默认值
|
||||
defaultFloorId: '',
|
||||
defaultAreaId: '',
|
||||
defaultUnitId: '',
|
||||
// 当前选中的楼层信息
|
||||
currentSelection: {
|
||||
floor: null,
|
||||
area: null,
|
||||
unit: null
|
||||
},
|
||||
// 当前选中的单元ID,用于状态栏查询
|
||||
selectedUnitId: '',
|
||||
// 往生者列表数据
|
||||
|
|
@ -157,7 +154,9 @@ export default {
|
|||
// 往生殿详情数据
|
||||
memorialDetail: null,
|
||||
// 滚动相关
|
||||
scrollTop: 0
|
||||
scrollTop: 0,
|
||||
// 供奉弹窗显示状态
|
||||
showOfferingModal: false
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
|
|
@ -274,8 +273,37 @@ export default {
|
|||
|
||||
// 提交供奉
|
||||
submitPrayer() {
|
||||
console.log('提交供奉')
|
||||
// 这里可以添加供奉逻辑
|
||||
console.log('显示供奉弹窗')
|
||||
this.showOfferingModal = true
|
||||
},
|
||||
|
||||
// 关闭供奉弹窗
|
||||
closeOfferingModal() {
|
||||
this.showOfferingModal = false
|
||||
},
|
||||
|
||||
// 确认供奉
|
||||
handleOfferingConfirm(offeringData) {
|
||||
console.log('确认供奉:', offeringData)
|
||||
|
||||
// 这里可以调用供奉API
|
||||
uni.showLoading({
|
||||
title: '正在提交供奉...'
|
||||
})
|
||||
|
||||
// 模拟API调用
|
||||
setTimeout(() => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: '供奉成功!',
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
// 关闭弹窗
|
||||
this.closeOfferingModal()
|
||||
|
||||
// 可以在这里刷新数据或跳转到其他页面
|
||||
}, 2000)
|
||||
},
|
||||
|
||||
// 刷新数据
|
||||
|
|
@ -479,9 +507,6 @@ export default {
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 状态栏容器样式
|
||||
:deep(.status-bar) {
|
||||
width: 100%;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user