我的订单
Showing
24 changed files
with
3038 additions
and
201 deletions
| ... | @@ -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 | ... | ... |
myCenter/order.vue
0 → 100644
| 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": "审核详情", | ... | ... |
pages/invoice/apply.vue
0 → 100644
| 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 |
pages/webview/webview.vue
0 → 100644
| 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 | ... | ... |
personal/levelRecord.vue
0 → 100644
| 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 |
personal/memberInfo.vue
0 → 100644
| 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 |
personal/order.vue
0 → 100644
| 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 |
personal/personInfo.vue
0 → 100644
| 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/arrow@2x.png
0 → 100644
275 Bytes
static/bd@2x.png
0 → 100644
711 Bytes
static/btn01@2x.png
0 → 100644
2.5 KB
static/btn02@2x.png
0 → 100644
3.47 KB
static/btn03@2x.png
0 → 100644
2.31 KB
static/calendar@2x.png
0 → 100644
507 Bytes
static/end@2x.png
0 → 100644
18 KB
static/user_01@2x.png
0 → 100644
382 KB
static/user_icon01@2x.png
0 → 100644
1.14 KB
static/user_icon02@2x.png
0 → 100644
1.79 KB
static/user_icon03@2x.png
0 → 100644
2.1 KB
-
Please register or sign in to post a comment