4cf9d409 by lttnew

我的订单

1 parent e97c4b0a
...@@ -349,6 +349,14 @@ export function addSelectPageList(query) { ...@@ -349,6 +349,14 @@ export function addSelectPageList(query) {
349 }) 349 })
350 } 350 }
351 351
352 // 获取个人技术认证详情
353 export function getPersonTecDetails(type, personId) {
354 return request({
355 url: `/person/technology/getPersonTecDetails/${type}/${personId}`,
356 method: 'get'
357 })
358 }
359
352 export function fillAuditLog(ids) { 360 export function fillAuditLog(ids) {
353 return request({ 361 return request({
354 url: `/person/paymentRange/fillAuditLog/${ids}`, 362 url: `/person/paymentRange/fillAuditLog/${ids}`,
...@@ -1441,7 +1449,57 @@ export function bindUser(data) { ...@@ -1441,7 +1449,57 @@ export function bindUser(data) {
1441 1449
1442 export function unbindUser() { 1450 export function unbindUser() {
1443 return request({ 1451 return request({
1444 url: `/person/info/unbindUser`, 1452 url: `/person/info/unBindUser`,
1445 method: 'post' 1453 method: 'post'
1446 }) 1454 })
1455 }
1456 /**
1457 * 订单列表
1458 * @param params
1459 * @returns {*}
1460 */
1461 export function orderList(params) {
1462 return request({
1463 url: `/common/order/list`,
1464 method: 'get',
1465 params
1466 })
1467 }
1468
1469 /**
1470 * 删除订单
1471 * @param params
1472 * @returns {*}
1473 */
1474 export function deleteOrder(id) {
1475 return request({
1476 url: `/common/order/${id}`,
1477 method: 'delete'
1478 })
1479 }
1480 /**
1481 * 取消订单
1482 * @param params
1483 * @returns {*}
1484 */
1485 export function cancelPay(id) {
1486 return request({
1487 url: `/person/paymentRangeNew/cancelPay/${id}`,
1488 method: 'post'
1489 })
1490 }
1491
1492 export const outputInvoiceNo = (data) => {
1493 return request({
1494 url: `/common/order/outputInvoiceNo/${data.id}`,
1495 method: 'post',
1496 params: data
1497 })
1498 }
1499
1500 export function getAssoPers(perId) {
1501 return request({
1502 url: '/person/info/getRoleListByPerId/' + perId,
1503 method: 'get'
1504 })
1447 } 1505 }
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -47,6 +47,7 @@ function logout() { ...@@ -47,6 +47,7 @@ function logout() {
47 uni.removeStorageSync('token') 47 uni.removeStorageSync('token')
48 uni.removeStorageSync('userName') 48 uni.removeStorageSync('userName')
49 uni.removeStorageSync('webUserName') 49 uni.removeStorageSync('webUserName')
50 uni.removeStorageSync('openId')
50 51
51 userStore.setUser(null) 52 userStore.setUser(null)
52 app.globalData.isLogin = false 53 app.globalData.isLogin = false
......
1 // dev 1 // dev
2 const baseUrl_api = 'http://192.168.1.189:8787' 2 const baseUrl_api = 'http://192.168.1.137:8787'
3 const payUrl = 'https://wxpay.cmbc.com.cn/mobilePlatform/appserver/lcbpPay.do' 3 const payUrl = 'https://wxpay.cmbc.com.cn/mobilePlatform/appserver/lcbpPay.do'
4 4
5 // prod 5 // prod
......
1 <template> 1 <template>
2 <view class="page"> 2 <view class="page">
3 <view class="bgbg"> 3 <view class="bgbg">
4 <view class="flex"> 4 <view class="flex">
5 <view class="imgbox"> 5 <view class="imgbox">
6 <image v-if="state.user.avatar" :src="state.user.avatar"/> 6 <image v-if="state.user.avatar" :src="state.user.avatar"/>
7 <image v-else src="@/static/nodata.png"/> 7 <image v-else src="@/static/nodata.png"/>
8 </view> 8 </view>
9 <text class="name">{{ state.user.userName }}</text> 9 <text class="name">{{ state.user.userName }}</text>
10 </view> 10 </view>
11 </view> 11 </view>
12 <view class="rMainBox"> 12 <view class="rMainBox">
13 <uni-list :border="false" class="myList"> 13 <uni-list :border="false" class="myList">
14 <uni-list-item thumb="/static/user_icon01.png" title="团体信息" showArrow clickable @click="goPath('/myCenter/teamInfo')"> 14 <uni-list-item thumb="/static/user_icon01.png" title="团体信息" showArrow clickable @click="goPath('/myCenter/teamInfo')">
15 </uni-list-item> 15 </uni-list-item>
16 16
17 <uni-list-item thumb="/static/user_icon02.png" title="会员认证" showArrow clickable @click="goPath('/myCenter/auth')"> 17 <uni-list-item thumb="/static/user_icon02.png" title="会员认证" showArrow clickable @click="goPath('/myCenter/auth')">
18 </uni-list-item> 18 </uni-list-item>
19 19
20 <!-- <uni-list-item thumb="/static/user_icon03.png" v-show="userType==2" title="账户信息" showArrow clickable> 20 <!-- <uni-list-item thumb="/static/user_icon03.png" v-show="userType==2" title="账户信息" showArrow clickable>
21 </uni-list-item> --> 21 </uni-list-item> -->
22 22
23 <uni-list-item thumb="/static/user_icon03.png" title="账号安全" showArrow clickable @click="goPath('/myCenter/safe')"> 23 <uni-list-item thumb="/static/user_icon03.png" title="账号安全" showArrow clickable @click="goPath('/myCenter/safe')">
24 </uni-list-item> 24 </uni-list-item>
25 25 <uni-list-item thumb="/static/user_icon03.png" title="我的订单" showArrow clickable @click="goPath('/myCenter/order')">
26 </uni-list> 26 </uni-list-item>
27 27
28 </view> 28 </uni-list>
29 29
30 <view class="fixedBottom" style="background: transparent;box-shadow: none;"> 30 </view>
31 <button @click="loginOut" class="btn btn-red" style="border-radius: 50px;">退出登录</button> 31
32 <view class="fixedBottom" style="background: transparent;box-shadow: none;">
33 <button @click="loginOut" class="btn btn-red" style="border-radius: 50px;">退出登录</button>
32 </view> 34 </view>
33 </view> 35 </view>
34 </template> 36 </template>
...@@ -60,11 +62,11 @@ let proId; ...@@ -60,11 +62,11 @@ let proId;
60 const svId = ref(null); 62 const svId = ref(null);
61 const numData = ref({}); 63 const numData = ref({});
62 64
63 const messageList = ref([]) 65 const messageList = ref([])
64 const state = reactive({ 66 const state = reactive({
65 user: {}, 67 user: {},
66 roleGroup: {}, 68 roleGroup: {},
67 postGroup: {} 69 postGroup: {}
68 }) 70 })
69 onShow(() => { 71 onShow(() => {
70 if (app.globalData.isLogin) { 72 if (app.globalData.isLogin) {
...@@ -80,12 +82,12 @@ onLoad(option => { ...@@ -80,12 +82,12 @@ onLoad(option => {
80 proId = decodeURIComponent(option.scene); 82 proId = decodeURIComponent(option.scene);
81 } else { 83 } else {
82 proId = option.proId; 84 proId = option.proId;
83 } 85 }
84 if(uni.showShareMenu){ 86 if(uni.showShareMenu){
85 uni.showShareMenu({ 87 uni.showShareMenu({
86 withShareTicket: true, 88 withShareTicket: true,
87 menus: ['shareAppMessage', 'shareTimeline'] 89 menus: ['shareAppMessage', 'shareTimeline']
88 }); 90 });
89 } 91 }
90 }); 92 });
91 93
...@@ -104,21 +106,21 @@ function loginOut() { ...@@ -104,21 +106,21 @@ function loginOut() {
104 } 106 }
105 }) 107 })
106 } 108 }
107 function getUser() { 109 function getUser() {
108 api.getUserProfile().then((response) => { 110 api.getUserProfile().then((response) => {
109 state.user = response.data.user 111 state.user = response.data.user
110 if(state.user.avatar&&state.user.avatar.indexOf('http')==-1){ 112 if(state.user.avatar&&state.user.avatar.indexOf('http')==-1){
111 state.user.avatar = config.baseUrl_api+state.user.avatar 113 state.user.avatar = config.baseUrl_api+state.user.avatar
112 } 114 }
113 state.roleGroup = response.data.roleGroup 115 state.roleGroup = response.data.roleGroup
114 state.postGroup = response.data.postGroup 116 state.postGroup = response.data.postGroup
115 uni.hideLoading(); 117 uni.hideLoading();
116 }) 118 })
117 } 119 }
118 function init() { 120 function init() {
119 uni.showLoading({ 121 uni.showLoading({
120 title: '加载中' 122 title: '加载中'
121 }); 123 });
122 getUser() 124 getUser()
123 loginServer.getMyOwnMemberInfo().then(res => { 125 loginServer.getMyOwnMemberInfo().then(res => {
124 userType.value = app.globalData.userType 126 userType.value = app.globalData.userType
...@@ -126,31 +128,31 @@ function init() { ...@@ -126,31 +128,31 @@ function init() {
126 uni.hideLoading(); 128 uni.hideLoading();
127 }) 129 })
128 } 130 }
129 function goPath(url){ 131 function goPath(url){
130 uni.navigateTo({ 132 uni.navigateTo({
131 url:url 133 url:url
132 }) 134 })
133 } 135 }
134 136
135 </script> 137 </script>
136 <style scope lang="scss"> 138 <style scope lang="scss">
137 .uni-list:after{display: none;} 139 .uni-list:after{display: none;}
138 .page { 140 .page {
139 width: 100vw; 141 width: 100vw;
140 overflow: hidden; 142 overflow: hidden;
141 } 143 }
142 .bgbg{ 144 .bgbg{
143 .flex{align-items: center;} 145 .flex{align-items: center;}
144 height: 280rpx;padding:30rpx; 146 height: 280rpx;padding:30rpx;
145 .name{margin-left: 20rpx; 147 .name{margin-left: 20rpx;
146 font-size: 36rpx;} 148 font-size: 36rpx;}
147 .imgbox{width: 120rpx; 149 .imgbox{width: 120rpx;
148 height: 120rpx;overflow: hidden; 150 height: 120rpx;overflow: hidden;
149 // background: #C7C7CD; 151 // background: #C7C7CD;
150 // border: 4rpx solid #FFFFFF; 152 // border: 4rpx solid #FFFFFF;
151 border-radius: 50%; 153 border-radius: 50%;
152 image{height: 120rpx;width: 120rpx;object-fit: cover;} 154 image{height: 120rpx;width: 120rpx;object-fit: cover;}
153 } 155 }
154 } 156 }
155 .loginOutIcon { 157 .loginOutIcon {
156 position: relative; 158 position: relative;
...@@ -219,11 +221,11 @@ function goPath(url){ ...@@ -219,11 +221,11 @@ function goPath(url){
219 margin: 30rpx 0 20rpx; 221 margin: 30rpx 0 20rpx;
220 padding: 0 20rpx 0; 222 padding: 0 20rpx 0;
221 } 223 }
222 } 224 }
223 .rMainBox {position: relative;top:-120rpx; 225 .rMainBox {position: relative;top:-120rpx;
224 box-sizing: border-box;padding: 20rpx 20rpx; 226 box-sizing: border-box;padding: 20rpx 20rpx;
225 background-color: #fff; 227 background-color: #fff;
226 border-radius: 15rpx; 228 border-radius: 15rpx;
227 margin: 25rpx;overflow: hidden; 229 margin: 25rpx;overflow: hidden;
228 } 230 }
229 </style> 231 </style>
...\ No newline at end of file ...\ No newline at end of file
......
1 <template>
2 <view class="order-page" :class="{ 'no-scroll': isPopupOpen }">
3 <!-- 顶部标签栏 -->
4 <view class="tab-bar">
5 <view
6 v-for="(tab, index) in tabs"
7 :key="index"
8 class="tab-item"
9 :class="{ active: currentTab === index }"
10 @click="switchTab(index)"
11 >
12 {{ tab.name }}
13 </view>
14 </view>
15
16 <!-- 订单列表 -->
17 <scroll-view
18 scroll-y
19 class="order-list-scroll"
20 :enhanced="true"
21 :show-scrollbar="false"
22 :scroll-enabled="!isPopupOpen"
23 >
24 <view class="order-list">
25 <!-- 有数据才循环 -->
26 <view v-if="list.length > 0">
27 <view
28 v-for="(item, index) in list"
29 :key="index"
30 class="order-card"
31 >
32 <!-- 订单头部:日期 + 状态 -->
33 <view class="card-header">
34 <view class="date">
35 <image src="/static/calendar@2x.png" v-if="item.payTime" mode="widthFix" style="width:30rpx;height:30rpx;"/>
36 <text class="date-text" v-if="item.payTime">{{ item.payTime }}</text>
37 </view>
38 <view
39 class="status-tag"
40 :class="{
41 success: item.payStatus == 1,
42 danger: item.payStatus == 2,
43 pending: item.payStatus == 0
44 }"
45 >
46 {{ getStatusText(item.payStatus) }}
47 </view>
48 </view>
49
50 <!-- 订单编号、缴费编号 -->
51 <view class="info-row">
52 <text class="label">订单编号:</text>
53 <text class="value">{{ item.tradeNo || '——' }}</text>
54 </view>
55 <view class="info-row">
56 <text class="label">缴费编号:</text>
57 <text class="value">{{ item.wfCode || '——' }}</text>
58 </view>
59
60 <!-- 核心:前2tab仅展示缴费年限,后2tab仅展示人数合计 -->
61 <view class="info-section flex f-j-s" v-if="item.content">
62 <!-- 个人/单位会员(仅缴费年限) -->
63 <view v-if="currentTab === 0 || currentTab === 1" class="single-info">
64 <view class="label">缴费年限:</view>
65 <view class="value">{{ item.content.yearCount || 0 }}</view>
66 </view>
67 <view class="line"></view>
68 <!-- 级位/段位考试(仅人数合计) -->
69 <view v-if="currentTab === 2 || currentTab === 3" class="single-info">
70 <view class="label">人数合计</view>
71 <view class="value">{{ item.content.allPersonCount || 0 }}</view>
72 </view>
73 <view class="single-info">
74 <view class="label">缴费方式</view>
75 <view class="value">民生付</view>
76 </view>
77 </view>
78
79 <!-- 费用合计 -->
80 <view class="total-row">
81 <text class="label">费用合计:</text>
82 <text class="amount">¥{{ (Number(item.price) || 0).toFixed(2) }}</text>
83 </view>
84
85 <!-- 按钮组:靠右紧凑展示 -->
86 <view class="btn-group">
87 <button class="btn btn-delete" @click="handleDelete(item)">删除</button>
88 <!-- 已缴费:申请开票/已开票 -->
89 <template v-if="item.payStatus == 1">
90 <button class="btn btn-invoice" @click="makeInvoiceFN(item)" :disabled="item.invoiceStatus === 1">
91 {{ item.invoiceStatus === 1 ? '已开票' : '申请开票' }}
92 </button>
93 </template>
94 <!-- 未缴费:去缴费 + 取消订单 -->
95 <template v-if="item.payStatus == 0">
96 <button class="btn btn-cancel" @click="handleCancel(item)">取消订单</button>
97 <button class="btn btn-pay" @click="handlePay(item)">去缴费</button>
98 </template>
99 </view>
100 </view>
101 </view>
102
103 <!-- 空状态 -->
104 <view v-else class="empty">
105 <text class="empty-text">暂无订单记录</text>
106 </view>
107
108 <!-- 加载/无更多提示 -->
109 <view class="loading-tip" v-if="loading">加载中...</view>
110 <view class="no-more" v-if="!loading && !hasMore && list.length">没有更多了</view>
111 </view>
112 </scroll-view>
113
114 <!-- 自定义删除确认弹窗 -->
115 <view v-if="showDelPopup" class="popup-mask" @touchmove.stop.prevent @click.stop="closeDelPopup">
116 <view class="custom-modal" @click.stop>
117 <view class="modal-title">提示</view>
118 <view class="modal-content">{{ delModalContent }}</view>
119 <view class="modal-btns">
120 <button class="modal-btn-cancel" @click="closeDelPopup">取消</button>
121 <button class="modal-btn-confirm" @click="confirmDel">确定</button>
122 </view>
123 </view>
124 </view>
125
126 <!-- 自定义取消订单确认弹窗 -->
127 <view v-if="showCancelPopup" class="popup-mask" @touchmove.stop.prevent @click.stop="closeCancelPopup">
128 <view class="custom-modal" @click.stop>
129 <view class="modal-title">提示</view>
130 <view class="modal-content">{{ cancelModalContent }}</view>
131 <view class="modal-btns">
132 <button class="modal-btn-cancel" @click="closeCancelPopup">取消</button>
133 <button class="modal-btn-confirm" @click="confirmCancel">确定</button>
134 </view>
135 </view>
136 </view>
137 </view>
138 </template>
139
140 <script setup>
141 import { ref, reactive, onMounted, computed } from 'vue';
142 import { onReachBottom, } from '@dcloudio/uni-app'
143 import * as api from '@/common/api.js'
144
145 // 获取deptType值(初始值为0,在onMounted中设置实际值)
146 const deptType = ref(0);
147
148
149 // 标签栏配置(根据deptType动态生成)
150 const tabs = computed(() => {
151 const dt = Number(deptType.value)
152 console.log('tabs computed, deptType:', deptType.value, 'dt:', dt, 'dt===6:', dt === 6, 'dt==6:', dt == 6);
153
154 if (dt === 6) {
155 console.log('返回3个tab: 个人会员、单位会员、级位考试');
156 return [
157 { name: '个人会员', type: '0' },
158 { name: '单位会员', type: '1' },
159 { name: '级位考试', type: '2' }
160 ];
161 } else if (dt === 2) {
162 console.log('返回3个tab: 单位会员、段位考试、越段考试');
163 return [
164 { name: '单位会员', type: '1' },
165 { name: '段位考试', type: '3' },
166 { name: '越段考试', type: '4' }
167 ];
168 } else {
169 console.log('返回默认5个tab, dt值为:', dt);
170 return [
171 { name: '个人会员', type: '0' },
172 { name: '单位会员', type: '1' },
173 { name: '级位考试', type: '2' },
174 { name: '段位考试', type: '3' },
175 { name: '越段考试', type: '4' }
176 ];
177 }
178 });
179 const currentTab = ref(0);
180
181 // 数据与分页配置
182 const list = ref([]);
183 const loading = ref(false);
184 const hasMore = ref(true);
185 const pageNum = ref(1);
186 const pageSize = ref(10);
187
188 // 查询参数
189 const queryParams = reactive({
190 pageNum: 1,
191 pageSize: 10,
192 type: '0',
193 queryType: '1',
194 // payStatus: ''
195 });
196
197 // 弹窗控制
198 const showDelPopup = ref(false);
199 const showCancelPopup = ref(false);
200 const isPopupOpen = ref(false);
201
202 // 弹窗内容
203 const delModalContent = ref('');
204 const cancelModalContent = ref('');
205
206 // 当前操作的订单
207 const currentOrder = ref(null);
208
209 // 页面挂载初始化
210 onMounted(() => {
211 // 获取app实例和deptType
212 const app = getApp();
213 console.log('onMounted - app:', app);
214 console.log('onMounted - app.globalData:', app.globalData);
215 deptType.value = Number(app.globalData?.deptType || 0);
216 console.log('onMounted - deptType.value:', deptType.value, typeof deptType.value);
217 initData();
218 });
219
220 // 小程序原生触底加载
221 onReachBottom(() => {
222 if (!loading.value && hasMore.value && !isPopupOpen.value) {
223 pageNum.value++;
224 initData();
225 }
226 });
227
228 // 切换标签
229 const switchTab = (index) => {
230 currentTab.value = index;
231 queryParams.type = tabs.value[index].type;
232 pageNum.value = 1;
233 list.value = [];
234 hasMore.value = true;
235 initData();
236 };
237
238 // 状态文本映射
239 const getStatusText = (status) => {
240 const map = {
241 0: '待缴费',
242 1: '缴费成功',
243 2: '订单取消'
244 };
245 return map[status] || '未知状态';
246 };
247
248 // 数据请求核心方法
249 const initData = async () => {
250 loading.value = true;
251 queryParams.pageNum = pageNum.value;
252
253 try {
254 const res = await api.orderList(queryParams);
255 if (!res || !res.rows) {
256 list.value = [];
257 hasMore.value = false;
258 return;
259 }
260 // 安全解析content字段
261 res.rows.forEach(item => {
262 if (item.content) {
263 try {
264 item.content = JSON.parse(item.content);
265 } catch (e) {
266 item.content = null;
267 }
268 }
269 });
270 // 分页拼接数据
271 if (pageNum.value === 1) {
272 list.value = res.rows;
273 } else {
274 list.value.push(...res.rows);
275 }
276 // 判断是否还有更多数据
277 hasMore.value = list.value.length < (res.total || 0);
278 } catch (e) {
279 console.error('订单加载异常:', e);
280 uni.showToast({ title: '加载失败', icon: 'none' });
281 } finally {
282 loading.value = false;
283 }
284 };
285
286 // 删除订单
287 const handleDelete = (item) => {
288 currentOrder.value = item;
289 delModalContent.value = `是否确认删除订单编号为"${item.tradeNo}"的订单?`;
290 showDelPopup.value = true;
291 isPopupOpen.value = true;
292 };
293
294 // 确认删除
295 const confirmDel = async () => {
296 if (!currentOrder.value) return;
297 try {
298 await api.deleteOrder(currentOrder.value.id);
299 uni.showToast({ title: '删除成功', icon: 'success' });
300 pageNum.value = 1;
301 list.value = [];
302 initData();
303 closeDelPopup();
304 } catch (e) {
305 uni.showToast({ title: '删除失败', icon: 'error' });
306 }
307 };
308
309 // 关闭删除弹窗
310 const closeDelPopup = () => {
311 showDelPopup.value = false;
312 isPopupOpen.value = false;
313 currentOrder.value = null;
314 };
315
316 // 去缴费
317 const handlePay = async (item) => {
318 if (item.payStatus !== 0) return;
319 try {
320 await api.goPay({ id: item.id });
321 uni.navigateTo({ url: `/pages/pay/pay?orderId=${item.id}` });
322 } catch (e) {
323 uni.showToast({ title: '发起支付失败', icon: 'none' });
324 }
325 };
326
327 // 申请开票
328 const makeInvoiceFN = (item) => {
329 // if (item.payStatus !== 1 || item.invoiceStatus === 1) return;
330 uni.navigateTo({ url: `/pages/invoice/apply?orderId=${item.id}amount=${item.price}` });
331 };
332
333 // 取消订单
334 const handleCancel = (item) => {
335 currentOrder.value = item;
336 cancelModalContent.value = `是否确认取消订单编号为"${item.tradeNo}"的订单?`;
337 showCancelPopup.value = true;
338 isPopupOpen.value = true;
339 };
340
341 // 确认取消订单
342 const confirmCancel = async () => {
343 if (!currentOrder.value) return;
344 try {
345 await api.cancelPay(currentOrder.value.id);
346 uni.showToast({ title: '取消成功', icon: 'success' });
347 pageNum.value = 1;
348 list.value = [];
349 initData();
350 closeCancelPopup();
351 } catch (e) {
352 uni.showToast({ title: '取消失败', icon: 'error' });
353 }
354 };
355
356 // 关闭取消订单弹窗
357 const closeCancelPopup = () => {
358 showCancelPopup.value = false;
359 isPopupOpen.value = false;
360 currentOrder.value = null;
361 };
362 </script>
363
364 <style lang="scss" scoped>
365 .order-page {
366 background: #f5f7fa;
367 min-height: 100vh;
368 display: flex;
369 flex-direction: column;
370
371 &.no-scroll {
372 overflow: hidden;
373 height: 100vh;
374 }
375 }
376
377 // 标签栏样式
378 .tab-bar {
379 display: flex;
380 background: #fff;
381 border-bottom: 1rpx solid #eee;
382 flex-shrink: 0;
383
384 .tab-item {
385 flex: 1;
386 text-align: center;
387 padding: 24rpx 0;
388 font-size: 28rpx;
389 color: #666;
390 position: relative;
391
392 &.active {
393 color: #e4393c;
394 font-weight: 500;
395
396 &::after {
397 content: '';
398 position: absolute;
399 bottom: 0;
400 left: 50%;
401 transform: translateX(-50%);
402 width: 60rpx;
403 height: 4rpx;
404 background: linear-gradient(90deg, #FF755A, #F51722);
405 border-radius: 2rpx;
406 }
407 }
408 }
409 }
410
411 // 滚动列表容器
412 .order-list-scroll {
413 flex: 1;
414 height: 0;
415 }
416
417 // 订单列表
418 .order-list {
419 padding: 20rpx;
420
421 .order-card {
422 background: #fff;
423 margin-bottom: 20rpx;
424 padding: 20rpx;
425 box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
426 border-top: 6rpx solid transparent;
427 background-clip: padding-box, border-box;
428 background-origin: padding-box, border-box;
429 background-image: linear-gradient(#fff, #fff), linear-gradient(90deg, #FF755A, #F51722);
430 }
431 }
432
433 // 卡片头部
434 .card-header {
435 display: flex;
436 justify-content: space-between;
437 align-items: center;
438 padding-bottom: 20rpx;
439 margin-bottom: 20rpx;
440 border-bottom: 1rpx dashed #eee;
441
442 .date {
443 display: flex;
444 align-items: center;
445 gap: 8rpx;
446 font-size: 26rpx;
447
448 .date-text {
449 color: #666;
450 }
451 }
452
453 .status-tag {
454 font-size: 24rpx;
455 padding: 6rpx 16rpx;
456 border-radius: 20rpx;
457
458 &.success {
459 background: #e6f7ef;
460 color: #52c41a;
461 }
462
463 &.danger {
464 background: #fff1f0;
465 color: #ff4d4f;
466 }
467
468 &.pending {
469 background: #f5f5f5;
470 color: #999;
471 }
472 }
473 }
474
475 // 基础信息行
476 .info-row {
477 display: flex;
478 align-items: center;
479 margin-bottom: 20rpx;
480 font-size: 26rpx;
481
482 .label {
483 color: #999;
484 flex-shrink: 0;
485 width: 140rpx;
486 }
487
488 .value {
489 color: #333;
490 word-break: break-all;
491 }
492 }
493
494 .info-section {
495 background: #f3f6fc;
496 display: flex;
497 align-items: center;
498 padding: 0 40rpx;
499 justify-content: space-around;
500 margin: 20rpx 0;
501 }
502 .line{
503 width: 1rpx;
504 height: 90%;
505 background: #eee;
506 }
507 .single-info {
508 padding: 16rpx 20rpx;
509 border-radius: 8rpx;
510 font-size: 26rpx;
511 // border-right: 1rpx solid #eee;
512 .label {
513 color: #999;
514 text-align: center;
515 }
516
517 .value {
518 color: #333;
519 font-weight: 500;
520 text-align: center;
521 margin-top: 10rpx;
522 }
523 }
524
525 // 费用合计
526 .total-row {
527 display: flex;
528 justify-content: space-between;
529 align-items: center;
530 margin: 0 0 30rpx;
531 padding: 15rpx 0;
532 font-size: 28rpx;
533 border-bottom: 1rpx dashed #eee;
534
535 .label {
536 color: #333;
537 }
538
539 .amount {
540 color: #EB6100;
541 font-weight: 600;
542 font-size: 32rpx;
543 }
544 }
545
546 // 按钮组
547 .btn-group {
548 display: flex;
549 justify-content: flex-end;
550 align-items: center;
551 gap: 16rpx;
552 width: 100%;
553
554 .btn {
555 padding: 12rpx 32rpx;
556 border-radius: 40rpx;
557 font-size: 24rpx;
558 line-height: 1.5;
559 white-space: nowrap;
560 display: inline-block;
561 margin: 0;
562 border: none;
563 width: 80px;
564 background: transparent;
565
566 &::after {
567 border: none;
568 }
569
570 &.btn-delete {
571 background: #fff;
572 color: #e4393c;
573 border: 1rpx solid #e4393c;
574 }
575
576 &.btn-invoice {
577 background: #fff;
578 color: #e4393c;
579 border: 1rpx solid #e4393c;
580 }
581
582 &.btn-cancel {
583 background: #fff;
584 color: #666;
585 border: 1rpx solid #ccc;
586 }
587
588 &.btn-pay {
589 background: linear-gradient(90deg, #FF755A, #F51722);
590 color: #fff;
591 border: none;
592 }
593
594 &:disabled {
595 opacity: 0.6;
596 pointer-events: none;
597 }
598 }
599 }
600
601 // 空状态
602 .empty {
603 display: flex;
604 justify-content: center;
605 align-items: center;
606 padding: 120rpx 0;
607
608 .empty-text {
609 color: #999;
610 font-size: 28rpx;
611 }
612 }
613
614 // 加载/无更多提示
615 .loading-tip, .no-more {
616 text-align: center;
617 padding: 20rpx 0;
618 color: #999;
619 font-size: 26rpx;
620 }
621
622 // 弹窗遮罩层
623 .popup-mask {
624 position: fixed;
625 top: 0;
626 left: 0;
627 right: 0;
628 bottom: 0;
629 background-color: rgba(0, 0, 0, 0.5);
630 display: flex;
631 align-items: center;
632 justify-content: center;
633 z-index: 999;
634 }
635
636 // 自定义弹窗样式
637 .custom-modal {
638 width: 600rpx;
639 background: #fff;
640 border-radius: 20rpx;
641 padding: 40rpx 30rpx;
642 box-sizing: border-box;
643 text-align: center;
644 box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.2);
645 }
646
647 .modal-title {
648 font-size: 36rpx;
649 font-weight: 600;
650 color: #333;
651 margin-bottom: 30rpx;
652 }
653
654 .modal-content {
655 font-size: 30rpx;
656 color: #666;
657 line-height: 1.6;
658 margin-bottom: 40rpx;
659 word-break: break-word;
660 }
661
662 .modal-btns {
663 display: flex;
664 justify-content: space-between;
665 gap: 20rpx;
666 }
667
668 .modal-btn-cancel {
669 flex: 1;
670 height: 80rpx;
671 line-height: 80rpx;
672 background: #f5f5f5;
673 color: #666;
674 border-radius: 40rpx;
675 font-size: 32rpx;
676 border: none;
677 margin: 0;
678 padding: 0;
679
680 &::after {
681 border: none;
682 }
683 }
684
685 .modal-btn-confirm {
686 flex: 1;
687 height: 80rpx;
688 line-height: 80rpx;
689 background: #C4121B;
690 color: #fff;
691 border-radius: 40rpx;
692 font-size: 32rpx;
693 border: none;
694 margin: 0;
695 padding: 0;
696
697 &::after {
698 border: none;
699 }
700 }
701 </style>
...\ No newline at end of file ...\ No newline at end of file
...@@ -13,11 +13,25 @@ ...@@ -13,11 +13,25 @@
13 } 13 }
14 }, 14 },
15 { 15 {
16 "path": "pages/webview/webview",
17 "style": {
18 "navigationBarTitleText": "中国跆拳道协会",
19 "enablePullDownRefresh": false
20 }
21 },
22 {
16 "path": "pages/index/msgList", 23 "path": "pages/index/msgList",
17 "style": { 24 "style": {
18 "navigationBarTitleText": "待办列表", 25 "navigationBarTitleText": "待办列表",
19 "enablePullDownRefresh": false 26 "enablePullDownRefresh": false
20 } 27 }
28 },
29 {
30 "path": "pages/invoice/apply",
31 "style": {
32 "navigationBarTitleText": "开具发票",
33 "enablePullDownRefresh": false
34 }
21 }, { 35 }, {
22 "path": "pages/rank/approval", 36 "path": "pages/rank/approval",
23 "style": { 37 "style": {
...@@ -165,12 +179,40 @@ ...@@ -165,12 +179,40 @@
165 } 179 }
166 }, 180 },
167 { 181 {
168 "path": "home", 182 "path": "home",
169 "style": { 183 "style": {
170 "navigationBarTitleText": "个人会员中心", 184 "navigationBarTitleText": "个人会员中心",
171 "enablePullDownRefresh": false 185 "enablePullDownRefresh": false
172 }
173 } 186 }
187 },
188 {
189 "path": "personInfo",
190 "style": {
191 "navigationBarTitleText": "人员信息",
192 "enablePullDownRefresh": false
193 }
194 },
195 {
196 "path": "memberInfo",
197 "style": {
198 "navigationBarTitleText": "个人会员信息",
199 "enablePullDownRefresh": false
200 }
201 },
202 {
203 "path": "levelRecord",
204 "style": {
205 "navigationBarTitleText": "级位记录",
206 "enablePullDownRefresh": false
207 }
208 },
209 {
210 "path": "order",
211 "style": {
212 "navigationBarTitleText": "我的订单",
213 "enablePullDownRefresh": false
214 }
215 }
174 ] 216 ]
175 }, 217 },
176 { 218 {
...@@ -684,6 +726,13 @@ ...@@ -684,6 +726,13 @@
684 } 726 }
685 }, 727 },
686 { 728 {
729 "path": "order",
730 "style": {
731 "navigationBarTitleText": "我的订单",
732 "enablePullDownRefresh": false
733 }
734 },
735 {
687 "path": "reviewList", 736 "path": "reviewList",
688 "style": { 737 "style": {
689 "navigationBarTitleText": "审核详情", 738 "navigationBarTitleText": "审核详情",
......
1 <template>
2 <view class="invoice-apply">
3 <view class="content">
4 <!-- 发票类型 -->
5 <view class="form-item">
6 <text class="label">发票类型</text>
7 <text class="value">{{ form.invoiceType === '2' ? '普通发票(企业)' : '普通发票(个人)' }}</text>
8 </view>
9
10 <!-- 发票抬头 -->
11 <view class="form-item">
12 <text class="label">发票抬头</text>
13 <input
14 class="input"
15 v-model="form.name"
16 placeholder="请输入公司全称或个人姓名"
17 placeholder-style="color: #999;"
18 />
19 </view>
20
21 <!-- 纳税人识别号(企业才显示) -->
22 <view class="form-item" v-if="form.invoiceType === '2'">
23 <text class="label">纳税人识别号</text>
24 <input
25 class="input"
26 v-model="form.taxno"
27 placeholder="请输入纳税人识别号"
28 placeholder-style="color: #999;"
29 maxlength="20"
30 />
31 </view>
32
33 <!-- 开票金额 -->
34 <view class="form-item">
35 <text class="label">开票金额</text>
36 <text class="amount">¥ {{ (Number(form.amount)).toFixed(2) }}</text>
37 </view>
38
39 <!-- 接收方式 -->
40 <view class="form-item">
41 <text class="label">接收方式</text>
42 <text class="value">电子邮箱</text>
43 </view>
44
45 <!-- 接收邮箱 -->
46 <view class="form-item">
47 <text class="label">接收邮箱</text>
48 <input
49 class="input"
50 v-model="form.email"
51 placeholder="请输入接收发票的邮箱(必填)"
52 placeholder-style="color: #999;"
53 />
54 </view>
55 </view>
56
57 <view class="hint">电子发票将在3-5个工作日内发送至该邮箱</view>
58
59 <!-- 提交按钮 -->
60 <view class="btn-wrap" @click="submitInvoice">
61 <view class="submit-btn">提交申请</view>
62 </view>
63 </view>
64 </template>
65
66 <script setup>
67 import { ref, reactive } from 'vue';
68 import { onLoad } from '@dcloudio/uni-app';
69 import { outputInvoiceNo } from '@/common/api.js'; // 与PC端接口一致
70
71 // 表单数据(与PC端字段完全对齐)
72 const form = reactive({
73 invoiceType: '1', // 1=个人 2=企业
74 name: '', // 发票抬头
75 taxno: '', // 纳税人识别号
76 email: '', // 邮箱
77 amount: 0, // 金额
78 id: '' // 订单ID
79 });
80
81 // 页面加载(接收PC端传来的参数)
82 onLoad((options) => {
83 if (options.id) {
84 form.id = options.id;
85 form.amount = options.amount;
86 console.log(33,form.amount);
87 }
88 if (options.invoiceType) {
89 form.invoiceType = options.invoiceType;
90 }
91 // getOrderInfo();
92 });
93
94 // 获取订单金额
95 // const getOrderInfo = async () => {
96 // try {
97 // // 这里替换成你真实获取订单金额的接口
98 // = 1500;
99 // } catch (error) {
100 // uni.showToast({ title: '获取订单信息失败', icon: 'none' });
101 // }
102 // };
103
104 // 提交发票申请(与PC逻辑完全一致)
105 const submitInvoice = async () => {
106 // 1. PC端逻辑:个人不允许开票
107 if (form.invoiceType === '1') {
108 return uni.showToast({ title: '暂不支持个人开票', icon: 'none' });
109 }
110
111 // 2. 抬头校验
112 if (!form.name) {
113 return uni.showToast({ title: '请输入发票抬头', icon: 'none' });
114 }
115
116 // 3. 企业必须填纳税人识别号
117 if (form.invoiceType === '2' && !form.taxno) {
118 return uni.showToast({ title: '请输入纳税人识别号', icon: 'none' });
119 }
120
121 // 4. 纳税人识别号格式校验(同PC)
122 const taxReg = /^[A-Z0-9]{15}$|^[A-Z0-9]{18}$|^[A-Z0-9]{20}$/;
123 if (form.invoiceType === '2' && !taxReg.test(form.taxno)) {
124 return uni.showToast({ title: '纳税人识别号格式不正确', icon: 'none' });
125 }
126
127 // 5. 邮箱校验
128 const emailReg = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
129 if (!form.email) {
130 return uni.showToast({ title: '请输入接收邮箱', icon: 'none' });
131 }
132 if (!emailReg.test(form.email)) {
133 return uni.showToast({ title: '请输入正确的邮箱地址', icon: 'none' });
134 }
135
136 try {
137 // 调用PC端同一个接口:outputInvoiceNo
138 await outputInvoiceNo(form);
139
140 uni.showToast({
141 title: '发票申请提交成功!',
142 icon: 'success',
143 duration: 2000
144 });
145
146 setTimeout(() => {
147 uni.navigateBack();
148 }, 2000);
149 } catch (error) {
150 uni.showToast({ title: '提交失败,请检查信息', icon: 'none' });
151 }
152 };
153 </script>
154
155 <style lang="scss" scoped>
156 .invoice-apply {
157 min-height: 100vh;
158 background: #f5f7fa;
159
160 .content {
161 padding: 20rpx;
162
163 .form-item {
164 display: flex;
165 justify-content: space-between;
166 align-items: center;
167 background: #fff;
168 padding: 24rpx;
169 border-bottom: 1rpx solid #eee;
170
171 .label {
172 font-size: 28rpx;
173 color: #333;
174 }
175
176 .input {
177 width: 80%;
178 font-size: 28rpx;
179 color: #333;
180 padding: 16rpx 0;
181 text-align: right;
182 }
183
184 .value {
185 font-size: 28rpx;
186 color: #333;
187 }
188
189 .amount {
190 font-size: 28rpx;
191 color: #e4393c;
192 font-weight: 500;
193 }
194 }
195 }
196
197 .hint {
198 font-size: 26rpx;
199 color: #B6BCC0;
200 margin-top: 20rpx;
201 text-align: center;
202 }
203
204 .btn-wrap {
205 width: 100%;
206 background-color: #fff;
207 padding: 30rpx;
208 position: fixed;
209 bottom: 0;
210 left: 0;
211 right: 0;
212 }
213
214 .submit-btn {
215 height: 70rpx;
216 line-height: 70rpx;
217 border-radius: 35rpx;
218 width: 90%;
219 margin: 0 auto;
220 background: #AD181F;
221 color: #fff;
222 font-size: 28rpx;
223 text-align: center;
224 }
225 }
226 </style>
...\ No newline at end of file ...\ No newline at end of file
1 <template>
2 <view class="container">
3 <web-view :src="url" @message="handleMessage"></web-view>
4 </view>
5 </template>
6
7 <script setup>
8 import { ref } from 'vue';
9 import {
10 onShow,
11 onLoad
12 } from '@dcloudio/uni-app'
13
14 const url = ref('');
15
16 onLoad((options) => {
17 if (options.url) {
18 url.value = decodeURIComponent(options.url);
19 }
20 });
21
22 const handleMessage = (event) => {
23 console.log('收到消息:', event.detail.data);
24 };
25 </script>
26
27 <style scoped>
28 .container {
29 width: 100%;
30 height: 100vh;
31 }
32 </style>
...\ No newline at end of file ...\ No newline at end of file
...@@ -6,22 +6,24 @@ ...@@ -6,22 +6,24 @@
6 </image> 6 </image>
7 7
8 <!-- 绑定/解绑学员 --> 8 <!-- 绑定/解绑学员 -->
9 <view v-if="!isBound" class="bind-student" @click="handleBindAction"> 9 <view class="bind-student" @click="handleBindAction">
10 <text>{{ isBound ? '解绑' : '绑定学员' }}</text> 10 <text>{{ isBound ? '解绑学员' : '绑定学员' }}</text>
11 <image class="arrow-icon" :src="config.baseUrl_api + '/fs/static/slices/bd@2x.png'" mode="aspectFit"> 11 <image src="/static/bd@2x.png" class="bind-icon" mode="aspectFit"></image>
12 </image>
13 </view> 12 </view>
14 13
15 <!-- 用户信息 --> 14 <!-- 用户信息 -->
16 <view class="user-section"> 15 <view class="user-section">
17 <view class="user-top"> 16 <view class="user-top">
18 <view class="avatar-wrap"> 17 <view class="avatar-wrap" @click="showLogoutConfirm">
19 <image class="avatar" :src="config.baseUrl_api + '/fs/static/slices/tx@2x.png'" 18 <!-- <image class="avatar" v-if="perInfo.photo" :src="config.baseUrl_api + perInfo.photo"
20 mode="aspectFill"> 19 mode="aspectFill">
21 </image> 20 </image> -->
22 </view> 21 <image class="avatar" :src="config.baseUrl_api + '/fs/static/slices/tx@2x.png'"
23 <view class="member-id">{{ userInfo.userName }}</view> 22 mode="aspectFill">
23 </image>
24 </view> 24 </view>
25 <view class="member-id">注册会员{{ userInfo.userName }}</view>
26 </view>
25 <view class="user-bottom"> 27 <view class="user-bottom">
26 <view class="user-name">{{ perInfo?.perName }}</view> 28 <view class="user-name">{{ perInfo?.perName }}</view>
27 <view class="card-info"> 29 <view class="card-info">
...@@ -32,7 +34,7 @@ ...@@ -32,7 +34,7 @@
32 </view> 34 </view>
33 35
34 <!-- 已过期印章 --> 36 <!-- 已过期印章 -->
35 <image v-if="perInfo?.perValidDateFlag && perInfo?.perValidDateFlag!='1'" class="expired-stamp" 37 <image v-if="perInfo?.perValidDateFlag == 0" class="expired-stamp"
36 :src="config.baseUrl_api + '/fs/static/slices/end@2x.png'" mode="aspectFit"> 38 :src="config.baseUrl_api + '/fs/static/slices/end@2x.png'" mode="aspectFit">
37 </image> 39 </image>
38 </view> 40 </view>
...@@ -41,55 +43,122 @@ ...@@ -41,55 +43,122 @@
41 <view class="func-card"> 43 <view class="func-card">
42 <view class="func-list"> 44 <view class="func-list">
43 <view class="func-item" @click="goToAuth"> 45 <view class="func-item" @click="goToAuth">
44 <image class="func-icon" :src="config.baseUrl_api + '/fs/static/slices/btn01@2x.png'" 46 <view class="func-icon">
45 mode="aspectFit"> 47 <image src="/static/btn01@2x.png"></image>
46 </image> 48 <!-- <uni-icons type="contact" size="40" color="#1E88E5"></uni-icons> -->
47 <text class="func-text">参赛能力认证</text> 49 </view>
50 <text class="func-text">人员信息</text>
48 </view> 51 </view>
49 <view class="func-item" @click="goToScore"> 52 <view class="func-item" @click="goToScore">
50 <image class="func-icon" :src="config.baseUrl_api + '/fs/static/slices/btn02@2x.png'" 53 <view class="func-icon">
51 mode="aspectFit"> 54 <image src="/static/btn02@2x.png"></image>
52 </image> 55 <!-- <uni-icons type="person" size="40" color="#1E88E5"></uni-icons> -->
53 <text class="func-text">成绩查询</text> 56 </view>
57 <text class="func-text">个人会员</text>
54 </view> 58 </view>
55 <view class="func-item" @click="goToRecord"> 59 <view class="func-item" @click="goToRecord">
56 <image class="func-icon" :src="config.baseUrl_api + '/fs/static/slices/btn03@2x.png'" 60 <view class="func-icon">
57 mode="aspectFit"> 61 <image src="/static/btn03@2x.png"></image>
58 </image> 62 <!-- <uni-icons type="list" size="40" color="#1E88E5"></uni-icons> -->
59 <text class="func-text">参赛记录</text> 63 </view>
64 <text class="func-text">级位记录</text>
60 </view> 65 </view>
61 </view> 66 </view>
62 </view> 67 </view>
63 68
64 <!-- 人员信息区域 --> 69 <!-- 查询功能区域 -->
65 <view class="info-section"> 70 <view class="query-section">
66 <view class="section-title"> 71 <view class="query-item" @click="goToOrder">
67 <view class="title-bar"></view> 72 <view class="query-item-left">
68 <text class="title-text">人员信息</text> 73 <image src="/static/user_icon01@2x.png" class="query-item-icon"></image>
74 <text class="query-item-text">我的订单</text>
75 </view>
76 <uni-icons type="arrowright" size="20" color="#999"></uni-icons>
69 </view> 77 </view>
70 <view class="info-card"> 78 <view class="query-item" @click="goToWebView(1)">
71 <view class="info-item"> 79 <view class="query-item-left">
72 <text class="item-label">姓名</text> 80 <image src="/static/user_icon03@2x.png" class="query-item-icon"></image>
73 <text class="item-value">{{ perInfo?.perName }}</text> 81 <text class="query-item-text">单位会员查询</text>
74 </view> 82 </view>
75 <view class="info-item"> 83 <uni-icons type="arrowright" size="20" color="#999"></uni-icons>
76 <text class="item-label">证件类型</text> 84 </view>
77 <text class="item-value">{{ perInfo?.idcTypeStr }}</text> 85 <view class="query-item" @click="goToWebView(2)">
86 <view class="query-item-left">
87 <image src="/static/user_icon03@2x.png" class="query-item-icon"></image>
88 <text class="query-item-text">个人会员查询</text>
78 </view> 89 </view>
79 <view class="info-item"> 90 <uni-icons type="arrowright" size="20" color="#999"></uni-icons>
80 <text class="item-label">身份证号</text> 91 </view>
81 <text class="item-value">{{ perInfo?.perIdcCode }}</text> 92 <view class="query-item" @click="goToWebView(3)">
93 <view class="query-item-left">
94 <image src="/static/user_icon02@2x.png" class="query-item-icon"></image>
95 <text class="query-item-text">旧版级位证书查询</text>
82 </view> 96 </view>
83 <view class="info-item"> 97 <uni-icons type="arrowright" size="20" color="#999"></uni-icons>
84 <text class="item-label">生日</text> 98 </view>
85 <text class="item-value">{{ perInfo?.birth }}</text> 99 <view class="query-item" @click="goToWebView(4)">
100 <view class="query-item-left">
101 <image src="/static/user_icon02@2x.png" class="query-item-icon"></image>
102 <text class="query-item-text">新版级位证书查询</text>
86 </view> 103 </view>
104 <uni-icons type="arrowright" size="20" color="#999"></uni-icons>
105 </view>
106 <view class="query-item" @click="goToWebView(5)">
107 <view class="query-item-left">
108 <image src="/static/user_icon02@2x.png" class="query-item-icon"></image>
109 <text class="query-item-text">级位记录查询</text>
110 </view>
111 <uni-icons type="arrowright" size="20" color="#999"></uni-icons>
112 </view>
113 <view class="query-item" @click="goToWebView(6)">
114 <view class="query-item-left">
115 <image src="/static/user_icon02@2x.png" class="query-item-icon"></image>
116 <text class="query-item-text">国际段位证书查询</text>
117 </view>
118 <uni-icons type="arrowright" size="20" color="#999"></uni-icons>
119 </view>
120 <view class="query-item" @click="goToWebView(7)">
121 <view class="query-item-left">
122 <image src="/static/user_icon02@2x.png" class="query-item-icon"></image>
123 <text class="query-item-text">中国段位证书查询</text>
124 </view>
125 <uni-icons type="arrowright" size="20" color="#999"></uni-icons>
126 </view>
127 <view class="query-item" @click="goToWebView(8)">
128 <view class="query-item-left">
129 <image src="/static/user_icon03@2x.png" class="query-item-icon"></image>
130 <text class="query-item-text">级位考官查询</text>
131 </view>
132 <uni-icons type="arrowright" size="20" color="#999"></uni-icons>
133 </view>
134 <view class="query-item" @click="goToWebView(9)">
135 <view class="query-item-left">
136 <image src="/static/user_icon03@2x.png" class="query-item-icon"></image>
137 <text class="query-item-text">段位考官查询</text>
138 </view>
139 <uni-icons type="arrowright" size="20" color="#999"></uni-icons>
140 </view>
141 <view class="query-item" @click="goToWebView(10)">
142 <view class="query-item-left">
143 <image src="/static/user_icon03@2x.png" class="query-item-icon"></image>
144 <text class="query-item-text">大众教练员查询</text>
145 </view>
146 <uni-icons type="arrowright" size="20" color="#999"></uni-icons>
147 </view>
148 <view class="query-item" @click="goToWebView(11)">
149 <view class="query-item-left">
150 <image src="/static/user_icon03@2x.png" class="query-item-icon"></image>
151 <text class="query-item-text">大众裁判员查询</text>
152 </view>
153 <uni-icons type="arrowright" size="20" color="#999"></uni-icons>
154 </view>
155 <view class="query-item" @click="goToWebView(12)">
156 <view class="query-item-left">
157 <image src="/static/user_icon03@2x.png" class="query-item-icon"></image>
158 <text class="query-item-text">培训讲师查询</text>
159 </view>
160 <uni-icons type="arrowright" size="20" color="#999"></uni-icons>
87 </view> 161 </view>
88 </view>
89
90 <!-- 退出登录按钮 -->
91 <view class="logout-section">
92 <view class="logout-btn" @click="handleLogout">退出登录</view>
93 </view> 162 </view>
94 163
95 <!-- 绑定学员弹框 --> 164 <!-- 绑定学员弹框 -->
...@@ -117,6 +186,20 @@ ...@@ -117,6 +186,20 @@
117 </view> 186 </view>
118 </view> 187 </view>
119 </uni-popup> 188 </uni-popup>
189
190 <!-- 退出登录确认框 -->
191 <view v-if="showConfirm" class="confirm-mask" @click.stop="cancelLogout">
192 <view class="confirm-box" @click.stop>
193 <view class="confirm-content">
194 <view class="confirm-title">退出登录</view>
195 <view class="confirm-text">确定要退出登录吗?</view>
196 </view>
197 <view class="confirm-buttons">
198 <view class="confirm-btn cancel" @click="cancelLogout">取消</view>
199 <view class="confirm-btn confirm" @click="confirmLogout">确定</view>
200 </view>
201 </view>
202 </view>
120 </view> 203 </view>
121 </template> 204 </template>
122 205
...@@ -146,6 +229,8 @@ ...@@ -146,6 +229,8 @@
146 const userStore = useUserStore() 229 const userStore = useUserStore()
147 const userInfo = computed(() => userStore.user) 230 const userInfo = computed(() => userStore.user)
148 const perInfo = computed(() => userStore.perInfo) 231 const perInfo = computed(() => userStore.perInfo)
232 console.log(222,userInfo.value)
233 console.log(333,perInfo.value)
149 234
150 // 是否已绑定学员 235 // 是否已绑定学员
151 const isBound = computed(() => { 236 const isBound = computed(() => {
...@@ -154,10 +239,11 @@ ...@@ -154,10 +239,11 @@
154 }) 239 })
155 240
156 const bindPopup = ref(null) 241 const bindPopup = ref(null)
157 const bindForm = ref({ 242 const bindForm = ref({
158 name: '', 243 name: '',
159 idcCode: '' 244 idcCode: ''
160 }) 245 })
246 const showConfirm = ref(false)
161 247
162 onMounted(() => { 248 onMounted(() => {
163 let webUserName = uni.getStorageSync('webUserName') 249 let webUserName = uni.getStorageSync('webUserName')
...@@ -255,10 +341,6 @@ ...@@ -255,10 +341,6 @@
255 uni.hideLoading() 341 uni.hideLoading()
256 342
257 if (err) { 343 if (err) {
258 // uni.showToast({
259 // title: '绑定失败',
260 // icon: 'none'
261 // })
262 return 344 return
263 } 345 }
264 346
...@@ -267,37 +349,69 @@ ...@@ -267,37 +349,69 @@
267 icon: 'success' 349 icon: 'success'
268 }) 350 })
269 closeBindPopup() 351 closeBindPopup()
270 // 刷新用户信息
271 getWebInfo() 352 getWebInfo()
272 } 353 }
273 354
355 // 返回上一页
356 const goBack = () => {
357 uni.navigateBack()
358 }
359
274 const goToAuth = () => { 360 const goToAuth = () => {
275 console.log("参赛能力认证"); 361 uni.navigateTo({
362 url: '/personal/personInfo'
363 });
276 }; 364 };
277 365
278 const goToScore = () => { 366 const goToScore = () => {
279 console.log("成绩查询"); 367 uni.navigateTo({
368 url: '/personal/memberInfo'
369 });
280 }; 370 };
281 371
372 const goToWebView = (type) => {
373 const url = "https://member.taekwondo.org.cn/#/authAccurate?type=" + type
374 uni.navigateTo({
375 url: "/pages/webview/webview?url=" + encodeURIComponent(url)
376 });
377 };
378
379 // 导航到级位记录
282 const goToRecord = () => { 380 const goToRecord = () => {
283 console.log("参赛记录"); 381 uni.navigateTo({
382 url: '/personal/levelRecord'
383 });
284 }; 384 };
285 385
286 // 退出登录 386 // 导航到我的订单
287 const handleLogout = () => { 387 const goToOrder = () => {
288 uni.showModal({ 388 uni.navigateTo({
289 content: `确认退出吗?`, 389 url: '/personal/order'
290 success: function(res) { 390 });
291 if (res.confirm) { 391 };
292 logout().then(() => { 392
293 uni.reLaunch({ 393
294 url: '/login/login' 394
295 }) 395 // 显示退出登录确认框
296 }) 396 const showLogoutConfirm = () => {
297 } 397 showConfirm.value = true;
298 } 398 };
299 }) 399
300 } 400 // 取消退出登录
401 const cancelLogout = () => {
402 showConfirm.value = false;
403 };
404
405 // 确认退出登录
406 const confirmLogout = () => {
407 // 调用退出登录接口
408 logout().then(() => {
409 // 跳转到登录页
410 uni.reLaunch({
411 url: '/login/login'
412 })
413 });
414 };
301 </script> 415 </script>
302 416
303 <style lang="scss" scoped> 417 <style lang="scss" scoped>
...@@ -307,6 +421,38 @@ ...@@ -307,6 +421,38 @@
307 padding-bottom: 40rpx; 421 padding-bottom: 40rpx;
308 } 422 }
309 423
424 /* 导航栏 */
425 .nav-bar {
426 display: flex;
427 align-items: center;
428 justify-content: space-between;
429 height: 88rpx;
430 background: #ffffff;
431 padding: 0 30rpx;
432 box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
433 position: sticky;
434 top: 0;
435 z-index: 100;
436 }
437
438 .nav-left {
439 width: 44rpx;
440 height: 44rpx;
441 display: flex;
442 align-items: center;
443 justify-content: center;
444 }
445
446 .nav-title {
447 font-size: 32rpx;
448 font-weight: 500;
449 color: #333;
450 }
451
452 .nav-right {
453 width: 44rpx;
454 }
455
310 /* 会员卡 */ 456 /* 会员卡 */
311 .member-card { 457 .member-card {
312 position: relative; 458 position: relative;
...@@ -333,19 +479,19 @@ ...@@ -333,19 +479,19 @@
333 gap: 8rpx; 479 gap: 8rpx;
334 z-index: 10; 480 z-index: 10;
335 padding: 10rpx 16rpx; 481 padding: 10rpx 16rpx;
336 background: rgba(255, 255, 255, 0.5); 482 // background: rgba(255, 255, 255, 0.5);
337 border-radius: 30rpx; 483 border-radius: 30rpx;
338 } 484 }
339 485
340 .bind-student text { 486 .bind-student text {
341 font-size: 26rpx; 487 font-size: 26rpx;
342 color: #8b7355; 488 color: #5c4b37;
343 } 489 }
344 490
345 .arrow-icon { 491 .bind-icon {
346 width: 28rpx; 492 width: 45rpx;
347 height: 28rpx; 493 height: 45rpx;
348 } 494 }
349 495
350 .user-section { 496 .user-section {
351 position: relative; 497 position: relative;
...@@ -373,7 +519,7 @@ ...@@ -373,7 +519,7 @@
373 519
374 .member-id { 520 .member-id {
375 font-size: 26rpx; 521 font-size: 26rpx;
376 color: #8b7355; 522 color: #503000;
377 } 523 }
378 524
379 .user-bottom { 525 .user-bottom {
...@@ -394,8 +540,8 @@ ...@@ -394,8 +540,8 @@
394 } 540 }
395 541
396 .info-row { 542 .info-row {
397 font-size: 24rpx; 543 font-size: 28rpx;
398 color: #8b7355; 544 color: #503000;
399 } 545 }
400 546
401 /* 已过期印章 */ 547 /* 已过期印章 */
...@@ -435,6 +581,15 @@ ...@@ -435,6 +581,15 @@
435 .func-icon { 581 .func-icon {
436 width: 72rpx; 582 width: 72rpx;
437 height: 72rpx; 583 height: 72rpx;
584 display: flex;
585 align-items: center;
586 justify-content: center;
587 // background: #f0f7ff;
588 // border-radius: 16rpx;
589 image{
590 width: 72rpx;
591 height: 72rpx;
592 }
438 } 593 }
439 594
440 .func-text { 595 .func-text {
...@@ -442,59 +597,43 @@ ...@@ -442,59 +597,43 @@
442 color: #333; 597 color: #333;
443 } 598 }
444 599
445 /* 人员信息区域 */ 600 /* 查询功能区域 */
446 .info-section { 601 .query-section {
447 margin: 0 30rpx; 602 margin: 0 30rpx;
603 background: #ffffff;
604 border-radius: 20rpx;
605 box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.06);
606 overflow: hidden;
448 } 607 }
449 608
450 .section-title { 609 .query-item {
451 display: flex; 610 display: flex;
452 align-items: center; 611 align-items: center;
453 gap: 12rpx; 612 justify-content: space-between;
454 margin-bottom: 20rpx; 613 padding: 32rpx 30rpx;
455 } 614 border-bottom: 1rpx solid #f5f5f5;
456
457 .title-bar {
458 width: 6rpx;
459 height: 32rpx;
460 background: #e6c560;
461 border-radius: 3rpx;
462 }
463
464 .title-text {
465 font-size: 30rpx;
466 font-weight: 500;
467 color: #333;
468 } 615 }
469 616
470 .info-card { 617 .query-item:last-child {
471 background: #ffffff; 618 border-bottom: none;
472 border-radius: 20rpx;
473 padding: 0 32rpx;
474 } 619 }
475 620
476 .info-item { 621 .query-item-left {
477 display: flex; 622 display: flex;
478 justify-content: space-between;
479 align-items: center; 623 align-items: center;
480 padding: 28rpx 0; 624 gap: 16rpx;
481 border-bottom: 1rpx solid #f5f5f5;
482 } 625 }
483 626
484 .info-item:last-child { 627 .query-item-icon {
485 border-bottom: none; 628 width: 44rpx;
629 height: 48rpx;
486 } 630 }
487 631
488 .item-label { 632 .query-item-text {
489 font-size: 28rpx; 633 font-size: 28rpx;
490 color: #333; 634 color: #333;
491 } 635 }
492 636
493 .item-value {
494 font-size: 28rpx;
495 color: #999;
496 }
497
498 /* 绑定学员弹框 */ 637 /* 绑定学员弹框 */
499 .bind-popup { 638 .bind-popup {
500 width: 600rpx; 639 width: 600rpx;
...@@ -572,18 +711,66 @@ ...@@ -572,18 +711,66 @@
572 font-weight: 500; 711 font-weight: 500;
573 } 712 }
574 713
575 /* 退出登录 */ 714 /* 退出登录确认框 */
576 .logout-section { 715 .confirm-mask {
577 margin: 60rpx 30rpx 40rpx; 716 position: fixed;
717 top: 0;
718 left: 0;
719 right: 0;
720 bottom: 0;
721 background: rgba(0, 0, 0, 0.5);
722 display: flex;
723 align-items: center;
724 justify-content: center;
725 z-index: 1000;
578 } 726 }
579 727
580 .logout-btn { 728 .confirm-box {
581 height: 88rpx; 729 width: 600rpx;
582 line-height: 88rpx;
583 text-align: center;
584 font-size: 30rpx;
585 color: #999;
586 background: #ffffff; 730 background: #ffffff;
587 border-radius: 20rpx; 731 border-radius: 20rpx;
732 overflow: hidden;
733 }
734
735 .confirm-content {
736 padding: 40rpx;
737 text-align: center;
738 }
739
740 .confirm-title {
741 font-size: 32rpx;
742 font-weight: 500;
743 color: #333;
744 margin-bottom: 20rpx;
745 }
746
747 .confirm-text {
748 font-size: 28rpx;
749 color: #666;
750 margin-top: 30rpx;
751 color: #C40F18;
752 }
753
754 .confirm-buttons {
755 display: flex;
756 border-top: 1rpx solid #eee;
757 }
758
759 .confirm-btn {
760 flex: 1;
761 height: 100rpx;
762 line-height: 100rpx;
763 text-align: center;
764 font-size: 30rpx;
765 }
766
767 .confirm-btn.cancel {
768 color: #666;
769 border-right: 1rpx solid #eee;
770 }
771
772 .confirm-btn.confirm {
773 color: #C40F18;
774 font-weight: 500;
588 } 775 }
589 </style> 776 </style>
...\ No newline at end of file ...\ No newline at end of file
......
1 <template>
2 <view class="page-container">
3
4 <!-- 表格头部 -->
5 <view class="table-header">
6 <view class="table-cell table-cell-1">序号</view>
7 <view class="table-cell table-cell-2">级位</view>
8 <view class="table-cell table-cell-3">级位号</view>
9 <view class="table-cell table-cell-4">获得证书时间</view>
10 <view class="table-cell table-cell-5">操作</view>
11 </view>
12
13 <!-- 表格内容 -->
14 <view v-if="loading" class="loading-container">
15 <uni-icons type="spinner" size="40" color="#409eff" class="loading-icon" />
16 <view class="loading-text">加载中...</view>
17 </view>
18 <view v-else class="table-content">
19 <view class="table-row" v-for="(item, index) in levelRecords" :key="index">
20 <view class="table-cell table-cell-1">{{ index + 1 }}</view>
21 <view class="table-cell table-cell-2">{{ szToHz(item.level) }}</view>
22 <view class="table-cell table-cell-3">{{ item.certCode }}</view>
23 <view class="table-cell table-cell-4">{{ item.createTime ? item.createTime.substring(0, 10) : '--' }}</view>
24 <view class="table-cell table-cell-5">
25 <view class="change-record-btn" @click="showChangeRecord(item)" v-if="item.remark?.length>0">变更记录</view>
26 </view>
27 </view>
28
29 <!-- 空状态 -->
30 <view v-if="levelRecords.length === 0 && !loading" class="empty-state">
31 <uni-icons type="empty" size="80" color="#ccc" />
32 <view class="empty-text">暂无级位记录</view>
33 </view>
34 </view>
35
36 <!-- 变更记录弹窗 -->
37 <uni-popup ref="changeRecordPopup" type="center">
38 <view class="popup-content">
39 <view class="popup-header">
40 <view class="popup-title">级位变更</view>
41 <view class="popup-close" @click="closeChangeRecord">
42 <uni-icons type="close" size="24" color="#fff" />
43 </view>
44 </view>
45 <view class="popup-body">
46 <view v-if="currentChangeRecord" class="change-details">
47 <view class="change-item">
48 <view class="change-label">变更名称:{{ currentChangeRecord.modName || '等级变更' }}</view>
49 <!-- <view class="change-value"></view> -->
50 </view>
51 <view class="change-item">
52 <view class="change-label">考级级别:{{ szToHz(currentChangeRecord.oldJi) }}</view>
53 <!-- <view class="change-value"></view> -->
54 </view>
55 <view class="change-item">
56 <view class="change-label">变更后级位:{{ szToHz(currentChangeRecord.newJi) }}</view>
57 <!-- <view class="change-value"></view> -->
58 </view>
59 <view class="change-item">
60 <view class="change-label">变更时间:{{ parseTime(currentChangeRecord.modTime) }}</view>
61 <!-- <view class="change-value">/view> -->
62 </view>
63 </view>
64 <!-- 空状态 -->
65 <view v-else class="empty-state">
66 <uni-icons type="empty" size="60" color="#ccc" />
67 <view class="empty-text">暂无变更记录</view>
68 </view>
69 </view>
70 <!-- <view class="popup-footer">
71 <button class="confirm-btn" @click="closeChangeRecord">确定</button>
72 </view> -->
73 </view>
74 </uni-popup>
75 </view>
76 </template>
77
78 <script setup>
79 import { ref, onMounted } from 'vue';
80 import { useUserStore } from '../store/modules/user';
81 import { getAssoPers } from '@/common/api.js';
82 import { getPersonTecDetails } from '@/common/api.js';
83
84 // 级位记录数据
85 const levelRecords = ref([]);
86 const loading = ref(false);
87 const perId = ref('');
88 const userStore = useUserStore();
89
90 // 变更记录相关
91 const changeRecordPopup = ref(null);
92 const currentChangeRecord = ref(null);
93
94 // 返回上一页
95 const goBack = () => {
96 uni.navigateBack();
97 };
98
99 // 显示变更记录
100 const showChangeRecord = (item) => {
101 // remark已经在getLevelRecords中解析过了,直接使用
102 if (item.remark) {
103 currentChangeRecord.value = Array.isArray(item.remark) ? item.remark[0] : item.remark;
104 } else {
105 currentChangeRecord.value = null;
106 }
107 changeRecordPopup.value.open();
108 };
109
110 // 关闭变更记录
111 const closeChangeRecord = () => {
112 changeRecordPopup.value.close();
113 };
114
115 // 获取级位记录数据
116 const getLevelRecords = async () => {
117 loading.value = true;
118 try {
119 const res = await getPersonTecDetails(0, perId.value); // 0表示级位
120 levelRecords.value = res.data || [];
121 // 处理数据
122 levelRecords.value.forEach(item => {
123 item.level = item.level * 1;
124 if (item.remark) {
125 try {
126 item.remark = JSON.parse(item.remark);
127 } catch (e) {
128 console.error('解析remark失败:', e);
129 }
130 }
131 });
132 } catch (error) {
133 console.error('获取级位记录失败:', error);
134 uni.showToast({
135 title: '获取级位记录失败',
136 icon: 'none'
137 });
138 } finally {
139 loading.value = false;
140 }
141 };
142
143 // 数字转汉字
144 const szToHz = (num) => {
145 const arr = ['', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
146 return arr[num] || num;
147 };
148
149 // 时间格式化
150 const parseTime = (time) => {
151 if (!time) return '--';
152 const date = new Date(time);
153 return date.getFullYear() + '-' +
154 String(date.getMonth() + 1).padStart(2, '0') + '-' +
155 String(date.getDate()).padStart(2, '0');
156 };
157
158 onMounted(async () => {
159 // 获取perId
160 const userInfo = userStore.user;
161 if (userInfo && userInfo.perId) {
162 perId.value = userInfo.perId;
163 getLevelRecords();
164 } else {
165 // 如果userInfo中没有perId,尝试通过getAssoPers获取
166 try {
167 const res = await getAssoPers(userInfo?.id || '');
168 perId.value = res.data[10] || '';
169 if (perId.value) {
170 getLevelRecords();
171 } else {
172 uni.showToast({
173 title: '获取用户信息失败',
174 icon: 'none'
175 });
176 }
177 } catch (error) {
178 console.error('获取perId失败:', error);
179 uni.showToast({
180 title: '获取用户信息失败',
181 icon: 'none'
182 });
183 }
184 }
185 });
186 </script>
187
188 <style lang="scss" scoped>
189 .page-container {
190 min-height: 100vh;
191 background: #f5f5f5;
192 }
193
194 /* 导航栏 */
195 .nav-bar {
196 display: flex;
197 align-items: center;
198 justify-content: space-between;
199 height: 88rpx;
200 background: #ffffff;
201 padding: 0 30rpx;
202 box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
203 position: sticky;
204 top: 0;
205 z-index: 100;
206 }
207
208 .nav-left {
209 width: 44rpx;
210 height: 44rpx;
211 display: flex;
212 align-items: center;
213 justify-content: center;
214 }
215
216 .nav-title {
217 font-size: 32rpx;
218 font-weight: 500;
219 color: #333;
220 }
221
222 .nav-right {
223 width: 44rpx;
224 }
225
226 /* 表格头部 */
227 .table-header {
228 display: flex;
229 background: linear-gradient(135deg, #ff6b6b, #ff9f43);
230 padding: 0 30rpx;
231 position: sticky;
232 // top: 88rpx;
233 z-index: 90;
234 }
235
236 /* 表格内容 */
237 .table-content {
238 background: #ffffff;
239 margin: 20rpx 20rpx;
240 border-radius: 16rpx;
241 overflow: hidden;
242 box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
243 }
244
245 /* 表格行 */
246 .table-row {
247 display: flex;
248 padding: 0 30rpx;
249 border-bottom: 1rpx solid #f0f0f0;
250 transition: all 0.3s ease;
251 }
252
253 .table-row:last-child {
254 border-bottom: none;
255 }
256
257 .table-row:hover {
258 background: #fff9f0;
259 }
260
261 /* 表格单元格 */
262 .table-cell {
263 padding: 24rpx 0;
264 font-size: 26rpx;
265 color: #333;
266 display: flex;
267 align-items: center;
268 justify-content: center;
269 text-align: center;
270 }
271
272 .table-header .table-cell {
273 color: #ffffff;
274 font-weight: 500;
275 }
276
277 /* 单元格宽度 */
278 .table-cell-1 {
279 width: 80rpx;
280 }
281
282 .table-cell-2 {
283 width: 120rpx;
284 }
285
286 .table-cell-3 {
287 flex: 1;
288 padding: 0 10rpx;
289 }
290
291 .table-cell-4 {
292 width: 200rpx;
293 }
294
295 .table-cell-5 {
296 width: 150rpx;
297 }
298
299 /* 变更记录按钮 */
300 .change-record-btn {
301 background: linear-gradient(135deg, #ff6b6b, #ff9f43);
302 color: #ffffff;
303 padding: 8rpx 16rpx;
304 border-radius: 20rpx;
305 font-size: 24rpx;
306 text-align: center;
307 cursor: pointer;
308 transition: all 0.3s ease;
309 }
310
311 .change-record-btn:hover {
312 transform: scale(1.05);
313 box-shadow: 0 4rpx 8rpx rgba(255, 107, 107, 0.3);
314 }
315
316 .change-record-btn:disabled {
317 background: #ccc;
318 cursor: not-allowed;
319 }
320
321 /* 空状态 */
322 .empty-state {
323 display: flex;
324 flex-direction: column;
325 align-items: center;
326 justify-content: center;
327 padding: 100rpx 0;
328 }
329
330 .empty-text {
331 margin-top: 20rpx;
332 font-size: 28rpx;
333 color: #999;
334 }
335
336 /* 弹窗 */
337 .popup-content {
338 width: 300px;
339 background: #ffffff;
340 border-radius: 20rpx;
341 overflow: hidden;
342 box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.15);
343 }
344
345 .popup-header {
346 display: flex;
347 align-items: center;
348 justify-content: space-between;
349 padding: 30rpx;
350 background: linear-gradient(135deg, #ff6b6b, #ff9f43);
351 }
352
353 .popup-title {
354 font-size: 32rpx;
355 font-weight: 500;
356 color: #ffffff;
357 }
358
359 .popup-close {
360 width: 44rpx;
361 height: 44rpx;
362 display: flex;
363 align-items: center;
364 justify-content: center;
365 background: rgba(255, 255, 255, 0.2);
366 border-radius: 50%;
367 }
368
369 .popup-close uni-icons {
370 color: #ffffff;
371 }
372
373 .popup-body {
374 padding: 40rpx;
375 }
376
377 /* 变更记录详情 */
378 .change-details {
379 width: 100%;
380 }
381
382 .change-item {
383 margin-bottom: 30rpx;
384 }
385
386 .change-item:last-child {
387 margin-bottom: 0;
388 }
389
390 .change-label {
391 font-size: 26rpx;
392 color: #666;
393 margin-bottom: 10rpx;
394 font-weight: 500;
395 }
396
397 .change-value {
398 font-size: 28rpx;
399 color: #333;
400 padding: 16rpx 24rpx;
401 background: #fff9f0;
402 border-radius: 12rpx;
403 border-left: 4rpx solid #ff6b6b;
404 }
405
406 .popup-footer {
407 padding: 0 30rpx 30rpx;
408 }
409
410 .confirm-btn {
411 width: 100%;
412 height: 80rpx;
413 background: linear-gradient(135deg, #ff6b6b, #ff9f43);
414 color: #ffffff;
415 border: none;
416 border-radius: 40rpx;
417 font-size: 28rpx;
418 font-weight: 500;
419 transition: all 0.3s ease;
420 }
421
422 .confirm-btn:hover {
423 transform: translateY(-2rpx);
424 box-shadow: 0 4rpx 12rpx rgba(255, 107, 107, 0.3);
425 }
426
427 /* 加载状态 */
428 .loading-container {
429 display: flex;
430 flex-direction: column;
431 align-items: center;
432 justify-content: center;
433 height: 500rpx;
434 }
435
436 .loading-icon {
437 animation: spin 1s linear infinite;
438 color: #ff6b6b;
439 }
440
441 .loading-text {
442 margin-top: 20rpx;
443 font-size: 28rpx;
444 color: #ff6b6b;
445 }
446
447 @keyframes spin {
448 from {
449 transform: rotate(0deg);
450 }
451 to {
452 transform: rotate(360deg);
453 }
454 }
455
456 /* 响应式调整 */
457 @media (max-width: 375px) {
458 .table-header,
459 .table-row {
460 padding: 0 20rpx;
461 }
462
463 .table-cell {
464 font-size: 24rpx;
465 padding: 20rpx 0;
466 }
467
468 .table-cell-1 {
469 width: 60rpx;
470 }
471
472 .table-cell-2 {
473 width: 100rpx;
474 }
475
476 .table-cell-4 {
477 width: 160rpx;
478 }
479
480 .table-cell-5 {
481 width: 120rpx;
482 }
483
484 .change-record-btn {
485 font-size: 22rpx;
486 padding: 6rpx 12rpx;
487 }
488
489 .popup-content {
490 width: 300px;
491 max-width: 450rpx;
492 }
493
494 .popup-header,
495 .popup-body,
496 .popup-footer {
497 padding: 24rpx 32rpx;
498 }
499
500 .change-label {
501 font-size: 28rpx;
502 }
503
504 .change-value {
505 font-size: 26rpx;
506 padding: 12rpx 20rpx;
507 }
508
509 .change-item {
510 margin-bottom: 20rpx;
511 }
512 }
513 </style>
...\ No newline at end of file ...\ No newline at end of file
1 <template>
2 <view class="page-container">
3
4 <!-- 信息展示区域 -->
5 <view v-if="loading" class="loading-container">
6 <uni-icons type="spinner" size="40" color="#409eff" class="loading-icon" />
7 <view class="loading-text">加载中...</view>
8 </view>
9 <view v-else class="info-card">
10 <view class="info-item">
11 <view class="info-label">姓名</view>
12 <view class="info-value">{{ form?.name || '--' }}</view>
13 </view>
14 <view class="info-item">
15 <view class="info-label">证件类型</view>
16 <view class="info-value">{{ getCertType(form?.idcType) }}</view>
17 </view>
18 <view class="info-item">
19 <view class="info-label">证件号</view>
20 <view class="info-value">{{ form?.idcCode || '--' }}</view>
21 </view>
22 <view class="info-item">
23 <view class="info-label">性别</view>
24 <view class="info-value">{{ getGender(form?.sex) }}</view>
25 </view>
26 <view class="info-item">
27 <view class="info-label">会员编号</view>
28 <view class="info-value">{{ form?.perCode || '--' }}</view>
29 </view>
30 <view class="info-item">
31 <view class="info-label">所属一级协会</view>
32 <view class="info-value">{{ form?.topAssName || '--' }}</view>
33 </view>
34 <view class="info-item">
35 <view class="info-label">所属地区协会</view>
36 <view class="info-value">{{ form?.areaAssName || '--' }}</view>
37 </view>
38 <view class="info-item">
39 <view class="info-label">注册单位会员</view>
40 <view class="info-value">{{ form?.memName || '--' }}</view>
41 </view>
42 <view class="info-item">
43 <view class="info-label">缴费日期</view>
44 <view class="info-value">{{ form?.payDate || '--' }}</view>
45 </view>
46 <view class="info-item">
47 <view class="info-label">注册时间</view>
48 <view class="info-value">{{ form?.createTime || '--' }}</view>
49 </view>
50 <view class="info-item">
51 <view class="info-label">出生日期</view>
52 <view class="info-value">{{ form?.birth || '--' }}</view>
53 </view>
54 <view class="info-item">
55 <view class="info-label">手机号码</view>
56 <view class="info-value">{{ form?.phone || '--' }}</view>
57 </view>
58 <view class="info-item">
59 <view class="info-label">地址</view>
60 <view class="info-value">{{ form?.site || '--' }}</view>
61 </view>
62 <view class="info-item">
63 <view class="info-label">详细地址</view>
64 <view class="info-value">{{ form?.address || '--' }}</view>
65 </view>
66 </view>
67 </view>
68 </template>
69
70 <script setup>
71 import { ref, onMounted } from 'vue';
72 import { useUserStore } from '../store/modules/user';
73 import { getAssoPers, getInfo } from '@/common/api.js';
74
75 const userStore = useUserStore();
76 const form = ref({});
77 const loading = ref(false);
78 const perId = ref('');
79
80 // 返回上一页
81 const goBack = () => {
82 uni.navigateBack();
83 };
84
85 // 获取证件类型
86 const getCertType = (type) => {
87 switch (type) {
88 case '0':
89 case '1':
90 return '身份证';
91 case '2':
92 return '护照';
93 case '3':
94 return '军官证';
95 case '4':
96 return '港澳通行证';
97 case '5':
98 return '台湾通行证';
99 default:
100 return '--';
101 }
102 };
103
104 // 获取性别
105 const getGender = (gender) => {
106 switch (gender) {
107 case '0':
108 case '1':
109 return '男';
110 case '2':
111 return '女';
112 default:
113 return '--';
114 }
115 };
116
117 // 获取个人会员信息
118 const getMemberInfo = async () => {
119 loading.value = true;
120 try {
121 const res = await getInfo(perId.value);
122 form.value = res.data;
123 // 处理数据
124 form.value.topAssName = form.value?.ancestorNameList?.[0] || '--';
125 form.value.areaAssName = form.value?.ancestorNameList?.[1] || '--';
126 form.value.memName = form.value.memName || '--';
127 form.value.payDate = form.value.payDate ? form.value.payDate.substring(0, 10) : '--';
128 form.value.createTime = form.value.createTime ? form.value.createTime.substring(0, 10) : '--';
129 form.value.birth = form.value.birth ? form.value.birth.substring(0, 10) : '--';
130 form.value.site = form.value.site || '--';
131 form.value.address = form.value.address || '--';
132 } catch (error) {
133 console.error('获取个人会员信息失败:', error);
134 uni.showToast({
135 title: '获取个人会员信息失败',
136 icon: 'none'
137 });
138 } finally {
139 loading.value = false;
140 }
141 };
142
143 onMounted(async () => {
144 // 获取perId
145 const userInfo = userStore.user;
146 if (userInfo && userInfo.perId) {
147 perId.value = userInfo.perId;
148 getMemberInfo();
149 } else {
150 // 如果userInfo中没有perId,尝试通过getAssoPers获取
151 try {
152 const res = await getAssoPers(userInfo?.id || '');
153 perId.value = res.data[10] || '';
154 if (perId.value) {
155 getMemberInfo();
156 } else {
157 uni.showToast({
158 title: '获取用户信息失败',
159 icon: 'none'
160 });
161 }
162 } catch (error) {
163 console.error('获取perId失败:', error);
164 uni.showToast({
165 title: '获取用户信息失败',
166 icon: 'none'
167 });
168 }
169 }
170 });
171 </script>
172
173 <style lang="scss" scoped>
174 .page-container {
175 min-height: 100vh;
176 background: #f5f5f5;
177 padding-bottom: 30rpx;
178 }
179
180 /* 导航栏 */
181 .nav-bar {
182 display: flex;
183 align-items: center;
184 justify-content: space-between;
185 height: 88rpx;
186 background: #ffffff;
187 padding: 0 30rpx;
188 box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
189 position: sticky;
190 top: 0;
191 z-index: 100;
192 }
193
194 .nav-left {
195 width: 44rpx;
196 height: 44rpx;
197 display: flex;
198 align-items: center;
199 justify-content: center;
200 }
201
202 .nav-title {
203 font-size: 32rpx;
204 font-weight: 500;
205 color: #333;
206 }
207
208 .nav-right {
209 width: 44rpx;
210 }
211
212 /* 信息卡片 */
213 .info-card {
214 margin: 20rpx;
215 background: #ffffff;
216 border-radius: 12rpx;
217 box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
218 overflow: hidden;
219 }
220
221 /* 信息项 */
222 .info-item {
223 display: flex;
224 align-items: center;
225 padding: 30rpx 24rpx;
226 border-bottom: 1rpx solid #f0f0f0;
227 }
228
229 .info-item:last-child {
230 border-bottom: none;
231 }
232
233 /* 标签 */
234 .info-label {
235 font-size: 28rpx;
236 color: #666666;
237 width: 200rpx;
238 flex-shrink: 0;
239 }
240
241 /* 值 */
242 .info-value {
243 font-size: 28rpx;
244 color: #333333;
245 flex: 1;
246 padding-left: 20rpx;
247 text-align: left;
248 word-break: break-all;
249 }
250
251 /* 加载状态 */
252 .loading-container {
253 display: flex;
254 flex-direction: column;
255 align-items: center;
256 justify-content: center;
257 height: 500rpx;
258 }
259
260 .loading-icon {
261 animation: spin 1s linear infinite;
262 }
263
264 .loading-text {
265 margin-top: 20rpx;
266 font-size: 28rpx;
267 color: #666;
268 }
269
270 @keyframes spin {
271 from {
272 transform: rotate(0deg);
273 }
274 to {
275 transform: rotate(360deg);
276 }
277 }
278
279 /* 响应式调整 */
280 @media (max-width: 375px) {
281 .info-label {
282 width: 160rpx;
283 font-size: 26rpx;
284 }
285
286 .info-value {
287 font-size: 26rpx;
288 padding-left: 16rpx;
289 }
290
291 .info-item {
292 padding: 24rpx 20rpx;
293 }
294 }
295 </style>
...\ No newline at end of file ...\ No newline at end of file
1 <template>
2 <view class="order-page" :class="{ 'no-scroll': isPopupOpen }">
3 <!-- 订单列表 -->
4 <scroll-view
5 scroll-y
6 class="order-list-scroll"
7 :enhanced="true"
8 :show-scrollbar="false"
9 :scroll-enabled="!isPopupOpen"
10 >
11 <view class="order-list">
12 <!-- 有数据才循环 -->
13 <view v-if="list.length > 0">
14 <view
15 v-for="(item, index) in list"
16 :key="index"
17 class="order-card"
18 >
19 <!-- 订单头部:日期 + 状态 -->
20 <view class="card-header">
21 <view class="date">
22 <image src="/static/calendar@2x.png" v-if="item.payTime" mode="widthFix" style="width:30rpx;height:30rpx;"/>
23 <text class="date-text" v-if="item.payTime">{{ item.payTime }}</text>
24 </view>
25 <view
26 class="status-tag"
27 :class="{
28 success: item.payStatus == 1,
29 danger: item.payStatus == 2,
30 pending: item.payStatus == 0
31 }"
32 >
33 {{ getStatusText(item.payStatus) }}
34 </view>
35 </view>
36
37 <!-- 订单编号、缴费编号 -->
38 <view class="info-row">
39 <text class="label">订单编号:</text>
40 <text class="value">{{ item.tradeNo || '——' }}</text>
41 </view>
42 <view class="info-row">
43 <text class="label">缴费编号:</text>
44 <text class="value">{{ item.wfCode || '——' }}</text>
45 </view>
46
47 <!-- 核心:个人会员仅展示缴费年限 -->
48 <view class="info-section flex f-j-s" v-if="item.content">
49 <view class="single-info">
50 <view class="label">缴费年限:</view>
51 <view class="value">{{ item.content.yearCount || 0 }}</view>
52 </view>
53 <view class="line"></view>
54 <view class="single-info">
55 <view class="label">缴费方式</view>
56 <view class="value">民生付</view>
57 </view>
58 </view>
59
60 <!-- 费用合计 -->
61 <view class="total-row">
62 <text class="label">费用合计:</text>
63 <text class="amount">¥{{ (Number(item.price) || 0).toFixed(2) }}</text>
64 </view>
65
66 <!-- 按钮组:靠右紧凑展示 -->
67 <view class="btn-group">
68 <button class="btn btn-delete" @click="handleDelete(item)">删除</button>
69 <!-- 已缴费:申请开票/已开票 -->
70 <template v-if="item.payStatus == 1">
71 <button class="btn btn-invoice" @click="makeInvoiceFN(item)" :disabled="item.invoiceStatus === 1">
72 {{ item.invoiceStatus === 1 ? '已开票' : '申请开票' }}
73 </button>
74 </template>
75 <!-- 未缴费:去缴费 + 取消订单 -->
76 <template v-if="item.payStatus == 0">
77 <button class="btn btn-cancel" @click="handleCancel(item)">取消订单</button>
78 <button class="btn btn-pay" @click="handlePay(item)">去缴费</button>
79 </template>
80 </view>
81 </view>
82 </view>
83
84 <!-- 空状态 -->
85 <view v-else class="empty">
86 <text class="empty-text">暂无订单记录</text>
87 </view>
88
89 <!-- 加载/无更多提示 -->
90 <view class="loading-tip" v-if="loading">加载中...</view>
91 <view class="no-more" v-if="!loading && !hasMore && list.length">没有更多了</view>
92 </view>
93 </scroll-view>
94
95 <!-- 自定义删除确认弹窗 -->
96 <view v-if="showDelPopup" class="popup-mask" @touchmove.stop.prevent @click.stop="closeDelPopup">
97 <view class="custom-modal" @click.stop>
98 <view class="modal-title">提示</view>
99 <view class="modal-content">{{ delModalContent }}</view>
100 <view class="modal-btns">
101 <button class="modal-btn-cancel" @click="closeDelPopup">取消</button>
102 <button class="modal-btn-confirm" @click="confirmDel">确定</button>
103 </view>
104 </view>
105 </view>
106
107 <!-- 自定义取消订单确认弹窗 -->
108 <view v-if="showCancelPopup" class="popup-mask" @touchmove.stop.prevent @click.stop="closeCancelPopup">
109 <view class="custom-modal" @click.stop>
110 <view class="modal-title">提示</view>
111 <view class="modal-content">{{ cancelModalContent }}</view>
112 <view class="modal-btns">
113 <button class="modal-btn-cancel" @click="closeCancelPopup">取消</button>
114 <button class="modal-btn-confirm" @click="confirmCancel">确定</button>
115 </view>
116 </view>
117 </view>
118 </view>
119 </template>
120
121 <script setup>
122 import { ref, reactive, onMounted,computed } from 'vue';
123 import { onReachBottom } from '@dcloudio/uni-app'
124 import { useUserStore } from "../store/modules/user";
125 import * as api from '@/common/api.js'
126
127 const userStore = useUserStore()
128 // 数据与分页配置
129 const list = ref([]);
130 const loading = ref(false);
131 const hasMore = ref(true);
132 const pageNum = ref(1);
133 const pageSize = ref(10);
134 const userInfo = computed(() => userStore.user)
135 // 查询参数(固定为个人会员类型)
136 const queryParams = reactive({
137 pageNum: 1,
138 pageSize: 10,
139 type: '0', // 0表示个人会员
140 queryType: '1',
141 // payStatus: '',
142 // perId: ''
143 });
144
145 // 弹窗控制
146 const showDelPopup = ref(false);
147 const showCancelPopup = ref(false);
148 const isPopupOpen = ref(false);
149
150 // 弹窗内容
151 const delModalContent = ref('');
152 const cancelModalContent = ref('');
153
154 // 当前操作的订单
155 const currentOrder = ref(null);
156
157 // 页面挂载初始化
158 onMounted(() => {
159 // 获取用户信息
160 // if (userInfo.value && userInfo.value.perId) {
161 // queryParams.perId = userInfo.value.perId;
162 initData();
163 // } else {
164 // uni.showToast({ title: '获取用户信息失败', icon: 'none' });
165 // }
166 });
167
168 // 小程序原生触底加载
169 onReachBottom(() => {
170 if (!loading.value && hasMore.value && !isPopupOpen.value) {
171 pageNum.value++;
172 initData();
173 }
174 });
175
176 // 状态文本映射
177 const getStatusText = (status) => {
178 const map = {
179 0: '待缴费',
180 1: '缴费成功',
181 2: '订单取消'
182 };
183 return map[status] || '未知状态';
184 };
185
186 // 数据请求核心方法
187 const initData = async () => {
188 loading.value = true;
189 queryParams.pageNum = pageNum.value;
190 try {
191 const res = await api.orderList(queryParams);
192 if (!res || !res.rows) {
193 list.value = [];
194 hasMore.value = false;
195 return;
196 }
197 // 安全解析content字段
198 res.rows.forEach(item => {
199 if (item.content) {
200 try {
201 item.content = JSON.parse(item.content);
202 } catch (e) {
203 item.content = null;
204 }
205 }
206 });
207 // 分页拼接数据
208 if (pageNum.value === 1) {
209 list.value = res.rows;
210 } else {
211 list.value.push(...res.rows);
212 }
213 // 判断是否还有更多数据
214 hasMore.value = list.value.length < (res.total || 0);
215 } catch (e) {
216 console.error('订单加载异常:', e);
217 uni.showToast({ title: '加载失败', icon: 'none' });
218 } finally {
219 loading.value = false;
220 }
221 };
222
223 // 删除订单
224 const handleDelete = (item) => {
225 currentOrder.value = item;
226 delModalContent.value = `是否确认删除订单编号为"${item.tradeNo}"的订单?`;
227 showDelPopup.value = true;
228 isPopupOpen.value = true;
229 };
230
231 // 确认删除
232 const confirmDel = async () => {
233 if (!currentOrder.value) return;
234 try {
235 await api.deleteOrder(currentOrder.value.id);
236 uni.showToast({ title: '删除成功', icon: 'success' });
237 pageNum.value = 1;
238 list.value = [];
239 initData();
240 closeDelPopup();
241 } catch (e) {
242 uni.showToast({ title: '删除失败', icon: 'error' });
243 }
244 };
245
246 // 关闭删除弹窗
247 const closeDelPopup = () => {
248 showDelPopup.value = false;
249 isPopupOpen.value = false;
250 currentOrder.value = null;
251 };
252
253 // 去缴费
254 const handlePay = async (item) => {
255 if (item.payStatus !== 0) return;
256 try {
257 await api.goPay({ id: item.id });
258 uni.navigateTo({ url: `/pages/pay/pay?orderId=${item.id}` });
259 } catch (e) {
260 uni.showToast({ title: '发起支付失败', icon: 'none' });
261 }
262 };
263
264 // 申请开票
265 const makeInvoiceFN = (item) => {
266 uni.navigateTo({ url: `/pages/invoice/apply?orderId=${item.id}amount=${item.price}` });
267 };
268
269 // 取消订单
270 const handleCancel = (item) => {
271 currentOrder.value = item;
272 cancelModalContent.value = `是否确认取消订单编号为"${item.tradeNo}"的订单?`;
273 showCancelPopup.value = true;
274 isPopupOpen.value = true;
275 };
276
277 // 确认取消订单
278 const confirmCancel = async () => {
279 if (!currentOrder.value) return;
280 try {
281 await api.cancelPay(currentOrder.value.id);
282 uni.showToast({ title: '取消成功', icon: 'success' });
283 pageNum.value = 1;
284 list.value = [];
285 initData();
286 closeCancelPopup();
287 } catch (e) {
288 uni.showToast({ title: '取消失败', icon: 'error' });
289 }
290 };
291
292 // 关闭取消订单弹窗
293 const closeCancelPopup = () => {
294 showCancelPopup.value = false;
295 isPopupOpen.value = false;
296 currentOrder.value = null;
297 };
298 </script>
299
300 <style lang="scss" scoped>
301 .order-page {
302 background: #f5f7fa;
303 min-height: 100vh;
304 display: flex;
305 flex-direction: column;
306
307 &.no-scroll {
308 overflow: hidden;
309 height: 100vh;
310 }
311 }
312
313 // 滚动列表容器
314 .order-list-scroll {
315 flex: 1;
316 height: 0;
317 }
318
319 // 订单列表
320 .order-list {
321 padding: 20rpx;
322
323 .order-card {
324 background: #fff;
325 margin-bottom: 20rpx;
326 padding: 20rpx;
327 box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
328 border-top: 6rpx solid transparent;
329 background-clip: padding-box, border-box;
330 background-origin: padding-box, border-box;
331 background-image: linear-gradient(#fff, #fff), linear-gradient(90deg, #FF755A, #F51722);
332 }
333 }
334
335 // 卡片头部
336 .card-header {
337 display: flex;
338 justify-content: space-between;
339 align-items: center;
340 padding-bottom: 20rpx;
341 margin-bottom: 20rpx;
342 border-bottom: 1rpx dashed #eee;
343
344 .date {
345 display: flex;
346 align-items: center;
347 gap: 8rpx;
348 font-size: 26rpx;
349
350 .date-text {
351 color: #666;
352 }
353 }
354
355 .status-tag {
356 font-size: 24rpx;
357 padding: 6rpx 16rpx;
358 border-radius: 20rpx;
359
360 &.success {
361 background: #e6f7ef;
362 color: #52c41a;
363 }
364
365 &.danger {
366 background: #fff1f0;
367 color: #ff4d4f;
368 }
369
370 &.pending {
371 background: #f5f5f5;
372 color: #999;
373 }
374 }
375 }
376
377 // 基础信息行
378 .info-row {
379 display: flex;
380 align-items: center;
381 margin-bottom: 20rpx;
382 font-size: 26rpx;
383
384 .label {
385 color: #999;
386 flex-shrink: 0;
387 width: 140rpx;
388 }
389
390 .value {
391 color: #333;
392 word-break: break-all;
393 }
394 }
395
396 .info-section {
397 background: #f3f6fc;
398 display: flex;
399 align-items: center;
400 padding: 0 40rpx;
401 justify-content: space-around;
402 margin: 20rpx 0;
403 }
404 .line{
405 width: 1rpx;
406 height: 90%;
407 background: #eee;
408 }
409 .single-info {
410 padding: 16rpx 20rpx;
411 border-radius: 8rpx;
412 font-size: 26rpx;
413 .label {
414 color: #999;
415 text-align: center;
416 }
417
418 .value {
419 color: #333;
420 font-weight: 500;
421 text-align: center;
422 margin-top: 10rpx;
423 }
424 }
425
426 // 费用合计
427 .total-row {
428 display: flex;
429 justify-content: space-between;
430 align-items: center;
431 margin: 0 0 30rpx;
432 padding: 15rpx 0;
433 font-size: 28rpx;
434 border-bottom: 1rpx dashed #eee;
435
436 .label {
437 color: #333;
438 }
439
440 .amount {
441 color: #EB6100;
442 font-weight: 600;
443 font-size: 32rpx;
444 }
445 }
446
447 // 按钮组
448 .btn-group {
449 display: flex;
450 justify-content: flex-end;
451 align-items: center;
452 gap: 16rpx;
453 width: 100%;
454
455 .btn {
456 padding: 12rpx 32rpx;
457 border-radius: 40rpx;
458 font-size: 24rpx;
459 line-height: 1.5;
460 white-space: nowrap;
461 display: inline-block;
462 margin: 0;
463 border: none;
464 width: 80px;
465 background: transparent;
466
467 &::after {
468 border: none;
469 }
470
471 &.btn-delete {
472 background: #fff;
473 color: #e4393c;
474 border: 1rpx solid #e4393c;
475 }
476
477 &.btn-invoice {
478 background: #fff;
479 color: #e4393c;
480 border: 1rpx solid #e4393c;
481 }
482
483 &.btn-cancel {
484 background: #fff;
485 color: #666;
486 border: 1rpx solid #ccc;
487 }
488
489 &.btn-pay {
490 background: linear-gradient(90deg, #FF755A, #F51722);
491 color: #fff;
492 border: none;
493 }
494
495 &:disabled {
496 opacity: 0.6;
497 pointer-events: none;
498 }
499 }
500 }
501
502 // 空状态
503 .empty {
504 display: flex;
505 justify-content: center;
506 align-items: center;
507 padding: 120rpx 0;
508
509 .empty-text {
510 color: #999;
511 font-size: 28rpx;
512 }
513 }
514
515 // 加载/无更多提示
516 .loading-tip, .no-more {
517 text-align: center;
518 padding: 20rpx 0;
519 color: #999;
520 font-size: 26rpx;
521 }
522
523 // 弹窗遮罩层
524 .popup-mask {
525 position: fixed;
526 top: 0;
527 left: 0;
528 right: 0;
529 bottom: 0;
530 background-color: rgba(0, 0, 0, 0.5);
531 display: flex;
532 align-items: center;
533 justify-content: center;
534 z-index: 999;
535 }
536
537 // 自定义弹窗样式
538 .custom-modal {
539 width: 600rpx;
540 background: #fff;
541 border-radius: 20rpx;
542 padding: 40rpx 30rpx;
543 box-sizing: border-box;
544 text-align: center;
545 box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.2);
546 }
547
548 .modal-title {
549 font-size: 36rpx;
550 font-weight: 600;
551 color: #333;
552 margin-bottom: 30rpx;
553 }
554
555 .modal-content {
556 font-size: 30rpx;
557 color: #666;
558 line-height: 1.6;
559 margin-bottom: 40rpx;
560 word-break: break-word;
561 }
562
563 .modal-btns {
564 display: flex;
565 justify-content: space-between;
566 gap: 20rpx;
567 }
568
569 .modal-btn-cancel {
570 flex: 1;
571 height: 80rpx;
572 line-height: 80rpx;
573 background: #f5f5f5;
574 color: #666;
575 border-radius: 40rpx;
576 font-size: 32rpx;
577 border: none;
578 margin: 0;
579 padding: 0;
580
581 &::after {
582 border: none;
583 }
584 }
585
586 .modal-btn-confirm {
587 flex: 1;
588 height: 80rpx;
589 line-height: 80rpx;
590 background: #C4121B;
591 color: #fff;
592 border-radius: 40rpx;
593 font-size: 32rpx;
594 border: none;
595 margin: 0;
596 padding: 0;
597
598 &::after {
599 border: none;
600 }
601 }
602 </style>
...\ No newline at end of file ...\ No newline at end of file
1 <template>
2 <view class="page-container">
3
4
5 <!-- 信息展示区域 -->
6 <view class="info-section">
7 <view class="info-item">
8 <view class="info-label">姓名</view>
9 <view class="info-value">{{ perInfo?.perName || '' }}</view>
10 </view>
11 <!-- <view class="info-item">
12 <view class="info-label">证件类型</view>
13 <view class="info-value">{{ getCertType(perInfo?.idcType) }}</view>
14 </view> -->
15 <view class="info-item">
16 <view class="info-label">身份证号</view>
17 <view class="info-value">{{ perInfo?.perIdcCode || '--' }}</view>
18 </view>
19 <view class="info-item">
20 <view class="info-label">生日</view>
21 <view class="info-value">{{ perInfo?.birth || '--' }}</view>
22 </view>
23 <view class="info-item">
24 <view class="info-label">会员卡号</view>
25 <view class="info-value">{{ perInfo?.perCode || '--' }}</view>
26 </view>
27 <view class="info-item">
28 <view class="info-label">会员有效期</view>
29 <view class="info-value">{{ perInfo?.perValidDate || '--' }}</view>
30 </view>
31 <!-- <view class="info-item">
32 <view class="info-label">性别</view>
33 <view class="info-value">{{ getGender(perInfo?.gender) }}</view>
34 </view>
35 <view class="info-item">
36 <view class="info-label">民族</view>
37 <view class="info-value">{{ perInfo?.nation || '--' }}</view>
38 </view>
39 <view class="info-item">
40 <view class="info-label">联系电话</view>
41 <view class="info-value">{{ perInfo?.phone || '--' }}</view>
42 </view>
43 <view class="info-item">
44 <view class="info-label">邮箱</view>
45 <view class="info-value">{{ perInfo?.email || '--' }}</view>
46 </view> -->
47 <!-- <view class="info-item">
48 <view class="info-label">地址</view>
49 <view class="info-value">{{ perInfo?.address || '--' }}</view>
50 </view> -->
51 </view>
52 </view>
53 </template>
54
55 <script setup>
56 import { computed, onMounted } from 'vue';
57 import { useUserStore } from '../store/modules/user';
58
59 const userStore = useUserStore();
60 const perInfo = computed(() => userStore.perInfo);
61
62 // 返回上一页
63 const goBack = () => {
64 uni.navigateBack();
65 };
66
67 // 获取证件类型
68 const getCertType = (type) => {
69 switch (type) {
70 case '1':
71 return '身份证';
72 case '2':
73 return '护照';
74 case '3':
75 return '军官证';
76 case '4':
77 return '港澳通行证';
78 case '5':
79 return '台湾通行证';
80 default:
81 return '--';
82 }
83 };
84
85 // 获取性别
86 const getGender = (gender) => {
87 switch (gender) {
88 case '1':
89 return '男';
90 case '2':
91 return '女';
92 default:
93 return '--';
94 }
95 };
96
97 onMounted(() => {
98 // 可以在这里添加额外的初始化逻辑
99 });
100 </script>
101
102 <style lang="scss" scoped>
103 .page-container {
104 min-height: 100vh;
105 background: #f5f5f5;
106 }
107
108 /* 导航栏 */
109 .nav-bar {
110 display: flex;
111 align-items: center;
112 justify-content: space-between;
113 height: 88rpx;
114 background: #ffffff;
115 padding: 0 30rpx;
116 box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
117 position: sticky;
118 top: 0;
119 z-index: 100;
120 }
121
122 .nav-left {
123 width: 44rpx;
124 height: 44rpx;
125 display: flex;
126 align-items: center;
127 justify-content: center;
128 }
129
130 .nav-title {
131 font-size: 32rpx;
132 font-weight: 500;
133 color: #333;
134 }
135
136 .nav-right {
137 width: 44rpx;
138 }
139
140 /* 信息展示区域 */
141 .info-section {
142 margin: 20rpx;
143 background: #ffffff;
144 }
145
146 .info-item {
147 display: flex;
148 align-items: center;
149 justify-content: space-between;
150 padding: 30rpx;
151 border-bottom: 1rpx solid #f5f5f5;
152 }
153
154 .info-item:last-child {
155 border-bottom: none;
156 }
157
158 .info-label {
159 font-size: 28rpx;
160 color: #666;
161 width: 150rpx;
162 }
163
164 .info-value {
165 font-size: 28rpx;
166 color: #333;
167 flex: 1;
168 text-align: right;
169 padding-left: 30rpx;
170 }
171 </style>
...\ No newline at end of file ...\ No newline at end of file
static/bd@2x.png

711 Bytes

Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!