费用结算+考点审核+证书邮寄+会员审核
Showing
19 changed files
with
3907 additions
and
2 deletions
| ... | @@ -1684,3 +1684,65 @@ export function editAddressOrder(examId, addressId) { | ... | @@ -1684,3 +1684,65 @@ export function editAddressOrder(examId, addressId) { |
| 1684 | method: 'put' | 1684 | method: 'put' |
| 1685 | }) | 1685 | }) |
| 1686 | } | 1686 | } |
| 1687 | /** | ||
| 1688 | * 查询证书列表 | ||
| 1689 | * @param query | ||
| 1690 | * @returns {*} | ||
| 1691 | */ | ||
| 1692 | export function certsLList(query) { | ||
| 1693 | return request({ | ||
| 1694 | url: '/exam/payment/certsList', | ||
| 1695 | method: 'get', | ||
| 1696 | params: query | ||
| 1697 | }) | ||
| 1698 | } | ||
| 1699 | |||
| 1700 | /** | ||
| 1701 | * 段位考试成绩列表 | ||
| 1702 | * @param params | ||
| 1703 | * @returns {*} | ||
| 1704 | */ | ||
| 1705 | export function getRankScoreList(params) { | ||
| 1706 | return request({ | ||
| 1707 | url: '/exam/info/rank/scoreList', | ||
| 1708 | method: 'get', | ||
| 1709 | params: params | ||
| 1710 | }) | ||
| 1711 | } | ||
| 1712 | |||
| 1713 | /** | ||
| 1714 | * 证书邮寄 | ||
| 1715 | * @param ids | ||
| 1716 | * @returns {*} | ||
| 1717 | */ | ||
| 1718 | export function postCert(ids) { | ||
| 1719 | return request({ | ||
| 1720 | url: `/exam/payment/postCert/${ids}`, | ||
| 1721 | method: 'post' | ||
| 1722 | }) | ||
| 1723 | } | ||
| 1724 | |||
| 1725 | /** | ||
| 1726 | * 查看物流信息 | ||
| 1727 | * @param id | ||
| 1728 | * @returns {*} | ||
| 1729 | */ | ||
| 1730 | export function queryTrace(id) { | ||
| 1731 | return request({ | ||
| 1732 | url: `/exam/payment/queryTrace/${id}`, | ||
| 1733 | method: 'get' | ||
| 1734 | }) | ||
| 1735 | } | ||
| 1736 | |||
| 1737 | /** | ||
| 1738 | * 获取考试详情 | ||
| 1739 | * @param examId | ||
| 1740 | * @returns {*} | ||
| 1741 | */ | ||
| 1742 | export function getExamInfo(examId) { | ||
| 1743 | return request({ | ||
| 1744 | url: `/exam/info/${examId}`, | ||
| 1745 | method: 'get' | ||
| 1746 | }) | ||
| 1747 | } | ||
| 1748 | ... | ... |
| ... | @@ -62,3 +62,242 @@ export function getRankScoreList(params) { | ... | @@ -62,3 +62,242 @@ export function getRankScoreList(params) { |
| 62 | params: params | 62 | params: params |
| 63 | }) | 63 | }) |
| 64 | } | 64 | } |
| 65 | |||
| 66 | /** | ||
| 67 | * 证书邮寄 | ||
| 68 | * @param ids | ||
| 69 | * @returns {*} | ||
| 70 | */ | ||
| 71 | export function postCert(ids) { | ||
| 72 | return request({ | ||
| 73 | url: `/exam/payment/postCert/${ids}`, | ||
| 74 | method: 'post' | ||
| 75 | }) | ||
| 76 | } | ||
| 77 | |||
| 78 | /** | ||
| 79 | * 查看物流信息 | ||
| 80 | * @param id | ||
| 81 | * @returns {*} | ||
| 82 | */ | ||
| 83 | export function queryTrace(id) { | ||
| 84 | return request({ | ||
| 85 | url: `/exam/payment/queryTrace/${id}`, | ||
| 86 | method: 'get' | ||
| 87 | }) | ||
| 88 | } | ||
| 89 | |||
| 90 | /** | ||
| 91 | * 获取考试详情 | ||
| 92 | * @param examId | ||
| 93 | * @returns {*} | ||
| 94 | */ | ||
| 95 | export function getExamInfo(examId) { | ||
| 96 | return request({ | ||
| 97 | url: `/exam/info/${examId}`, | ||
| 98 | method: 'get' | ||
| 99 | }) | ||
| 100 | } | ||
| 101 | |||
| 102 | /** | ||
| 103 | * 获取考生列表 | ||
| 104 | * @param params | ||
| 105 | * @returns {*} | ||
| 106 | */ | ||
| 107 | export function getStudentList(params) { | ||
| 108 | return request({ | ||
| 109 | url: '/exam/person/list', | ||
| 110 | method: 'get', | ||
| 111 | params: params | ||
| 112 | }) | ||
| 113 | } | ||
| 114 | |||
| 115 | /** | ||
| 116 | * 缴费单列表 | ||
| 117 | * @param query | ||
| 118 | * @returns {*} | ||
| 119 | */ | ||
| 120 | export function paymentList(query) { | ||
| 121 | return request({ | ||
| 122 | url: '/exam/payment/list', | ||
| 123 | method: 'get', | ||
| 124 | params: query | ||
| 125 | }) | ||
| 126 | } | ||
| 127 | |||
| 128 | /** | ||
| 129 | * 获取审核记录 | ||
| 130 | * @param examId | ||
| 131 | * @param type | ||
| 132 | * @returns {*} | ||
| 133 | */ | ||
| 134 | export function getLogs(examId, type) { | ||
| 135 | return request({ | ||
| 136 | url: `/exam/info/getLogs/${examId}/${type}`, | ||
| 137 | method: 'get' | ||
| 138 | }) | ||
| 139 | } | ||
| 140 | |||
| 141 | /** | ||
| 142 | * 考点审核列表 | ||
| 143 | * @param query | ||
| 144 | * @returns {*} | ||
| 145 | */ | ||
| 146 | export function listInfo(query) { | ||
| 147 | return request({ | ||
| 148 | url: '/member/examPointApply/list', | ||
| 149 | method: 'get', | ||
| 150 | params: query | ||
| 151 | }) | ||
| 152 | } | ||
| 153 | |||
| 154 | /** | ||
| 155 | * 考点审核 | ||
| 156 | * @param params | ||
| 157 | * @returns {*} | ||
| 158 | */ | ||
| 159 | export function ztxAudit(params) { | ||
| 160 | return request({ | ||
| 161 | url: `/member/examPointApply/audit/${params.ids}`, | ||
| 162 | method: 'post', | ||
| 163 | params | ||
| 164 | }) | ||
| 165 | } | ||
| 166 | |||
| 167 | /** | ||
| 168 | * 获取机构资料 | ||
| 169 | * @param memId | ||
| 170 | * @returns {*} | ||
| 171 | */ | ||
| 172 | export function getInstitutionInfo(memId) { | ||
| 173 | return request({ | ||
| 174 | url: `/groupMember/authentication/info/${memId}`, | ||
| 175 | method: 'get' | ||
| 176 | }) | ||
| 177 | } | ||
| 178 | |||
| 179 | /** | ||
| 180 | * 会员审核列表 | ||
| 181 | * @param params | ||
| 182 | * @returns {*} | ||
| 183 | */ | ||
| 184 | export function certifiedNewList(params) { | ||
| 185 | return request({ | ||
| 186 | url: `/system/certifiedNew/list`, | ||
| 187 | method: 'get', | ||
| 188 | params | ||
| 189 | }) | ||
| 190 | } | ||
| 191 | |||
| 192 | /** | ||
| 193 | * 会员审核 | ||
| 194 | * @param params | ||
| 195 | * @returns {*} | ||
| 196 | */ | ||
| 197 | export function shenAudit(params) { | ||
| 198 | return request({ | ||
| 199 | url: `/system/certifiedNew/shenAudit/${params.ids}`, | ||
| 200 | method: 'post', | ||
| 201 | params | ||
| 202 | }) | ||
| 203 | } | ||
| 204 | |||
| 205 | /** | ||
| 206 | * 获取审核日志 | ||
| 207 | * @param id | ||
| 208 | * @returns {*} | ||
| 209 | */ | ||
| 210 | export function getAuditLogs(id) { | ||
| 211 | return request({ | ||
| 212 | url: `/system/config/getLogs/${id}`, | ||
| 213 | method: 'get' | ||
| 214 | }) | ||
| 215 | } | ||
| 216 | |||
| 217 | /** | ||
| 218 | * 获取会员审核日志 | ||
| 219 | * @param id | ||
| 220 | * @returns {*} | ||
| 221 | */ | ||
| 222 | export function certifiedNewGetLogs(id) { | ||
| 223 | return request({ | ||
| 224 | url: `/system/certifiedNew/getLogs/${id}`, | ||
| 225 | method: 'get' | ||
| 226 | }) | ||
| 227 | } | ||
| 228 | |||
| 229 | /** | ||
| 230 | * 结算列表 | ||
| 231 | * @param params | ||
| 232 | * @returns {*} | ||
| 233 | */ | ||
| 234 | export function settlementList(params) { | ||
| 235 | return request({ | ||
| 236 | url: `/exam/paymentSubmit/list`, | ||
| 237 | method: 'get', | ||
| 238 | params | ||
| 239 | }) | ||
| 240 | } | ||
| 241 | |||
| 242 | /** | ||
| 243 | * 结算详情 | ||
| 244 | * @param id | ||
| 245 | * @returns {*} | ||
| 246 | */ | ||
| 247 | export function settlementInfo(id) { | ||
| 248 | return request({ | ||
| 249 | url: `/exam/paymentSubmit/info/${id}`, | ||
| 250 | method: 'get' | ||
| 251 | }) | ||
| 252 | } | ||
| 253 | |||
| 254 | /** | ||
| 255 | * 结算审核 | ||
| 256 | * @param params | ||
| 257 | * @returns {*} | ||
| 258 | */ | ||
| 259 | export function settlementAudit(params) { | ||
| 260 | return request({ | ||
| 261 | url: `/exam/paymentSubmit/audit/${params.ids}`, | ||
| 262 | method: 'post', | ||
| 263 | params | ||
| 264 | }) | ||
| 265 | } | ||
| 266 | |||
| 267 | /** | ||
| 268 | * 结算申请列表(用于新建结算申请) | ||
| 269 | * @param params | ||
| 270 | * @returns {*} | ||
| 271 | */ | ||
| 272 | export function settlementApplyList(params) { | ||
| 273 | return request({ | ||
| 274 | url: `/exam/payment/list`, | ||
| 275 | method: 'get', | ||
| 276 | params | ||
| 277 | }) | ||
| 278 | } | ||
| 279 | |||
| 280 | /** | ||
| 281 | * 提交结算申请 | ||
| 282 | * @param data | ||
| 283 | * @returns {*} | ||
| 284 | */ | ||
| 285 | export function settlementCommit(data) { | ||
| 286 | return request({ | ||
| 287 | url: `/exam/paymentSubmit/commit`, | ||
| 288 | method: 'post', | ||
| 289 | params: data | ||
| 290 | }) | ||
| 291 | } | ||
| 292 | |||
| 293 | /** | ||
| 294 | * 结算确认 - 获取费用明细 | ||
| 295 | * @param ids | ||
| 296 | * @returns {*} | ||
| 297 | */ | ||
| 298 | export function settlementConfirm(ids) { | ||
| 299 | return request({ | ||
| 300 | url: `/exam/paymentSubmit/confirm/${ids}`, | ||
| 301 | method: 'post' | ||
| 302 | }) | ||
| 303 | } | ... | ... |
| ... | @@ -119,7 +119,7 @@ page { | ... | @@ -119,7 +119,7 @@ page { |
| 119 | .pd30{padding: 30rpx;box-sizing: border-box;} | 119 | .pd30{padding: 30rpx;box-sizing: border-box;} |
| 120 | 120 | ||
| 121 | .appList{width: 700rpx;margin:30rpx auto; | 121 | .appList{width: 700rpx;margin:30rpx auto; |
| 122 | .appItem{background: #FFFFFF;padding: 20rpx 30rpx 30rpx;margin-bottom: 30rpx; | 122 | .appItem{background: #eb7c7c;padding: 20rpx 30rpx 30rpx;margin-bottom: 30rpx; |
| 123 | box-shadow: 0rpx 12rpx 116rpx 0rpx rgba(196,203,214,0.1); | 123 | box-shadow: 0rpx 12rpx 116rpx 0rpx rgba(196,203,214,0.1); |
| 124 | border-radius: 15rpx;position: relative; | 124 | border-radius: 15rpx;position: relative; |
| 125 | .iconbox{position: absolute;left: 20rpx;} | 125 | .iconbox{position: absolute;left: 20rpx;} | ... | ... |
level/ztx/certDetail.vue
0 → 100644
This diff is collapsed.
Click to expand it.
level/ztx/certLogistics.vue
0 → 100644
| 1 | <template> | ||
| 2 | <view class="logistics-page"> | ||
| 3 | <!-- 物流信息卡片 --> | ||
| 4 | <view class="logistics-info-card"> | ||
| 5 | <view class="info-header"> | ||
| 6 | <uni-icons type=" truck" size="20" color="#AD181F"></uni-icons> | ||
| 7 | <text class="header-title">物流信息</text> | ||
| 8 | </view> | ||
| 9 | <view class="info-content"> | ||
| 10 | <view class="info-row"> | ||
| 11 | <text class="label">运单号</text> | ||
| 12 | <text class="value tracking-number" @click="copyTracking">{{ currentItem.postCode || '-' }} | ||
| 13 | <text class="copy-btn">复制</text> | ||
| 14 | </text> | ||
| 15 | </view> | ||
| 16 | <view class="info-row"> | ||
| 17 | <text class="label">当前状态</text> | ||
| 18 | <text class="value status-sended" v-if="currentItem.postStatus == 1">已邮寄</text> | ||
| 19 | <text class="value status-pending" v-else>未邮寄</text> | ||
| 20 | </view> | ||
| 21 | <view class="info-row"> | ||
| 22 | <text class="label">邮寄时间</text> | ||
| 23 | <text class="value">{{ currentItem.submitTime ? formatDateTime(currentItem.submitTime) : '-' }}</text> | ||
| 24 | </view> | ||
| 25 | </view> | ||
| 26 | </view> | ||
| 27 | |||
| 28 | <!-- 物流时间线 --> | ||
| 29 | <view class="timeline-section"> | ||
| 30 | <view class="section-header"> | ||
| 31 | <uni-icons type="location-filled" size="18" color="#AD181F"></uni-icons> | ||
| 32 | <text class="section-title">运输轨迹</text> | ||
| 33 | </view> | ||
| 34 | |||
| 35 | <view class="loading-wrap" v-if="loading"> | ||
| 36 | <uni-load-more status="loading"></uni-load-more> | ||
| 37 | </view> | ||
| 38 | |||
| 39 | <view class="timeline-wrap" v-else> | ||
| 40 | <view class="timeline-list" v-if="trackingNodes.length > 0"> | ||
| 41 | <view | ||
| 42 | class="timeline-item" | ||
| 43 | :class="{ first: idx === 0 }" | ||
| 44 | v-for="(node, idx) in trackingNodes" | ||
| 45 | :key="idx" | ||
| 46 | > | ||
| 47 | <view class="timeline-left"> | ||
| 48 | <view class="timeline-dot"> | ||
| 49 | <uni-icons v-if="idx === 0" type="check" size="12" color="#fff"></uni-icons> | ||
| 50 | </view> | ||
| 51 | <view class="timeline-line" v-if="idx < trackingNodes.length - 1"></view> | ||
| 52 | </view> | ||
| 53 | <view class="timeline-right"> | ||
| 54 | <view class="timeline-content"> | ||
| 55 | <view class="timeline-title">{{ node.categoryName }}</view> | ||
| 56 | <view class="timeline-time">{{ node.operationTime }}</view> | ||
| 57 | <view class="timeline-desc">{{ node.operationRemark }}</view> | ||
| 58 | </view> | ||
| 59 | </view> | ||
| 60 | </view> | ||
| 61 | </view> | ||
| 62 | |||
| 63 | <view class="no-logistics" v-else> | ||
| 64 | <image mode="aspectFit" src="/static/nodata.png"></image> | ||
| 65 | <text>暂无物流信息</text> | ||
| 66 | </view> | ||
| 67 | </view> | ||
| 68 | </view> | ||
| 69 | </view> | ||
| 70 | </template> | ||
| 71 | |||
| 72 | <script setup> | ||
| 73 | import * as api from '@/common/api.js' | ||
| 74 | import { ref } from 'vue' | ||
| 75 | import { onLoad } from '@dcloudio/uni-app' | ||
| 76 | |||
| 77 | const loading = ref(false) | ||
| 78 | const payId = ref('') | ||
| 79 | const currentItem = ref({}) | ||
| 80 | const trackingNodes = ref([]) | ||
| 81 | |||
| 82 | onLoad((options) => { | ||
| 83 | if (options.payId) { | ||
| 84 | payId.value = options.payId | ||
| 85 | if (options.postCode) currentItem.value.postCode = options.postCode | ||
| 86 | if (options.postStatus) currentItem.value.postStatus = parseInt(options.postStatus) | ||
| 87 | if (options.submitTime) currentItem.value.submitTime = options.submitTime | ||
| 88 | getLogisticsInfo() | ||
| 89 | } | ||
| 90 | }) | ||
| 91 | |||
| 92 | function getLogisticsInfo() { | ||
| 93 | if (!payId.value) return | ||
| 94 | |||
| 95 | loading.value = true | ||
| 96 | api.queryTrace(payId.value).then(res => { | ||
| 97 | loading.value = false | ||
| 98 | trackingNodes.value = res.data || [] | ||
| 99 | }).catch(err => { | ||
| 100 | loading.value = false | ||
| 101 | console.error('获取物流信息失败', err) | ||
| 102 | uni.showToast({ title: '获取物流信息失败', icon: 'none' }) | ||
| 103 | }) | ||
| 104 | } | ||
| 105 | |||
| 106 | function copyTracking() { | ||
| 107 | if (!currentItem.value.postCode) return | ||
| 108 | uni.setClipboardData({ | ||
| 109 | data: currentItem.value.postCode, | ||
| 110 | success: () => { | ||
| 111 | uni.showToast({ title: '已复制', icon: 'success' }) | ||
| 112 | } | ||
| 113 | }) | ||
| 114 | } | ||
| 115 | |||
| 116 | function formatDateTime(dateStr) { | ||
| 117 | if (!dateStr) return '-' | ||
| 118 | return dateStr.replace('T', ' ').substring(0, 19) | ||
| 119 | } | ||
| 120 | </script> | ||
| 121 | |||
| 122 | <style lang="scss" scoped> | ||
| 123 | .logistics-page { | ||
| 124 | min-height: 100vh; | ||
| 125 | background-color: #f5f5f5; | ||
| 126 | padding: 20rpx; | ||
| 127 | padding-bottom: 40rpx; | ||
| 128 | } | ||
| 129 | |||
| 130 | /* 物流信息卡片 */ | ||
| 131 | .logistics-info-card { | ||
| 132 | background-color: #fff; | ||
| 133 | border-radius: 16rpx; | ||
| 134 | padding: 30rpx; | ||
| 135 | margin-bottom: 20rpx; | ||
| 136 | } | ||
| 137 | |||
| 138 | .info-header { | ||
| 139 | display: flex; | ||
| 140 | align-items: center; | ||
| 141 | margin-bottom: 24rpx; | ||
| 142 | |||
| 143 | .header-title { | ||
| 144 | font-size: 30rpx; | ||
| 145 | font-weight: 600; | ||
| 146 | color: #333; | ||
| 147 | margin-left: 10rpx; | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | .info-content { | ||
| 152 | .info-row { | ||
| 153 | display: flex; | ||
| 154 | justify-content: space-between; | ||
| 155 | align-items: center; | ||
| 156 | padding: 16rpx 0; | ||
| 157 | border-bottom: 1px solid #f0f0f0; | ||
| 158 | |||
| 159 | &:last-child { | ||
| 160 | border-bottom: none; | ||
| 161 | } | ||
| 162 | |||
| 163 | .label { | ||
| 164 | font-size: 26rpx; | ||
| 165 | color: #999; | ||
| 166 | } | ||
| 167 | |||
| 168 | .value { | ||
| 169 | font-size: 26rpx; | ||
| 170 | color: #333; | ||
| 171 | |||
| 172 | &.status-sended { | ||
| 173 | color: #4caf50; | ||
| 174 | } | ||
| 175 | |||
| 176 | &.status-pending { | ||
| 177 | color: #ff9800; | ||
| 178 | } | ||
| 179 | |||
| 180 | &.tracking-number { | ||
| 181 | display: flex; | ||
| 182 | align-items: center; | ||
| 183 | gap: 10rpx; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 187 | .copy-btn { | ||
| 188 | font-size: 22rpx; | ||
| 189 | color: #AD181F; | ||
| 190 | background-color: #fef0f0; | ||
| 191 | padding: 4rpx 12rpx; | ||
| 192 | border-radius: 16rpx; | ||
| 193 | } | ||
| 194 | } | ||
| 195 | } | ||
| 196 | |||
| 197 | /* 时间线 */ | ||
| 198 | .timeline-section { | ||
| 199 | background-color: #fff; | ||
| 200 | border-radius: 16rpx; | ||
| 201 | padding: 30rpx; | ||
| 202 | } | ||
| 203 | |||
| 204 | .section-header { | ||
| 205 | display: flex; | ||
| 206 | align-items: center; | ||
| 207 | margin-bottom: 30rpx; | ||
| 208 | |||
| 209 | .section-title { | ||
| 210 | font-size: 30rpx; | ||
| 211 | font-weight: 600; | ||
| 212 | color: #333; | ||
| 213 | margin-left: 10rpx; | ||
| 214 | } | ||
| 215 | } | ||
| 216 | |||
| 217 | .loading-wrap { | ||
| 218 | padding: 60rpx 0; | ||
| 219 | text-align: center; | ||
| 220 | } | ||
| 221 | |||
| 222 | .timeline-wrap { | ||
| 223 | .timeline-list { | ||
| 224 | padding-left: 10rpx; | ||
| 225 | } | ||
| 226 | |||
| 227 | .timeline-item { | ||
| 228 | display: flex; | ||
| 229 | position: relative; | ||
| 230 | |||
| 231 | &.first { | ||
| 232 | .timeline-dot { | ||
| 233 | background-color: #AD181F; | ||
| 234 | border-color: #AD181F; | ||
| 235 | } | ||
| 236 | |||
| 237 | .timeline-title { | ||
| 238 | color: #AD181F; | ||
| 239 | } | ||
| 240 | } | ||
| 241 | } | ||
| 242 | |||
| 243 | .timeline-left { | ||
| 244 | display: flex; | ||
| 245 | flex-direction: column; | ||
| 246 | align-items: center; | ||
| 247 | margin-right: 20rpx; | ||
| 248 | } | ||
| 249 | |||
| 250 | .timeline-dot { | ||
| 251 | width: 28rpx; | ||
| 252 | height: 28rpx; | ||
| 253 | border-radius: 50%; | ||
| 254 | border: 2px solid #ccc; | ||
| 255 | background-color: #fff; | ||
| 256 | display: flex; | ||
| 257 | align-items: center; | ||
| 258 | justify-content: center; | ||
| 259 | flex-shrink: 0; | ||
| 260 | z-index: 1; | ||
| 261 | } | ||
| 262 | |||
| 263 | .timeline-line { | ||
| 264 | width: 2rpx; | ||
| 265 | flex: 1; | ||
| 266 | background-color: #e0e0e0; | ||
| 267 | margin: 8rpx 0; | ||
| 268 | min-height: 60rpx; | ||
| 269 | } | ||
| 270 | |||
| 271 | .timeline-right { | ||
| 272 | flex: 1; | ||
| 273 | padding-bottom: 40rpx; | ||
| 274 | } | ||
| 275 | |||
| 276 | .timeline-content { | ||
| 277 | .timeline-title { | ||
| 278 | font-size: 28rpx; | ||
| 279 | color: #333; | ||
| 280 | font-weight: 500; | ||
| 281 | } | ||
| 282 | |||
| 283 | .timeline-time { | ||
| 284 | font-size: 24rpx; | ||
| 285 | color: #999; | ||
| 286 | margin-top: 8rpx; | ||
| 287 | } | ||
| 288 | |||
| 289 | .timeline-desc { | ||
| 290 | font-size: 26rpx; | ||
| 291 | color: #666; | ||
| 292 | margin-top: 12rpx; | ||
| 293 | line-height: 1.6; | ||
| 294 | background-color: #fafafa; | ||
| 295 | padding: 16rpx; | ||
| 296 | border-radius: 8rpx; | ||
| 297 | } | ||
| 298 | } | ||
| 299 | |||
| 300 | .no-logistics { | ||
| 301 | display: flex; | ||
| 302 | flex-direction: column; | ||
| 303 | align-items: center; | ||
| 304 | justify-content: center; | ||
| 305 | padding: 80rpx 0; | ||
| 306 | |||
| 307 | image { | ||
| 308 | width: 200rpx; | ||
| 309 | height: 200rpx; | ||
| 310 | } | ||
| 311 | |||
| 312 | text { | ||
| 313 | font-size: 28rpx; | ||
| 314 | color: #999; | ||
| 315 | margin-top: 20rpx; | ||
| 316 | } | ||
| 317 | } | ||
| 318 | } | ||
| 319 | </style> |
level/ztx/costSettlement.vue
0 → 100644
| 1 | <template> | ||
| 2 | <view class="cost-settlement-page"> | ||
| 3 | <!-- 顶部标签栏 --> | ||
| 4 | <view class="tab-bar"> | ||
| 5 | <view | ||
| 6 | v-for="tab in tabs" | ||
| 7 | :key="tab.value" | ||
| 8 | class="tab-item" | ||
| 9 | :class="{ active: currentTab === tab.value }" | ||
| 10 | @click="onTabChange(tab.value)" | ||
| 11 | > | ||
| 12 | <text class="tab-text">{{ tab.label }}</text> | ||
| 13 | <view class="tab-indicator" v-if="currentTab === tab.value"></view> | ||
| 14 | </view> | ||
| 15 | </view> | ||
| 16 | |||
| 17 | <!-- 新建按钮 --> | ||
| 18 | <view class="action-bar"> | ||
| 19 | <view class="btn-add" @click="goAdd"> | ||
| 20 | <uni-icons type="plus" size="16" color="#fff"></uni-icons> | ||
| 21 | <text>新建结算申请</text> | ||
| 22 | </view> | ||
| 23 | </view> | ||
| 24 | |||
| 25 | <!-- 列表内容 --> | ||
| 26 | <scroll-view | ||
| 27 | scroll-y | ||
| 28 | class="list-content" | ||
| 29 | @scrolltolower="onLoadMore" | ||
| 30 | > | ||
| 31 | <view class="loading-wrap" v-if="loading && list.length === 0"> | ||
| 32 | <uni-load-more status="loading"></uni-load-more> | ||
| 33 | </view> | ||
| 34 | |||
| 35 | <view class="empty-wrap" v-else-if="!loading && list.length === 0"> | ||
| 36 | <view class="nodata"> | ||
| 37 | <image mode="aspectFit" src="/static/nodata.png"></image> | ||
| 38 | <text>暂无数据</text> | ||
| 39 | </view> | ||
| 40 | </view> | ||
| 41 | |||
| 42 | <view class="appList" v-else> | ||
| 43 | <view class="appItem" v-for="(item, index) in list" :key="index"> | ||
| 44 | <view @click="goDetail(item)"> | ||
| 45 | <view class="status"> | ||
| 46 | <text :class="getStatusClass(item.status)"> | ||
| 47 | {{ getStatusText(item.status) }} | ||
| 48 | </text> | ||
| 49 | </view> | ||
| 50 | <view class="date"> | ||
| 51 | <view class="text-primary" v-if="item.code">{{ item.code }}</view> | ||
| 52 | </view> | ||
| 53 | |||
| 54 | <view class="name mt0">{{ item.name || '-' }}</view> | ||
| 55 | <view class="flexbox"> | ||
| 56 | <view> | ||
| 57 | 结算单位 | ||
| 58 | <view>{{ item.memName || '-' }}</view> | ||
| 59 | </view> | ||
| 60 | <view> | ||
| 61 | 结算金额 | ||
| 62 | <view class="text-red">¥{{ Number(item.price || 0).toFixed(2) }}</view> | ||
| 63 | </view> | ||
| 64 | </view> | ||
| 65 | <view class="flex f-j-s"> | ||
| 66 | <view class="info-time" v-if="item.commitTime"> | ||
| 67 | 提交时间:{{ formatDate(item.commitTime) }} | ||
| 68 | </view> | ||
| 69 | </view> | ||
| 70 | </view> | ||
| 71 | </view> | ||
| 72 | </view> | ||
| 73 | |||
| 74 | <view class="loading" v-if="list.length > 0"> | ||
| 75 | <uni-load-more :status="loadStatus" :contentText="loadMoreText"></uni-load-more> | ||
| 76 | </view> | ||
| 77 | </scroll-view> | ||
| 78 | </view> | ||
| 79 | </template> | ||
| 80 | |||
| 81 | <script setup> | ||
| 82 | import * as api from '@/common/api_exam.js' | ||
| 83 | import { ref } from 'vue' | ||
| 84 | import { onLoad, onShow } from '@dcloudio/uni-app' | ||
| 85 | |||
| 86 | const app = getApp() | ||
| 87 | |||
| 88 | const tabs = [ | ||
| 89 | { label: '全部', value: '' }, | ||
| 90 | { label: '待结算', value: '1' }, | ||
| 91 | { label: '结算通过', value: '2' }, | ||
| 92 | { label: '结算拒绝', value: '3' } | ||
| 93 | ] | ||
| 94 | |||
| 95 | const currentTab = ref('1') | ||
| 96 | const list = ref([]) | ||
| 97 | const loading = ref(false) | ||
| 98 | const loadStatus = ref('more') | ||
| 99 | const loadMoreText = { | ||
| 100 | contentdown: '上拉加载更多', | ||
| 101 | contentrefresh: '正在加载...', | ||
| 102 | contentnomore: '没有更多了' | ||
| 103 | } | ||
| 104 | const queryParams = ref({ | ||
| 105 | pageNum: 1, | ||
| 106 | pageSize: 10 | ||
| 107 | }) | ||
| 108 | |||
| 109 | onLoad(() => { | ||
| 110 | if (app.globalData.isLogin) { | ||
| 111 | init() | ||
| 112 | } else { | ||
| 113 | app.firstLoadCallback = () => { | ||
| 114 | init() | ||
| 115 | } | ||
| 116 | } | ||
| 117 | }) | ||
| 118 | |||
| 119 | onShow(() => { | ||
| 120 | if (app.globalData.isLogin && list.value.length > 0) { | ||
| 121 | refreshList() | ||
| 122 | } | ||
| 123 | }) | ||
| 124 | |||
| 125 | function init() { | ||
| 126 | list.value = [] | ||
| 127 | queryParams.value.pageNum = 1 | ||
| 128 | loadStatus.value = 'more' | ||
| 129 | getList() | ||
| 130 | } | ||
| 131 | |||
| 132 | function refreshList() { | ||
| 133 | list.value = [] | ||
| 134 | queryParams.value.pageNum = 1 | ||
| 135 | loadStatus.value = 'more' | ||
| 136 | getList() | ||
| 137 | } | ||
| 138 | |||
| 139 | function onTabChange(value) { | ||
| 140 | currentTab.value = value | ||
| 141 | init() | ||
| 142 | } | ||
| 143 | |||
| 144 | function getList() { | ||
| 145 | if (loadStatus.value === 'nomore') return | ||
| 146 | if (loading.value && list.value.length > 0) return | ||
| 147 | |||
| 148 | loading.value = true | ||
| 149 | if (list.value.length === 0) { | ||
| 150 | loadStatus.value = 'loading' | ||
| 151 | } | ||
| 152 | |||
| 153 | const params = { | ||
| 154 | ...queryParams.value, | ||
| 155 | status: currentTab.value | ||
| 156 | } | ||
| 157 | |||
| 158 | api.settlementList(params).then(res => { | ||
| 159 | const data = res.rows || [] | ||
| 160 | const totalData = res.total || 0 | ||
| 161 | |||
| 162 | if (queryParams.value.pageNum === 1) { | ||
| 163 | list.value = data | ||
| 164 | } else { | ||
| 165 | list.value = [...list.value, ...data] | ||
| 166 | } | ||
| 167 | |||
| 168 | if (list.value.length >= totalData) { | ||
| 169 | loadStatus.value = 'nomore' | ||
| 170 | } else { | ||
| 171 | loadStatus.value = 'more' | ||
| 172 | } | ||
| 173 | }).catch(() => { | ||
| 174 | loadStatus.value = 'more' | ||
| 175 | }).finally(() => { | ||
| 176 | loading.value = false | ||
| 177 | }) | ||
| 178 | } | ||
| 179 | |||
| 180 | function onLoadMore() { | ||
| 181 | if (loadStatus.value !== 'more' || loading.value) return | ||
| 182 | queryParams.value.pageNum++ | ||
| 183 | getList() | ||
| 184 | } | ||
| 185 | |||
| 186 | function getStatusText(status) { | ||
| 187 | const map = { 1: '待结算', 2: '结算通过', 3: '结算拒绝' } | ||
| 188 | return map[status] || '未知' | ||
| 189 | } | ||
| 190 | |||
| 191 | function getStatusClass(status) { | ||
| 192 | const map = { | ||
| 193 | 1: 'text-warning', | ||
| 194 | 2: 'text-success', | ||
| 195 | 3: 'text-danger' | ||
| 196 | } | ||
| 197 | return map[status] || '' | ||
| 198 | } | ||
| 199 | |||
| 200 | function formatDate(dateStr) { | ||
| 201 | if (!dateStr) return '-' | ||
| 202 | if (typeof dateStr === 'string' && dateStr.indexOf('T') > -1) { | ||
| 203 | return dateStr.slice(0, 10) | ||
| 204 | } | ||
| 205 | return dateStr | ||
| 206 | } | ||
| 207 | |||
| 208 | function goDetail(item) { | ||
| 209 | const itemStr = encodeURIComponent(JSON.stringify(item)) | ||
| 210 | uni.navigateTo({ | ||
| 211 | url: `/level/ztx/costSettlementDetail?item=${itemStr}` | ||
| 212 | }) | ||
| 213 | } | ||
| 214 | |||
| 215 | function goAdd() { | ||
| 216 | uni.navigateTo({ | ||
| 217 | url: `/level/ztx/costSettlementAdd` | ||
| 218 | }) | ||
| 219 | } | ||
| 220 | </script> | ||
| 221 | |||
| 222 | <style lang="scss" scoped> | ||
| 223 | .cost-settlement-page { | ||
| 224 | min-height: 100vh; | ||
| 225 | background-color: #f5f5f5; | ||
| 226 | } | ||
| 227 | |||
| 228 | .tab-bar { | ||
| 229 | display: flex; | ||
| 230 | background-color: #fff; | ||
| 231 | padding: 0 20rpx; | ||
| 232 | position: sticky; | ||
| 233 | top: 0; | ||
| 234 | z-index: 100; | ||
| 235 | |||
| 236 | .tab-item { | ||
| 237 | flex: 1; | ||
| 238 | display: flex; | ||
| 239 | flex-direction: column; | ||
| 240 | align-items: center; | ||
| 241 | padding: 24rpx 0; | ||
| 242 | position: relative; | ||
| 243 | |||
| 244 | .tab-text { | ||
| 245 | font-size: 28rpx; | ||
| 246 | color: #666; | ||
| 247 | } | ||
| 248 | |||
| 249 | .tab-indicator { | ||
| 250 | position: absolute; | ||
| 251 | bottom: 0; | ||
| 252 | left: 50%; | ||
| 253 | transform: translateX(-50%); | ||
| 254 | width: 80rpx; | ||
| 255 | height: 6rpx; | ||
| 256 | background-color: #AD181F; | ||
| 257 | border-radius: 3rpx; | ||
| 258 | } | ||
| 259 | |||
| 260 | &.active { | ||
| 261 | .tab-text { | ||
| 262 | color: #AD181F; | ||
| 263 | font-weight: 600; | ||
| 264 | } | ||
| 265 | } | ||
| 266 | } | ||
| 267 | } | ||
| 268 | |||
| 269 | .action-bar { | ||
| 270 | padding: 20rpx; | ||
| 271 | background-color: #f5f5f5; | ||
| 272 | |||
| 273 | .btn-add { | ||
| 274 | display: flex; | ||
| 275 | align-items: center; | ||
| 276 | justify-content: center; | ||
| 277 | gap: 8rpx; | ||
| 278 | background-color: #AD181F; | ||
| 279 | color: #fff; | ||
| 280 | padding: 20rpx 0; | ||
| 281 | border-radius: 12rpx; | ||
| 282 | font-size: 28rpx; | ||
| 283 | |||
| 284 | &:active { | ||
| 285 | opacity: 0.8; | ||
| 286 | } | ||
| 287 | } | ||
| 288 | } | ||
| 289 | |||
| 290 | .list-content { | ||
| 291 | height: calc(100vh - 200rpx); | ||
| 292 | // padding: 0 20rpx 20rpx; | ||
| 293 | } | ||
| 294 | |||
| 295 | .loading-wrap, | ||
| 296 | .empty-wrap { | ||
| 297 | padding: 100rpx 0; | ||
| 298 | text-align: center; | ||
| 299 | } | ||
| 300 | |||
| 301 | /* 列表样式 */ | ||
| 302 | .appList { | ||
| 303 | padding: 0; | ||
| 304 | margin:0rpx auto; | ||
| 305 | } | ||
| 306 | |||
| 307 | .appItem { | ||
| 308 | background-color: #fff; | ||
| 309 | border-radius: 16rpx; | ||
| 310 | padding: 30rpx; | ||
| 311 | margin-bottom: 20rpx; | ||
| 312 | box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05); | ||
| 313 | |||
| 314 | .status { | ||
| 315 | display: inline-block; | ||
| 316 | padding: 6rpx 20rpx; | ||
| 317 | border-radius: 20rpx; | ||
| 318 | font-size: 24rpx; | ||
| 319 | margin-bottom: 16rpx; | ||
| 320 | |||
| 321 | .text-success { | ||
| 322 | color: #4caf50; | ||
| 323 | } | ||
| 324 | |||
| 325 | .text-warning { | ||
| 326 | color: #ff9800; | ||
| 327 | } | ||
| 328 | |||
| 329 | .text-danger { | ||
| 330 | color: #f5222d; | ||
| 331 | } | ||
| 332 | } | ||
| 333 | |||
| 334 | .date { | ||
| 335 | font-size: 24rpx; | ||
| 336 | color: #999; | ||
| 337 | } | ||
| 338 | |||
| 339 | .text-primary { | ||
| 340 | font-size: 28rpx; | ||
| 341 | color: #AD181F; | ||
| 342 | } | ||
| 343 | |||
| 344 | .name { | ||
| 345 | font-size: 28rpx; | ||
| 346 | font-weight: 600; | ||
| 347 | color: #333; | ||
| 348 | margin-bottom: 20rpx; | ||
| 349 | margin-top: 10rpx; | ||
| 350 | |||
| 351 | &.mt0 { | ||
| 352 | margin-top: 0; | ||
| 353 | } | ||
| 354 | } | ||
| 355 | |||
| 356 | .flexbox { | ||
| 357 | display: flex; | ||
| 358 | justify-content: space-between; | ||
| 359 | background-color: #fafafa; | ||
| 360 | border-radius: 12rpx; | ||
| 361 | padding: 20rpx; | ||
| 362 | margin: 20rpx 0; | ||
| 363 | |||
| 364 | view { | ||
| 365 | flex: 1; | ||
| 366 | text-align: center; | ||
| 367 | font-size: 24rpx; | ||
| 368 | color: #999; | ||
| 369 | |||
| 370 | view { | ||
| 371 | font-size: 28rpx; | ||
| 372 | color: #333; | ||
| 373 | font-weight: 500; | ||
| 374 | margin-top: 8rpx; | ||
| 375 | } | ||
| 376 | } | ||
| 377 | |||
| 378 | .text-red { | ||
| 379 | color: #AD181F; | ||
| 380 | } | ||
| 381 | } | ||
| 382 | |||
| 383 | .flex { | ||
| 384 | display: flex; | ||
| 385 | |||
| 386 | &.f-j-s { | ||
| 387 | justify-content: space-between; | ||
| 388 | } | ||
| 389 | } | ||
| 390 | |||
| 391 | .info-time { | ||
| 392 | font-size: 24rpx; | ||
| 393 | color: #666; | ||
| 394 | margin-top: 16rpx; | ||
| 395 | } | ||
| 396 | } | ||
| 397 | |||
| 398 | .nodata { | ||
| 399 | display: flex; | ||
| 400 | flex-direction: column; | ||
| 401 | align-items: center; | ||
| 402 | justify-content: center; | ||
| 403 | padding: 100rpx 0; | ||
| 404 | |||
| 405 | image { | ||
| 406 | width: 300rpx; | ||
| 407 | height: 300rpx; | ||
| 408 | } | ||
| 409 | |||
| 410 | text { | ||
| 411 | font-size: 28rpx; | ||
| 412 | color: #999; | ||
| 413 | margin-top: 20rpx; | ||
| 414 | } | ||
| 415 | } | ||
| 416 | |||
| 417 | .loading { | ||
| 418 | padding: 30rpx 0; | ||
| 419 | text-align: center; | ||
| 420 | } | ||
| 421 | </style> |
level/ztx/costSettlementAdd.vue
0 → 100644
| 1 | <template> | ||
| 2 | <view class="cost-settlement-add-page"> | ||
| 3 | <!-- 列表内容 --> | ||
| 4 | <scroll-view | ||
| 5 | scroll-y | ||
| 6 | class="list-content" | ||
| 7 | @scrolltolower="onLoadMore" | ||
| 8 | > | ||
| 9 | <view class="loading-wrap" v-if="loading && list.length === 0"> | ||
| 10 | <uni-load-more status="loading"></uni-load-more> | ||
| 11 | </view> | ||
| 12 | |||
| 13 | <view class="empty-wrap" v-else-if="!loading && list.length === 0"> | ||
| 14 | <view class="nodata"> | ||
| 15 | <image mode="aspectFit" src="/static/nodata.png"></image> | ||
| 16 | <text>暂无可结算的缴费单</text> | ||
| 17 | </view> | ||
| 18 | </view> | ||
| 19 | |||
| 20 | <view class="appList" v-else> | ||
| 21 | <view class="appItem" v-for="(item, index) in list" :key="item.payId || index" @click="toggleSelect(item)"> | ||
| 22 | <view class="select-indicator" :class="{ selected: isSelected(item) }"> | ||
| 23 | <uni-icons v-if="isSelected(item)" type="checkmark" size="14" color="#fff"></uni-icons> | ||
| 24 | </view> | ||
| 25 | <view class="item-content"> | ||
| 26 | <view class="status"> | ||
| 27 | <text :class="getStatusClass(item.verityStatus)"> | ||
| 28 | {{ item.verityStatusStr || '审核中' }} | ||
| 29 | </text> | ||
| 30 | </view> | ||
| 31 | <view class="date"> | ||
| 32 | <view class="text-primary" v-if="item.payCode">{{ item.payCode }}</view> | ||
| 33 | </view> | ||
| 34 | |||
| 35 | <view class="name mt0">{{ item.name || '-' }}</view> | ||
| 36 | <view class="flexbox"> | ||
| 37 | <view> | ||
| 38 | 缴费单位 | ||
| 39 | <view>{{ item.applyMemberName || '-' }}</view> | ||
| 40 | </view> | ||
| 41 | <view> | ||
| 42 | 考试人数 | ||
| 43 | <view>{{ item.totalNum || 0 }} 人</view> | ||
| 44 | </view> | ||
| 45 | <view> | ||
| 46 | 总金额 | ||
| 47 | <view class="text-red">¥{{ Number(item.totalAmount || 0).toFixed(2) }}</view> | ||
| 48 | </view> | ||
| 49 | </view> | ||
| 50 | <view class="flex f-j-s"> | ||
| 51 | <view class="info-time" v-if="item.submitTime"> | ||
| 52 | 提交时间:{{ formatDate(item.submitTime) }} | ||
| 53 | </view> | ||
| 54 | </view> | ||
| 55 | </view> | ||
| 56 | </view> | ||
| 57 | </view> | ||
| 58 | |||
| 59 | <view class="loading" v-if="list.length > 0"> | ||
| 60 | <uni-load-more :status="loadStatus" :contentText="loadMoreText"></uni-load-more> | ||
| 61 | </view> | ||
| 62 | </scroll-view> | ||
| 63 | |||
| 64 | <!-- 底部提交按钮 --> | ||
| 65 | <view class="bottom-bar" v-if="selectedIds.size > 0"> | ||
| 66 | <view class="summary-info"> | ||
| 67 | <view class="summary-item"> | ||
| 68 | <text class="summary-label">费用合计:</text> | ||
| 69 | <text class="summary-value text-red">¥{{ totalAmount.toFixed(2) }}</text> | ||
| 70 | </view> | ||
| 71 | <view class="summary-item"> | ||
| 72 | <text class="summary-label">人数合计:</text> | ||
| 73 | <text class="summary-value">{{ totalNum }} 人</text> | ||
| 74 | </view> | ||
| 75 | </view> | ||
| 76 | <view class="submit-btn" @click="handleSettlement"> | ||
| 77 | 结算申请 | ||
| 78 | </view> | ||
| 79 | </view> | ||
| 80 | </view> | ||
| 81 | </template> | ||
| 82 | |||
| 83 | <script setup> | ||
| 84 | import * as api from '@/common/api_exam.js' | ||
| 85 | import { ref, computed } from 'vue' | ||
| 86 | import { onLoad } from '@dcloudio/uni-app' | ||
| 87 | |||
| 88 | const loading = ref(false) | ||
| 89 | const list = ref([]) | ||
| 90 | const selectedIds = ref(new Set()) | ||
| 91 | const loadStatus = ref('more') | ||
| 92 | const loadMoreText = { | ||
| 93 | contentdown: '上拉加载更多', | ||
| 94 | contentrefresh: '正在加载...', | ||
| 95 | contentnomore: '没有更多了' | ||
| 96 | } | ||
| 97 | const queryParams = ref({ | ||
| 98 | pageNum: 1, | ||
| 99 | pageSize: 10, | ||
| 100 | type: 1, | ||
| 101 | submitFlag: '0' | ||
| 102 | }) | ||
| 103 | |||
| 104 | // 选中的费用合计 | ||
| 105 | const totalAmount = computed(() => { | ||
| 106 | return list.value | ||
| 107 | .filter(item => selectedIds.value.has(item.payId)) | ||
| 108 | .reduce((sum, item) => sum + (Number(item.totalAmount) || 0), 0) | ||
| 109 | }) | ||
| 110 | |||
| 111 | // 选中的人数合计 | ||
| 112 | const totalNum = computed(() => { | ||
| 113 | return list.value | ||
| 114 | .filter(item => selectedIds.value.has(item.payId)) | ||
| 115 | .reduce((sum, item) => sum + (Number(item.totalNum) || 0), 0) | ||
| 116 | }) | ||
| 117 | |||
| 118 | onLoad(() => { | ||
| 119 | getList() | ||
| 120 | }) | ||
| 121 | |||
| 122 | function getList() { | ||
| 123 | if (loadStatus.value === 'nomore') return | ||
| 124 | if (loading.value && list.value.length > 0) return | ||
| 125 | |||
| 126 | loading.value = true | ||
| 127 | if (list.value.length === 0) { | ||
| 128 | loadStatus.value = 'loading' | ||
| 129 | } | ||
| 130 | |||
| 131 | api.settlementApplyList(queryParams.value).then(res => { | ||
| 132 | const data = res.rows || [] | ||
| 133 | const totalData = res.total || 0 | ||
| 134 | |||
| 135 | if (queryParams.value.pageNum === 1) { | ||
| 136 | list.value = data | ||
| 137 | } else { | ||
| 138 | list.value = [...list.value, ...data] | ||
| 139 | } | ||
| 140 | |||
| 141 | if (list.value.length >= totalData) { | ||
| 142 | loadStatus.value = 'nomore' | ||
| 143 | } else { | ||
| 144 | loadStatus.value = 'more' | ||
| 145 | } | ||
| 146 | }).catch(() => { | ||
| 147 | loadStatus.value = 'more' | ||
| 148 | }).finally(() => { | ||
| 149 | loading.value = false | ||
| 150 | }) | ||
| 151 | } | ||
| 152 | |||
| 153 | function onLoadMore() { | ||
| 154 | if (loadStatus.value !== 'more' || loading.value) return | ||
| 155 | queryParams.value.pageNum++ | ||
| 156 | getList() | ||
| 157 | } | ||
| 158 | |||
| 159 | function getStatusClass(status) { | ||
| 160 | const map = { | ||
| 161 | 1: 'text-success', | ||
| 162 | 2: 'text-danger', | ||
| 163 | 3: 'text-warning' | ||
| 164 | } | ||
| 165 | return map[status] || 'text-warning' | ||
| 166 | } | ||
| 167 | |||
| 168 | function formatDate(dateStr) { | ||
| 169 | if (!dateStr) return '-' | ||
| 170 | if (typeof dateStr === 'string' && dateStr.indexOf('T') > -1) { | ||
| 171 | return dateStr.slice(0, 10) | ||
| 172 | } | ||
| 173 | return dateStr | ||
| 174 | } | ||
| 175 | |||
| 176 | function toggleSelect(item) { | ||
| 177 | if (selectedIds.value.has(item.payId)) { | ||
| 178 | selectedIds.value.delete(item.payId) | ||
| 179 | } else { | ||
| 180 | selectedIds.value.add(item.payId) | ||
| 181 | } | ||
| 182 | selectedIds.value = new Set(selectedIds.value) | ||
| 183 | } | ||
| 184 | |||
| 185 | // 修复:这里传 item 而不是 payId | ||
| 186 | function isSelected(item) { | ||
| 187 | return selectedIds.value.has(item.payId) | ||
| 188 | } | ||
| 189 | |||
| 190 | function handleSettlement() { | ||
| 191 | if (selectedIds.value.size === 0) { | ||
| 192 | uni.showToast({ title: '请选择要结算的缴费单', icon: 'none' }) | ||
| 193 | return | ||
| 194 | } | ||
| 195 | |||
| 196 | const ids = Array.from(selectedIds.value).join(',') | ||
| 197 | uni.navigateTo({ | ||
| 198 | url: `/level/ztx/costSettlementConfirm?ids=${ids}` | ||
| 199 | }) | ||
| 200 | } | ||
| 201 | </script> | ||
| 202 | |||
| 203 | <style lang="scss" scoped> | ||
| 204 | .cost-settlement-add-page { | ||
| 205 | min-height: 100vh; | ||
| 206 | background-color: #f5f5f5; | ||
| 207 | padding-bottom: 120rpx; | ||
| 208 | } | ||
| 209 | |||
| 210 | .list-content { | ||
| 211 | height: calc(100vh - 120rpx); | ||
| 212 | padding: 20rpx; | ||
| 213 | box-sizing: border-box; | ||
| 214 | } | ||
| 215 | |||
| 216 | .loading-wrap, | ||
| 217 | .empty-wrap { | ||
| 218 | padding: 100rpx 0; | ||
| 219 | text-align: center; | ||
| 220 | } | ||
| 221 | |||
| 222 | .appList { | ||
| 223 | padding: 0; | ||
| 224 | } | ||
| 225 | |||
| 226 | .appItem { | ||
| 227 | background-color: #fff; | ||
| 228 | border-radius: 16rpx; | ||
| 229 | padding: 30rpx; | ||
| 230 | margin-bottom: 20rpx; | ||
| 231 | box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05); | ||
| 232 | display: flex; | ||
| 233 | align-items: center; | ||
| 234 | position: relative; | ||
| 235 | |||
| 236 | // 选择框 - 修复样式 | ||
| 237 | .select-indicator { | ||
| 238 | width: 36rpx; | ||
| 239 | height: 36rpx; | ||
| 240 | border-radius: 50%; | ||
| 241 | border: 2rpx solid #ddd; | ||
| 242 | display: flex; | ||
| 243 | align-items: center; | ||
| 244 | justify-content: center; | ||
| 245 | margin-right: 20rpx; | ||
| 246 | flex-shrink: 0; | ||
| 247 | transition: all 0.2s; | ||
| 248 | |||
| 249 | &.selected { | ||
| 250 | background-color: #AD181F; | ||
| 251 | border-color: #AD181F; | ||
| 252 | } | ||
| 253 | } | ||
| 254 | |||
| 255 | .item-content { | ||
| 256 | flex: 1; | ||
| 257 | min-width: 0; | ||
| 258 | } | ||
| 259 | |||
| 260 | .status { | ||
| 261 | display: inline-block; | ||
| 262 | padding: 6rpx 20rpx; | ||
| 263 | border-radius: 20rpx; | ||
| 264 | font-size: 24rpx; | ||
| 265 | margin-bottom: 16rpx; | ||
| 266 | |||
| 267 | .text-success { | ||
| 268 | color: #4caf50; | ||
| 269 | } | ||
| 270 | .text-warning { | ||
| 271 | color: #ff9800; | ||
| 272 | } | ||
| 273 | .text-danger { | ||
| 274 | color: #f5222d; | ||
| 275 | } | ||
| 276 | } | ||
| 277 | |||
| 278 | .date { | ||
| 279 | font-size: 24rpx; | ||
| 280 | color: #999; | ||
| 281 | } | ||
| 282 | |||
| 283 | .text-primary { | ||
| 284 | font-size: 28rpx; | ||
| 285 | color: #AD181F; | ||
| 286 | } | ||
| 287 | |||
| 288 | .name { | ||
| 289 | font-size: 28rpx; | ||
| 290 | font-weight: 600; | ||
| 291 | color: #333; | ||
| 292 | margin-bottom: 20rpx; | ||
| 293 | margin-top: 10rpx; | ||
| 294 | |||
| 295 | &.mt0 { | ||
| 296 | margin-top: 0; | ||
| 297 | } | ||
| 298 | } | ||
| 299 | |||
| 300 | .flexbox { | ||
| 301 | display: flex; | ||
| 302 | justify-content: space-between; | ||
| 303 | background-color: #fafafa; | ||
| 304 | border-radius: 12rpx; | ||
| 305 | padding: 20rpx; | ||
| 306 | margin: 20rpx 0; | ||
| 307 | |||
| 308 | view { | ||
| 309 | flex: 1; | ||
| 310 | text-align: center; | ||
| 311 | font-size: 24rpx; | ||
| 312 | color: #999; | ||
| 313 | |||
| 314 | view { | ||
| 315 | font-size: 28rpx; | ||
| 316 | color: #333; | ||
| 317 | font-weight: 500; | ||
| 318 | margin-top: 8rpx; | ||
| 319 | } | ||
| 320 | } | ||
| 321 | |||
| 322 | .text-red { | ||
| 323 | color: #AD181F; | ||
| 324 | } | ||
| 325 | } | ||
| 326 | |||
| 327 | .flex { | ||
| 328 | display: flex; | ||
| 329 | |||
| 330 | &.f-j-s { | ||
| 331 | justify-content: space-between; | ||
| 332 | } | ||
| 333 | } | ||
| 334 | |||
| 335 | .info-time { | ||
| 336 | font-size: 24rpx; | ||
| 337 | color: #666; | ||
| 338 | margin-top: 16rpx; | ||
| 339 | } | ||
| 340 | } | ||
| 341 | |||
| 342 | .nodata { | ||
| 343 | display: flex; | ||
| 344 | flex-direction: column; | ||
| 345 | align-items: center; | ||
| 346 | justify-content: center; | ||
| 347 | padding: 100rpx 0; | ||
| 348 | |||
| 349 | image { | ||
| 350 | width: 300rpx; | ||
| 351 | height: 300rpx; | ||
| 352 | } | ||
| 353 | |||
| 354 | text { | ||
| 355 | font-size: 28rpx; | ||
| 356 | color: #999; | ||
| 357 | margin-top: 20rpx; | ||
| 358 | } | ||
| 359 | } | ||
| 360 | |||
| 361 | .loading { | ||
| 362 | padding: 30rpx 0; | ||
| 363 | text-align: center; | ||
| 364 | } | ||
| 365 | |||
| 366 | .bottom-bar { | ||
| 367 | position: fixed; | ||
| 368 | bottom: 0; | ||
| 369 | left: 0; | ||
| 370 | right: 0; | ||
| 371 | background-color: #fff; | ||
| 372 | display: flex; | ||
| 373 | align-items: center; | ||
| 374 | justify-content: space-between; | ||
| 375 | padding: 20rpx 30rpx; | ||
| 376 | padding-bottom: calc(20rpx + env(safe-area-inset-bottom)); | ||
| 377 | box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.05); | ||
| 378 | z-index: 99; | ||
| 379 | |||
| 380 | .summary-info { | ||
| 381 | display: flex; | ||
| 382 | flex-direction: column; | ||
| 383 | gap: 8rpx; | ||
| 384 | |||
| 385 | .summary-item { | ||
| 386 | display: flex; | ||
| 387 | align-items: center; | ||
| 388 | |||
| 389 | .summary-label { | ||
| 390 | font-size: 24rpx; | ||
| 391 | color: #666; | ||
| 392 | } | ||
| 393 | |||
| 394 | .summary-value { | ||
| 395 | font-size: 28rpx; | ||
| 396 | color: #333; | ||
| 397 | font-weight: 600; | ||
| 398 | } | ||
| 399 | |||
| 400 | .text-red { | ||
| 401 | color: #AD181F; | ||
| 402 | } | ||
| 403 | } | ||
| 404 | } | ||
| 405 | |||
| 406 | .submit-btn { | ||
| 407 | background-color: #AD181F; | ||
| 408 | color: #fff; | ||
| 409 | padding: 20rpx 50rpx; | ||
| 410 | border-radius: 40rpx; | ||
| 411 | font-size: 28rpx; | ||
| 412 | |||
| 413 | &:active { | ||
| 414 | opacity: 0.8; | ||
| 415 | } | ||
| 416 | } | ||
| 417 | } | ||
| 418 | </style> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
level/ztx/costSettlementConfirm.vue
0 → 100644
| 1 | <template> | ||
| 2 | <view class="settlement-confirm-page"> | ||
| 3 | <!-- 统计卡片区 --> | ||
| 4 | <view class="stats-grid"> | ||
| 5 | <view class="stat-card"> | ||
| 6 | <view class="stat-label">考试总人数</view> | ||
| 7 | <view class="stat-value">{{ form.personCount || 0 }}<text class="stat-unit">人</text></view> | ||
| 8 | </view> | ||
| 9 | <view class="stat-card"> | ||
| 10 | <view class="stat-label">费用合计</view> | ||
| 11 | <view class="stat-value">{{ form.allFee || '0.00' }}<text class="stat-unit">元</text></view> | ||
| 12 | </view> | ||
| 13 | <view class="stat-card"> | ||
| 14 | <view class="stat-label">结算费用</view> | ||
| 15 | <view class="stat-value text-red">{{ form.fee || '0.00' }}<text class="stat-unit">元</text></view> | ||
| 16 | </view> | ||
| 17 | </view> | ||
| 18 | |||
| 19 | <!-- 级别分布明细 --> | ||
| 20 | <view class="level-section"> | ||
| 21 | <view class="section-title">级别分布明细</view> | ||
| 22 | <view class="level-tags"> | ||
| 23 | <view v-for="(val, inx) in form.count" :key="inx" class="level-tag" :class="`level-${inx % 3 + 1}`"> | ||
| 24 | {{ szToHz(inx) }}级:{{ val }}人 | ||
| 25 | </view> | ||
| 26 | </view> | ||
| 27 | </view> | ||
| 28 | |||
| 29 | <view class="divider"></view> | ||
| 30 | |||
| 31 | <!-- 发票上传区域 --> | ||
| 32 | <view class="upload-section"> | ||
| 33 | <view class="section-title">发票上传</view> | ||
| 34 | <view class="upload-area"> | ||
| 35 | <view class="upload-tip">支持格式:jpg、png、pdf,大小不超过10MB</view> | ||
| 36 | <uni-file-picker | ||
| 37 | v-model="fileList" | ||
| 38 | file-mediatype="image" | ||
| 39 | file-extname="jpg,jpeg,png,pdf" | ||
| 40 | :limit="1" | ||
| 41 | @select="selectFile" | ||
| 42 | @progress="fileProgress" | ||
| 43 | @success="fileSuccess" | ||
| 44 | @delete="fileDelete" | ||
| 45 | > | ||
| 46 | <view class="upload-btn" v-if="!fileList.length"> | ||
| 47 | <uni-icons type="plus" size="24" color="#AD181F"></uni-icons> | ||
| 48 | <!-- <text>上传发票</text> --> | ||
| 49 | </view> | ||
| 50 | <view v-else class="file-item"> | ||
| 51 | <uni-icons type="paperclip" size="16" color="#AD181F"></uni-icons> | ||
| 52 | <text class="file-name">{{ fileList[0].name }}</text> | ||
| 53 | </view> | ||
| 54 | </uni-file-picker> | ||
| 55 | </view> | ||
| 56 | </view> | ||
| 57 | |||
| 58 | <!-- 底部操作按钮 --> | ||
| 59 | <view class="bottom-bar"> | ||
| 60 | <view class="cancel-btn" @click="handleCancel">取消</view> | ||
| 61 | <view class="submit-btn" @click="handleSubmit">提交结算申请</view> | ||
| 62 | </view> | ||
| 63 | </view> | ||
| 64 | </template> | ||
| 65 | |||
| 66 | <script setup> | ||
| 67 | import * as api from '@/common/api_exam.js' | ||
| 68 | import { uploadFileList } from '@/common/api.js' | ||
| 69 | import { ref, } from 'vue'; | ||
| 70 | import { onLoad } from '@dcloudio/uni-app' | ||
| 71 | |||
| 72 | const form = ref({}) | ||
| 73 | const fileList = ref([]) | ||
| 74 | const loading = ref(false) | ||
| 75 | const ids = ref('') | ||
| 76 | const uploadedUrl = ref('') // 上传后的文件路径 | ||
| 77 | |||
| 78 | onLoad((options) => { | ||
| 79 | const { ids: optIds } = options | ||
| 80 | if (optIds) { | ||
| 81 | ids.value = optIds | ||
| 82 | getConfirm(optIds) | ||
| 83 | } | ||
| 84 | }) | ||
| 85 | |||
| 86 | // 数字转汉字 | ||
| 87 | function szToHz(num) { | ||
| 88 | const arr = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十'] | ||
| 89 | return arr[num] || num + 1 | ||
| 90 | } | ||
| 91 | |||
| 92 | async function getConfirm(ids) { | ||
| 93 | loading.value = true | ||
| 94 | try { | ||
| 95 | const res = await api.settlementConfirm(ids) | ||
| 96 | form.value = res.data || {} | ||
| 97 | } catch (err) { | ||
| 98 | console.error('获取结算明细失败', err) | ||
| 99 | uni.showToast({ title: '获取数据失败', icon: 'none' }) | ||
| 100 | } finally { | ||
| 101 | loading.value = false | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | function selectFile(e) { | ||
| 106 | const file = e.tempFiles[0] | ||
| 107 | if (!file) return | ||
| 108 | uni.showLoading({ title: '上传中' }) | ||
| 109 | uploadFileList(e.tempFilePaths[0]).then(data => { | ||
| 110 | uploadedUrl.value = data | ||
| 111 | uni.hideLoading() | ||
| 112 | uni.showToast({ title: '上传成功', icon: 'success' }) | ||
| 113 | }).catch(err => { | ||
| 114 | uni.hideLoading() | ||
| 115 | uni.showToast({ title: '上传失败', icon: 'none' }) | ||
| 116 | }) | ||
| 117 | } | ||
| 118 | |||
| 119 | function fileProgress(e) { | ||
| 120 | console.log('上传进度:', e) | ||
| 121 | } | ||
| 122 | |||
| 123 | function fileSuccess(e) { | ||
| 124 | console.log('上传成功:', e) | ||
| 125 | } | ||
| 126 | |||
| 127 | function fileDelete(e) { | ||
| 128 | fileList.value = [] | ||
| 129 | uploadedUrl.value = '' | ||
| 130 | } | ||
| 131 | |||
| 132 | function handleCancel() { | ||
| 133 | uni.navigateBack() | ||
| 134 | } | ||
| 135 | |||
| 136 | async function handleSubmit() { | ||
| 137 | if (!uploadedUrl.value) { | ||
| 138 | uni.showToast({ title: '请上传发票', icon: 'none' }) | ||
| 139 | return | ||
| 140 | } | ||
| 141 | |||
| 142 | // 使用上传后的真实路径 | ||
| 143 | const url = JSON.stringify([{ url: uploadedUrl.value, name: fileList.value[0]?.name || 'invoice' }]) | ||
| 144 | |||
| 145 | try { | ||
| 146 | uni.showLoading({ title: '提交中...' }) | ||
| 147 | await api.settlementCommit({ ids: ids.value, url }) | ||
| 148 | uni.hideLoading() | ||
| 149 | uni.showToast({ title: '提交成功', icon: 'success' }) | ||
| 150 | setTimeout(() => { | ||
| 151 | uni.navigateBack({ | ||
| 152 | delta: 2 // 返回两级页面 | ||
| 153 | }) | ||
| 154 | }, 1500) | ||
| 155 | } catch (err) { | ||
| 156 | uni.hideLoading() | ||
| 157 | console.error('提交失败', err) | ||
| 158 | uni.showToast({ title: '提交失败', icon: 'none' }) | ||
| 159 | } | ||
| 160 | } | ||
| 161 | </script> | ||
| 162 | |||
| 163 | <style lang="scss" scoped> | ||
| 164 | .settlement-confirm-page { | ||
| 165 | min-height: 100vh; | ||
| 166 | background-color: #f5f5f5; | ||
| 167 | padding: 20rpx; | ||
| 168 | padding-bottom: 140rpx; | ||
| 169 | } | ||
| 170 | |||
| 171 | .stats-grid { | ||
| 172 | display: grid; | ||
| 173 | grid-template-columns: repeat(3, 1fr); | ||
| 174 | gap: 20rpx; | ||
| 175 | margin-bottom: 20rpx; | ||
| 176 | } | ||
| 177 | |||
| 178 | .stat-card { | ||
| 179 | background: #fff; | ||
| 180 | border-radius: 16rpx; | ||
| 181 | padding: 30rpx 20rpx; | ||
| 182 | text-align: center; | ||
| 183 | box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05); | ||
| 184 | |||
| 185 | .stat-label { | ||
| 186 | font-size: 24rpx; | ||
| 187 | color: #999; | ||
| 188 | margin-bottom: 12rpx; | ||
| 189 | } | ||
| 190 | |||
| 191 | .stat-value { | ||
| 192 | font-size: 36rpx; | ||
| 193 | font-weight: 700; | ||
| 194 | color: #333; | ||
| 195 | line-height: 1.2; | ||
| 196 | } | ||
| 197 | |||
| 198 | .stat-unit { | ||
| 199 | font-size: 24rpx; | ||
| 200 | font-weight: 400; | ||
| 201 | color: #999; | ||
| 202 | margin-left: 4rpx; | ||
| 203 | } | ||
| 204 | |||
| 205 | .text-red { | ||
| 206 | color: #AD181F; | ||
| 207 | } | ||
| 208 | } | ||
| 209 | |||
| 210 | .level-section { | ||
| 211 | background: #fff; | ||
| 212 | border-radius: 16rpx; | ||
| 213 | padding: 30rpx; | ||
| 214 | margin-bottom: 20rpx; | ||
| 215 | box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05); | ||
| 216 | border-left: 8rpx solid #27a9e7; | ||
| 217 | |||
| 218 | .section-title { | ||
| 219 | font-size: 28rpx; | ||
| 220 | font-weight: 600; | ||
| 221 | color: #333; | ||
| 222 | margin-bottom: 24rpx; | ||
| 223 | } | ||
| 224 | |||
| 225 | .level-tags { | ||
| 226 | display: flex; | ||
| 227 | flex-wrap: wrap; | ||
| 228 | gap: 20rpx; | ||
| 229 | |||
| 230 | .level-tag { | ||
| 231 | padding: 12rpx 24rpx; | ||
| 232 | border-radius: 30rpx; | ||
| 233 | font-size: 24rpx; | ||
| 234 | font-weight: 500; | ||
| 235 | background: #fff; | ||
| 236 | box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05); | ||
| 237 | } | ||
| 238 | |||
| 239 | .level-1 { | ||
| 240 | background: linear-gradient(135deg, #fef2e8, #ffe4d6); | ||
| 241 | color: #c2410c; | ||
| 242 | } | ||
| 243 | |||
| 244 | .level-2 { | ||
| 245 | background: linear-gradient(135deg, #eef2ff, #e0e7ff); | ||
| 246 | color: #1e40af; | ||
| 247 | } | ||
| 248 | |||
| 249 | .level-3 { | ||
| 250 | background: linear-gradient(135deg, #ecfdf5, #d1fae5); | ||
| 251 | color: #065f46; | ||
| 252 | } | ||
| 253 | } | ||
| 254 | } | ||
| 255 | |||
| 256 | .divider { | ||
| 257 | height: 1rpx; | ||
| 258 | background-color: #eee; | ||
| 259 | margin: 20rpx 0; | ||
| 260 | } | ||
| 261 | |||
| 262 | .upload-section { | ||
| 263 | background: #fff; | ||
| 264 | border-radius: 16rpx; | ||
| 265 | padding: 30rpx; | ||
| 266 | box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05); | ||
| 267 | |||
| 268 | .section-title { | ||
| 269 | font-size: 28rpx; | ||
| 270 | font-weight: 600; | ||
| 271 | color: #333; | ||
| 272 | margin-bottom: 24rpx; | ||
| 273 | } | ||
| 274 | |||
| 275 | .upload-area { | ||
| 276 | background: #fafcff; | ||
| 277 | padding: 24rpx; | ||
| 278 | border-radius: 12rpx; | ||
| 279 | border: 2rpx dashed #cbd5e1; | ||
| 280 | display: flex; | ||
| 281 | flex-direction: column; | ||
| 282 | align-items: center; | ||
| 283 | gap: 20rpx; | ||
| 284 | |||
| 285 | .upload-tip { | ||
| 286 | font-size: 24rpx; | ||
| 287 | color: #999; | ||
| 288 | text-align: center; | ||
| 289 | } | ||
| 290 | |||
| 291 | .upload-btn { | ||
| 292 | display: flex; | ||
| 293 | flex-direction: column; | ||
| 294 | align-items: center; | ||
| 295 | gap: 12rpx; | ||
| 296 | padding: 30rpx 60rpx; | ||
| 297 | border-radius: 16rpx; | ||
| 298 | color: #AD181F; | ||
| 299 | font-size: 28rpx; | ||
| 300 | } | ||
| 301 | |||
| 302 | .file-item { | ||
| 303 | display: flex; | ||
| 304 | align-items: center; | ||
| 305 | gap: 12rpx; | ||
| 306 | padding: 20rpx 30rpx; | ||
| 307 | background: #fff; | ||
| 308 | border-radius: 12rpx; | ||
| 309 | border: 1rpx solid #eee; | ||
| 310 | |||
| 311 | .file-name { | ||
| 312 | font-size: 26rpx; | ||
| 313 | color: #333; | ||
| 314 | max-width: 400rpx; | ||
| 315 | overflow: hidden; | ||
| 316 | text-overflow: ellipsis; | ||
| 317 | white-space: nowrap; | ||
| 318 | } | ||
| 319 | } | ||
| 320 | } | ||
| 321 | } | ||
| 322 | |||
| 323 | .bottom-bar { | ||
| 324 | position: fixed; | ||
| 325 | bottom: 0; | ||
| 326 | left: 0; | ||
| 327 | right: 0; | ||
| 328 | background-color: #fff; | ||
| 329 | display: flex; | ||
| 330 | align-items: center; | ||
| 331 | justify-content: space-between; | ||
| 332 | padding: 20rpx 30rpx; | ||
| 333 | padding-bottom: calc(20rpx + env(safe-area-inset-bottom)); | ||
| 334 | box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.05); | ||
| 335 | z-index: 99; | ||
| 336 | |||
| 337 | .cancel-btn { | ||
| 338 | flex: 1; | ||
| 339 | text-align: center; | ||
| 340 | padding: 24rpx 0; | ||
| 341 | border-radius: 40rpx; | ||
| 342 | font-size: 28rpx; | ||
| 343 | background-color: #f5f5f5; | ||
| 344 | color: #666; | ||
| 345 | margin-right: 20rpx; | ||
| 346 | } | ||
| 347 | |||
| 348 | .submit-btn { | ||
| 349 | flex: 2; | ||
| 350 | text-align: center; | ||
| 351 | padding: 24rpx 0; | ||
| 352 | border-radius: 40rpx; | ||
| 353 | font-size: 28rpx; | ||
| 354 | background-color: #AD181F; | ||
| 355 | color: #fff; | ||
| 356 | } | ||
| 357 | } | ||
| 358 | </style> |
level/ztx/costSettlementDetail.vue
0 → 100644
This diff is collapsed.
Click to expand it.
level/ztx/examinationAudit.vue
0 → 100644
| 1 | <template> | ||
| 2 | <view class="audit-page"> | ||
| 3 | <!-- 提示信息 --> | ||
| 4 | <view class="tips-box"> | ||
| 5 | <uni-icons type="info" size="18" color="#13B5B1"></uni-icons> | ||
| 6 | <text class="tips-text" v-if="type === 'batch'">批量审核 {{ ids.split(',').length }} 条记录</text> | ||
| 7 | <text class="tips-text" v-else>单个审核</text> | ||
| 8 | </view> | ||
| 9 | |||
| 10 | <!-- 审核表单 --> | ||
| 11 | <view class="form-section"> | ||
| 12 | <view class="section-header"> | ||
| 13 | <uni-icons type="edit" size="18" color="#AD181F"></uni-icons> | ||
| 14 | <text class="section-title">审核信息</text> | ||
| 15 | </view> | ||
| 16 | |||
| 17 | <view class="form-card"> | ||
| 18 | <view class="form-item"> | ||
| 19 | <text class="form-label">审批结果</text> | ||
| 20 | <view class="radio-group"> | ||
| 21 | <view | ||
| 22 | class="radio-item" | ||
| 23 | :class="{ selected: form.flag === '1' }" | ||
| 24 | @click="form.flag = '1'" | ||
| 25 | > | ||
| 26 | <view class="radio-circle"> | ||
| 27 | <uni-icons v-if="form.flag === '1'" type="checkmark" size="10" color="#fff"></uni-icons> | ||
| 28 | </view> | ||
| 29 | <text>审批通过</text> | ||
| 30 | </view> | ||
| 31 | <view | ||
| 32 | class="radio-item" | ||
| 33 | :class="{ selected: form.flag === '0' }" | ||
| 34 | @click="form.flag = '0'" | ||
| 35 | > | ||
| 36 | <view class="radio-circle"> | ||
| 37 | <uni-icons v-if="form.flag === '0'" type="checkmark" size="10" color="#fff"></uni-icons> | ||
| 38 | </view> | ||
| 39 | <text>审批拒绝</text> | ||
| 40 | </view> | ||
| 41 | </view> | ||
| 42 | </view> | ||
| 43 | |||
| 44 | <view class="form-item"> | ||
| 45 | <text class="form-label">备注</text> | ||
| 46 | <textarea | ||
| 47 | v-model="form.reason" | ||
| 48 | class="textarea" | ||
| 49 | placeholder="请输入备注信息(拒绝时必填)" | ||
| 50 | :maxlength="500" | ||
| 51 | /> | ||
| 52 | </view> | ||
| 53 | </view> | ||
| 54 | </view> | ||
| 55 | |||
| 56 | <!-- 提交按钮 --> | ||
| 57 | <view class="submit-wrap"> | ||
| 58 | <button class="btn-cancel" @click="goBack">取消</button> | ||
| 59 | <button class="btn-submit" @click="doSubmit" :disabled="submitting"> | ||
| 60 | <text v-if="!submitting">确认提交</text> | ||
| 61 | <text v-else>提交中...</text> | ||
| 62 | </button> | ||
| 63 | </view> | ||
| 64 | </view> | ||
| 65 | </template> | ||
| 66 | |||
| 67 | <script setup> | ||
| 68 | import * as api from '@/common/api_exam.js' | ||
| 69 | import { ref } from 'vue' | ||
| 70 | import { onLoad } from '@dcloudio/uni-app' | ||
| 71 | |||
| 72 | |||
| 73 | const type = ref('single') // single 或 batch | ||
| 74 | const ids = ref('') | ||
| 75 | const submitting = ref(false) | ||
| 76 | |||
| 77 | const form = ref({ | ||
| 78 | flag: '1', | ||
| 79 | reason: '' | ||
| 80 | }) | ||
| 81 | |||
| 82 | onLoad((options) => { | ||
| 83 | if (options.type) { | ||
| 84 | type.value = options.type | ||
| 85 | } | ||
| 86 | if (options.ids) { | ||
| 87 | ids.value = options.ids | ||
| 88 | } | ||
| 89 | }) | ||
| 90 | |||
| 91 | function goBack() { | ||
| 92 | uni.navigateBack() | ||
| 93 | } | ||
| 94 | |||
| 95 | function doSubmit() { | ||
| 96 | if (form.value.flag === '0' && !form.value.reason) { | ||
| 97 | uni.showToast({ | ||
| 98 | title: '请输入拒绝理由', | ||
| 99 | icon: 'none' | ||
| 100 | }) | ||
| 101 | return | ||
| 102 | } | ||
| 103 | |||
| 104 | if (submitting.value) return | ||
| 105 | submitting.value = true | ||
| 106 | |||
| 107 | const params = { | ||
| 108 | ids: ids.value, | ||
| 109 | flag: form.value.flag, | ||
| 110 | reason: form.value.reason || '' | ||
| 111 | } | ||
| 112 | |||
| 113 | api.ztxAudit(params).then(res => { | ||
| 114 | uni.showToast({ | ||
| 115 | title: '操作成功', | ||
| 116 | icon: 'success' | ||
| 117 | }) | ||
| 118 | setTimeout(() => { | ||
| 119 | uni.navigateBack() | ||
| 120 | }, 1500) | ||
| 121 | }).catch(err => { | ||
| 122 | console.error('审核失败', err) | ||
| 123 | uni.showToast({ | ||
| 124 | title: '操作失败', | ||
| 125 | icon: 'none' | ||
| 126 | }) | ||
| 127 | submitting.value = false | ||
| 128 | }) | ||
| 129 | } | ||
| 130 | </script> | ||
| 131 | |||
| 132 | <style lang="scss" scoped> | ||
| 133 | .audit-page { | ||
| 134 | min-height: 100vh; | ||
| 135 | background-color: #f5f5f5; | ||
| 136 | padding: 20rpx; | ||
| 137 | padding-bottom: 120rpx; | ||
| 138 | } | ||
| 139 | |||
| 140 | .tips-box { | ||
| 141 | background-color: #e8f8f7; | ||
| 142 | border-radius: 12rpx; | ||
| 143 | padding: 24rpx; | ||
| 144 | margin-bottom: 20rpx; | ||
| 145 | display: flex; | ||
| 146 | align-items: center; | ||
| 147 | gap: 12rpx; | ||
| 148 | |||
| 149 | .tips-text { | ||
| 150 | font-size: 26rpx; | ||
| 151 | color: #13B5B1; | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | .form-section { | ||
| 156 | background-color: #fff; | ||
| 157 | border-radius: 16rpx; | ||
| 158 | padding: 30rpx; | ||
| 159 | margin-bottom: 20rpx; | ||
| 160 | } | ||
| 161 | |||
| 162 | .section-header { | ||
| 163 | display: flex; | ||
| 164 | align-items: center; | ||
| 165 | margin-bottom: 30rpx; | ||
| 166 | |||
| 167 | .section-title { | ||
| 168 | font-size: 30rpx; | ||
| 169 | font-weight: 600; | ||
| 170 | color: #333; | ||
| 171 | margin-left: 10rpx; | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | .form-card { | ||
| 176 | .form-item { | ||
| 177 | margin-bottom: 30rpx; | ||
| 178 | |||
| 179 | &:last-child { | ||
| 180 | margin-bottom: 0; | ||
| 181 | } | ||
| 182 | |||
| 183 | .form-label { | ||
| 184 | display: block; | ||
| 185 | font-size: 28rpx; | ||
| 186 | color: #333; | ||
| 187 | margin-bottom: 16rpx; | ||
| 188 | font-weight: 500; | ||
| 189 | } | ||
| 190 | |||
| 191 | .radio-group { | ||
| 192 | display: flex; | ||
| 193 | gap: 40rpx; | ||
| 194 | } | ||
| 195 | |||
| 196 | .radio-item { | ||
| 197 | display: flex; | ||
| 198 | align-items: center; | ||
| 199 | gap: 12rpx; | ||
| 200 | font-size: 28rpx; | ||
| 201 | color: #333; | ||
| 202 | |||
| 203 | .radio-circle { | ||
| 204 | width: 36rpx; | ||
| 205 | height: 36rpx; | ||
| 206 | border-radius: 50%; | ||
| 207 | border: 2rpx solid #ddd; | ||
| 208 | display: flex; | ||
| 209 | align-items: center; | ||
| 210 | justify-content: center; | ||
| 211 | } | ||
| 212 | |||
| 213 | &.selected { | ||
| 214 | .radio-circle { | ||
| 215 | background-color: #13B5B1; | ||
| 216 | border-color: #13B5B1; | ||
| 217 | } | ||
| 218 | } | ||
| 219 | } | ||
| 220 | |||
| 221 | .textarea { | ||
| 222 | width: 100%; | ||
| 223 | height: 200rpx; | ||
| 224 | border: 1px solid #eee; | ||
| 225 | border-radius: 12rpx; | ||
| 226 | padding: 20rpx; | ||
| 227 | font-size: 28rpx; | ||
| 228 | color: #333; | ||
| 229 | background-color: #fafafa; | ||
| 230 | box-sizing: border-box; | ||
| 231 | } | ||
| 232 | } | ||
| 233 | } | ||
| 234 | |||
| 235 | .submit-wrap { | ||
| 236 | position: fixed; | ||
| 237 | bottom: 0; | ||
| 238 | left: 0; | ||
| 239 | right: 0; | ||
| 240 | height: 110rpx; | ||
| 241 | background-color: #fff; | ||
| 242 | display: flex; | ||
| 243 | align-items: center; | ||
| 244 | justify-content: center; | ||
| 245 | gap: 30rpx; | ||
| 246 | padding: 0 30rpx; | ||
| 247 | box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.05); | ||
| 248 | |||
| 249 | button { | ||
| 250 | flex: 1; | ||
| 251 | height: 80rpx; | ||
| 252 | line-height: 80rpx; | ||
| 253 | font-size: 28rpx; | ||
| 254 | border-radius: 40rpx; | ||
| 255 | border: none; | ||
| 256 | } | ||
| 257 | |||
| 258 | .btn-cancel { | ||
| 259 | background-color: #f5f5f5; | ||
| 260 | color: #666; | ||
| 261 | } | ||
| 262 | |||
| 263 | .btn-submit { | ||
| 264 | background: linear-gradient(135deg, #13B5B1, #15c5c1); | ||
| 265 | color: #fff; | ||
| 266 | |||
| 267 | &[disabled] { | ||
| 268 | background: #ccc; | ||
| 269 | } | ||
| 270 | } | ||
| 271 | } | ||
| 272 | </style> |
level/ztx/examinationDetail.vue
0 → 100644
| 1 | <template> | ||
| 2 | <view class="detail-page"> | ||
| 3 | <!-- 基本信息 --> | ||
| 4 | <view class="section"> | ||
| 5 | <view class="section-header"> | ||
| 6 | <uni-icons type="paperclip" size="18" color="#AD181F"></uni-icons> | ||
| 7 | <text class="section-title">基本信息</text> | ||
| 8 | </view> | ||
| 9 | <view class="info-card"> | ||
| 10 | <view class="info-row"> | ||
| 11 | <text class="label">申请单位</text> | ||
| 12 | <text class="value">{{ form.memName || '-' }}</text> | ||
| 13 | </view> | ||
| 14 | <view class="info-row"> | ||
| 15 | <text class="label">所属协会</text> | ||
| 16 | <text class="value">{{ form.shenMemName || '-' }}</text> | ||
| 17 | </view> | ||
| 18 | <view class="info-row"> | ||
| 19 | <text class="label">审核状态</text> | ||
| 20 | <text class="value" :class="getStatusClass(form.auditStatus)"> | ||
| 21 | {{ getStatusText(form.auditStatus) }} | ||
| 22 | </text> | ||
| 23 | </view> | ||
| 24 | <view class="info-row"> | ||
| 25 | <text class="label">是否需要</text> | ||
| 26 | <text class="value">{{ form.selfSelect == 1 ? '否' : '是' }}</text> | ||
| 27 | </view> | ||
| 28 | <view class="info-row"> | ||
| 29 | <text class="label">会员有效期</text> | ||
| 30 | <text class="value">{{ formatDate(form.memValidDate) }}</text> | ||
| 31 | </view> | ||
| 32 | <view class="info-row"> | ||
| 33 | <text class="label">申请日期</text> | ||
| 34 | <text class="value">{{ formatDate(form.commitTime) }}</text> | ||
| 35 | </view> | ||
| 36 | <view class="info-row"> | ||
| 37 | <text class="label">审核日期</text> | ||
| 38 | <text class="value">{{ formatDate(form.auditTime) }}</text> | ||
| 39 | </view> | ||
| 40 | <view class="info-row"> | ||
| 41 | <text class="label">考官</text> | ||
| 42 | <text class="value">{{ form.examiners || '-' }}</text> | ||
| 43 | </view> | ||
| 44 | </view> | ||
| 45 | </view> | ||
| 46 | |||
| 47 | <!-- 审核记录 --> | ||
| 48 | <view class="section" v-if="auditList.length > 0"> | ||
| 49 | <view class="section-header"> | ||
| 50 | <uni-icons type="checkmark-circle" size="18" color="#AD181F"></uni-icons> | ||
| 51 | <text class="section-title">审核记录</text> | ||
| 52 | </view> | ||
| 53 | <view class="audit-list"> | ||
| 54 | <view class="audit-item" v-for="(item, index) in auditList" :key="index"> | ||
| 55 | <view class="audit-dot" :class="item.auditResult == 2 ? 'pass' : 'fail'"></view> | ||
| 56 | <view class="audit-content"> | ||
| 57 | <view class="audit-row"> | ||
| 58 | <text class="audit-label">审核协会</text> | ||
| 59 | <text class="audit-value">{{ item.auditDeptName || '-' }}</text> | ||
| 60 | </view> | ||
| 61 | <view class="audit-row"> | ||
| 62 | <text class="audit-label">审核时间</text> | ||
| 63 | <text class="audit-value">{{ formatDateTime(item.auditTime) }}</text> | ||
| 64 | </view> | ||
| 65 | <view class="audit-row"> | ||
| 66 | <text class="audit-label">审核状态</text> | ||
| 67 | <text class="audit-value" :class="item.auditResult == 2 ? 'text-success' : 'text-danger'"> | ||
| 68 | {{ item.auditResult == 2 ? '通过' : '拒绝' }} | ||
| 69 | </text> | ||
| 70 | </view> | ||
| 71 | <view class="audit-row" v-if="item.auditMsg"> | ||
| 72 | <text class="audit-label">备注</text> | ||
| 73 | <text class="audit-value">{{ item.auditMsg }}</text> | ||
| 74 | </view> | ||
| 75 | </view> | ||
| 76 | </view> | ||
| 77 | </view> | ||
| 78 | </view> | ||
| 79 | |||
| 80 | <!-- 考官信息 --> | ||
| 81 | <view class="section" v-if="examinerList.length > 0"> | ||
| 82 | <view class="section-header"> | ||
| 83 | <uni-icons type="person" size="18" color="#AD181F"></uni-icons> | ||
| 84 | <text class="section-title">考官信息</text> | ||
| 85 | </view> | ||
| 86 | <view class="examiner-table" v-if="examinerList.length > 0"> | ||
| 87 | <view class="table-header"> | ||
| 88 | <view class="th th-name">姓名</view> | ||
| 89 | <view class="th th-code">会员号</view> | ||
| 90 | <view class="th th-idcard">证件号码</view> | ||
| 91 | </view> | ||
| 92 | <view class="table-body"> | ||
| 93 | <view class="table-row" v-for="(item, index) in examinerList" :key="index"> | ||
| 94 | <view class="td td-name">{{ item.perName }}</view> | ||
| 95 | <view class="td td-code">{{ item.perCode || '-' }}</view> | ||
| 96 | <view class="td td-idcard">{{ item.perIdcCode || '-' }}</view> | ||
| 97 | </view> | ||
| 98 | </view> | ||
| 99 | </view> | ||
| 100 | <view class="no-data" v-else> | ||
| 101 | <text>暂无考官信息</text> | ||
| 102 | </view> | ||
| 103 | </view> | ||
| 104 | </view> | ||
| 105 | </template> | ||
| 106 | |||
| 107 | <script setup> | ||
| 108 | import * as api from '@/common/api_exam.js' | ||
| 109 | import { ref } from 'vue' | ||
| 110 | import { onLoad } from '@dcloudio/uni-app' | ||
| 111 | |||
| 112 | const form = ref({}) | ||
| 113 | const auditList = ref([]) | ||
| 114 | const examinerList = ref([]) | ||
| 115 | |||
| 116 | const auditStatusMap = { 1: '审核中', 2: '审核通过', 3: '审核拒绝' } | ||
| 117 | |||
| 118 | onLoad((options) => { | ||
| 119 | if (options.item) { | ||
| 120 | try { | ||
| 121 | const itemData = JSON.parse(decodeURIComponent(options.item)) | ||
| 122 | form.value = itemData | ||
| 123 | if (itemData.auditList) { | ||
| 124 | auditList.value = itemData.auditList | ||
| 125 | } | ||
| 126 | if (itemData.memId) { | ||
| 127 | getExaminerList(itemData.memId) | ||
| 128 | } | ||
| 129 | } catch (e) { | ||
| 130 | console.error('解析数据失败', e) | ||
| 131 | } | ||
| 132 | } | ||
| 133 | }) | ||
| 134 | |||
| 135 | function getExaminerList(memId) { | ||
| 136 | api.listInfo({ memId: memId }).then(res => { | ||
| 137 | if (res.rows) { | ||
| 138 | examinerList.value = res.rows | ||
| 139 | } | ||
| 140 | }).catch(err => { | ||
| 141 | console.error('获取考官列表失败', err) | ||
| 142 | }) | ||
| 143 | } | ||
| 144 | |||
| 145 | function getStatusText(status) { | ||
| 146 | return auditStatusMap[status] || '-' | ||
| 147 | } | ||
| 148 | |||
| 149 | function getStatusClass(status) { | ||
| 150 | const classMap = { | ||
| 151 | 1: 'text-warning', | ||
| 152 | 2: 'text-success', | ||
| 153 | 3: 'text-danger' | ||
| 154 | } | ||
| 155 | return classMap[status] || '' | ||
| 156 | } | ||
| 157 | |||
| 158 | function formatDate(dateStr) { | ||
| 159 | if (!dateStr) return '-' | ||
| 160 | return dateStr.substring(0, 10) | ||
| 161 | } | ||
| 162 | |||
| 163 | function formatDateTime(dateStr) { | ||
| 164 | if (!dateStr) return '-' | ||
| 165 | if (typeof dateStr === 'string' && dateStr.indexOf('T') > -1) { | ||
| 166 | const [date, time] = dateStr.split('T') | ||
| 167 | return `${date} ${time?.slice(0, 5) || ''}` | ||
| 168 | } | ||
| 169 | return dateStr | ||
| 170 | } | ||
| 171 | </script> | ||
| 172 | |||
| 173 | <style lang="scss" scoped> | ||
| 174 | .detail-page { | ||
| 175 | min-height: 100vh; | ||
| 176 | background-color: #f5f5f5; | ||
| 177 | padding: 20rpx; | ||
| 178 | padding-bottom: 40rpx; | ||
| 179 | } | ||
| 180 | |||
| 181 | .section { | ||
| 182 | background-color: #fff; | ||
| 183 | border-radius: 16rpx; | ||
| 184 | padding: 30rpx; | ||
| 185 | margin-bottom: 20rpx; | ||
| 186 | } | ||
| 187 | |||
| 188 | .section-header { | ||
| 189 | display: flex; | ||
| 190 | align-items: center; | ||
| 191 | margin-bottom: 24rpx; | ||
| 192 | |||
| 193 | .section-title { | ||
| 194 | font-size: 30rpx; | ||
| 195 | font-weight: 600; | ||
| 196 | color: #333; | ||
| 197 | margin-left: 10rpx; | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | .info-card { | ||
| 202 | .info-row { | ||
| 203 | display: flex; | ||
| 204 | justify-content: space-between; | ||
| 205 | padding: 16rpx 0; | ||
| 206 | border-bottom: 1px solid #f0f0f0; | ||
| 207 | |||
| 208 | &:last-child { | ||
| 209 | border-bottom: none; | ||
| 210 | } | ||
| 211 | |||
| 212 | .label { | ||
| 213 | font-size: 26rpx; | ||
| 214 | color: #999; | ||
| 215 | flex-shrink: 0; | ||
| 216 | } | ||
| 217 | |||
| 218 | .value { | ||
| 219 | font-size: 26rpx; | ||
| 220 | color: #333; | ||
| 221 | text-align: right; | ||
| 222 | margin-left: 20rpx; | ||
| 223 | |||
| 224 | &.text-success { | ||
| 225 | color: #4caf50; | ||
| 226 | } | ||
| 227 | |||
| 228 | &.text-warning { | ||
| 229 | color: #ff9800; | ||
| 230 | } | ||
| 231 | |||
| 232 | &.text-danger { | ||
| 233 | color: #f44336; | ||
| 234 | } | ||
| 235 | } | ||
| 236 | } | ||
| 237 | } | ||
| 238 | |||
| 239 | /* 审核记录 */ | ||
| 240 | .audit-list { | ||
| 241 | .audit-item { | ||
| 242 | display: flex; | ||
| 243 | padding: 20rpx 0; | ||
| 244 | border-bottom: 1px dashed #eee; | ||
| 245 | |||
| 246 | &:last-child { | ||
| 247 | border-bottom: none; | ||
| 248 | } | ||
| 249 | |||
| 250 | .audit-dot { | ||
| 251 | width: 14rpx; | ||
| 252 | height: 14rpx; | ||
| 253 | border-radius: 50%; | ||
| 254 | margin-top: 8rpx; | ||
| 255 | margin-right: 20rpx; | ||
| 256 | flex-shrink: 0; | ||
| 257 | |||
| 258 | &.pass { | ||
| 259 | background-color: #4caf50; | ||
| 260 | } | ||
| 261 | |||
| 262 | &.fail { | ||
| 263 | background-color: #f44336; | ||
| 264 | } | ||
| 265 | } | ||
| 266 | |||
| 267 | .audit-content { | ||
| 268 | flex: 1; | ||
| 269 | |||
| 270 | .audit-row { | ||
| 271 | display: flex; | ||
| 272 | margin-bottom: 10rpx; | ||
| 273 | |||
| 274 | &:last-child { | ||
| 275 | margin-bottom: 0; | ||
| 276 | } | ||
| 277 | |||
| 278 | .audit-label { | ||
| 279 | font-size: 24rpx; | ||
| 280 | color: #999; | ||
| 281 | width: 140rpx; | ||
| 282 | flex-shrink: 0; | ||
| 283 | } | ||
| 284 | |||
| 285 | .audit-value { | ||
| 286 | font-size: 26rpx; | ||
| 287 | color: #333; | ||
| 288 | flex: 1; | ||
| 289 | |||
| 290 | &.text-success { | ||
| 291 | color: #4caf50; | ||
| 292 | } | ||
| 293 | |||
| 294 | &.text-danger { | ||
| 295 | color: #f44336; | ||
| 296 | } | ||
| 297 | } | ||
| 298 | } | ||
| 299 | } | ||
| 300 | } | ||
| 301 | } | ||
| 302 | |||
| 303 | /* 考官表格 */ | ||
| 304 | .examiner-table { | ||
| 305 | border: 1px solid #eee; | ||
| 306 | border-radius: 12rpx; | ||
| 307 | overflow: hidden; | ||
| 308 | |||
| 309 | .table-header { | ||
| 310 | display: flex; | ||
| 311 | background-color: #f5f5f5; | ||
| 312 | |||
| 313 | .th { | ||
| 314 | padding: 20rpx 0; | ||
| 315 | text-align: center; | ||
| 316 | font-size: 24rpx; | ||
| 317 | color: #666; | ||
| 318 | font-weight: 500; | ||
| 319 | } | ||
| 320 | } | ||
| 321 | |||
| 322 | .th-name { width: 25%; } | ||
| 323 | .th-code { width: 30%; } | ||
| 324 | .th-idcard { width: 45%; } | ||
| 325 | |||
| 326 | .table-body { | ||
| 327 | .table-row { | ||
| 328 | display: flex; | ||
| 329 | border-bottom: 1px solid #eee; | ||
| 330 | |||
| 331 | &:last-child { | ||
| 332 | border-bottom: none; | ||
| 333 | } | ||
| 334 | |||
| 335 | .td { | ||
| 336 | padding: 20rpx 0; | ||
| 337 | text-align: center; | ||
| 338 | font-size: 24rpx; | ||
| 339 | color: #333; | ||
| 340 | overflow: hidden; | ||
| 341 | text-overflow: ellipsis; | ||
| 342 | white-space: nowrap; | ||
| 343 | } | ||
| 344 | } | ||
| 345 | |||
| 346 | .td-name { width: 25%; } | ||
| 347 | .td-code { width: 30%; } | ||
| 348 | .td-idcard { width: 45%; } | ||
| 349 | } | ||
| 350 | } | ||
| 351 | |||
| 352 | .no-data { | ||
| 353 | padding: 60rpx 0; | ||
| 354 | text-align: center; | ||
| 355 | color: #999; | ||
| 356 | font-size: 26rpx; | ||
| 357 | } | ||
| 358 | </style> |
level/ztx/examinationVerification.vue
0 → 100644
This diff is collapsed.
Click to expand it.
level/ztx/institutionInfo.vue
0 → 100644
| 1 | <template> | ||
| 2 | <view class="institution-page"> | ||
| 3 | <view class="loading-wrap" v-if="loading"> | ||
| 4 | <uni-load-more status="loading"></uni-load-more> | ||
| 5 | </view> | ||
| 6 | |||
| 7 | <view v-else> | ||
| 8 | <!-- 基本信息 --> | ||
| 9 | <view class="section"> | ||
| 10 | <view class="section-header"> | ||
| 11 | <uni-icons type="office" size="18" color="#AD181F"></uni-icons> | ||
| 12 | <text class="section-title">基本信息</text> | ||
| 13 | </view> | ||
| 14 | <view class="info-card"> | ||
| 15 | <view class="info-row"> | ||
| 16 | <text class="label">所属协会</text> | ||
| 17 | <text class="value">{{ form.parentDeptName || '-' }}</text> | ||
| 18 | </view> | ||
| 19 | <!-- <view class="info-row"> | ||
| 20 | <text class="label">会员编号</text> | ||
| 21 | <text class="value">{{ form.menCode || '-' }}</text> | ||
| 22 | </view> --> | ||
| 23 | <view class="info-row"> | ||
| 24 | <text class="label">机构名称</text> | ||
| 25 | <text class="value">{{ form.name || '-' }}</text> | ||
| 26 | </view> | ||
| 27 | <view class="info-row"> | ||
| 28 | <text class="label">认证地址</text> | ||
| 29 | <text class="value">{{ form.provinceStr + form.cityStr + form.regionStr || '-' }}</text> | ||
| 30 | </view> | ||
| 31 | <view class="info-row"> | ||
| 32 | <text class="label">详细地址</text> | ||
| 33 | <text class="value">{{ form.adress || '-' }}</text> | ||
| 34 | </view> | ||
| 35 | <view class="info-row"> | ||
| 36 | <text class="label">联系人</text> | ||
| 37 | <text class="value">{{ form.siteContact || '-' }}</text> | ||
| 38 | </view> | ||
| 39 | <view class="info-row"> | ||
| 40 | <text class="label">联系方式</text> | ||
| 41 | <text class="value">{{ form.siteTel || '-' }}</text> | ||
| 42 | </view> | ||
| 43 | <view class="info-row" v-if="form.applyPoints !== undefined"> | ||
| 44 | <text class="label">是否为考点</text> | ||
| 45 | <text class="value">{{ form.applyPoints == 1 ? '是' : '否' }}</text> | ||
| 46 | </view> | ||
| 47 | |||
| 48 | </view> | ||
| 49 | </view> | ||
| 50 | |||
| 51 | <!-- 营业执照 --> | ||
| 52 | <view class="section" v-if="form.businessLicense"> | ||
| 53 | <view class="section-header"> | ||
| 54 | <uni-icons type="document" size="18" color="#AD181F"></uni-icons> | ||
| 55 | <text class="section-title">营业执照</text> | ||
| 56 | </view> | ||
| 57 | <view class="info-card"> | ||
| 58 | <view class="info-row"> | ||
| 59 | <text class="label">营业执照名称</text> | ||
| 60 | <text class="value">{{ form.companyName || '-' }}</text> | ||
| 61 | </view> | ||
| 62 | <view class="info-row"> | ||
| 63 | <text class="label">社会信用代码</text> | ||
| 64 | <text class="value">{{ form.creditCode || '-' }}</text> | ||
| 65 | </view> | ||
| 66 | <view class="info-row" v-if="form.validityDate"> | ||
| 67 | <text class="label">有效期</text> | ||
| 68 | <text class="value">{{ form.validityDate }}</text> | ||
| 69 | </view> | ||
| 70 | <view class="info-row"> | ||
| 71 | <text class="label">营业执照</text> | ||
| 72 | <view> | ||
| 73 | <template v-slot:footer> | ||
| 74 | <view style="width: 50vw;word-break: break-all;text-align: right;" @click="download(form.businessLicense[0]?.url)" v-if="form.businessLicense&&form.businessLicense?.length>0"> | ||
| 75 | <text class="text-primary">{{form.businessLicense[0]?.name}}</text> | ||
| 76 | |||
| 77 | </view> | ||
| 78 | </template> | ||
| 79 | </view> | ||
| 80 | </view> | ||
| 81 | </view> | ||
| 82 | </view> | ||
| 83 | |||
| 84 | <!-- 法人信息 --> | ||
| 85 | <view class="section"> | ||
| 86 | <view class="section-header"> | ||
| 87 | <uni-icons type="person" size="18" color="#AD181F"></uni-icons> | ||
| 88 | <text class="section-title">法人信息</text> | ||
| 89 | </view> | ||
| 90 | <view class="info-card"> | ||
| 91 | <view class="info-row"> | ||
| 92 | <text class="label">法人姓名</text> | ||
| 93 | <text class="value">{{ form.legal || '-' }}</text> | ||
| 94 | </view> | ||
| 95 | <view class="info-row"> | ||
| 96 | <text class="label">法人证件号</text> | ||
| 97 | <text class="value">{{ form.legalIdcCode || '-' }}</text> | ||
| 98 | </view> | ||
| 99 | </view> | ||
| 100 | </view> | ||
| 101 | |||
| 102 | <!-- 证件照片 --> | ||
| 103 | <view class="section" v-if="form.legalIdcPhoto && form.legalIdcPhoto.length > 0"> | ||
| 104 | <view class="section-header"> | ||
| 105 | <uni-icons type="photo" size="18" color="#AD181F"></uni-icons> | ||
| 106 | <text class="section-title">法人证件照</text> | ||
| 107 | </view> | ||
| 108 | <view class="image-list"> | ||
| 109 | <image | ||
| 110 | v-for="(img, index) in form.legalIdcPhoto" | ||
| 111 | :key="index" | ||
| 112 | class="preview-image" | ||
| 113 | :src="getImageUrl(img)" | ||
| 114 | mode="aspectFit" | ||
| 115 | @click="previewImage(form.legalIdcPhoto, index)" | ||
| 116 | /> | ||
| 117 | </view> | ||
| 118 | </view> | ||
| 119 | |||
| 120 | <!-- 机构照片 --> | ||
| 121 | <view class="section" v-if="form.pictures && form.pictures.length > 0"> | ||
| 122 | <view class="section-header"> | ||
| 123 | <uni-icons type="image" size="18" color="#AD181F"></uni-icons> | ||
| 124 | <text class="section-title">机构照片</text> | ||
| 125 | </view> | ||
| 126 | <view class="image-list"> | ||
| 127 | <image | ||
| 128 | v-for="(img, index) in form.pictures" | ||
| 129 | :key="index" | ||
| 130 | class="preview-image" | ||
| 131 | :src="getImageUrl(img)" | ||
| 132 | mode="aspectFit" | ||
| 133 | @click="previewImage(form.pictures, index)" | ||
| 134 | /> | ||
| 135 | </view> | ||
| 136 | </view> | ||
| 137 | </view> | ||
| 138 | </view> | ||
| 139 | </template> | ||
| 140 | |||
| 141 | <script setup> | ||
| 142 | import * as api from '@/common/api.js' | ||
| 143 | import { ref } from 'vue' | ||
| 144 | import { onLoad } from '@dcloudio/uni-app' | ||
| 145 | |||
| 146 | // const config = require('@/config.js') | ||
| 147 | import config from '@/config.js' | ||
| 148 | |||
| 149 | const loading = ref(false) | ||
| 150 | const form = ref({}) | ||
| 151 | |||
| 152 | onLoad((options) => { | ||
| 153 | if (options.memId) { | ||
| 154 | getInstitutionInfo(options.memId) | ||
| 155 | } | ||
| 156 | }) | ||
| 157 | function download(url) { | ||
| 158 | console.log(url) | ||
| 159 | if (url.indexOf('.png') > -1 || url.indexOf('.jpg') > -1) { | ||
| 160 | if(url.indexOf('http')>-1){ | ||
| 161 | uni.previewImage({ | ||
| 162 | urls: [url], | ||
| 163 | success: function(res) { | ||
| 164 | console.log(res,[url],'111') | ||
| 165 | } | ||
| 166 | }) | ||
| 167 | } else { | ||
| 168 | uni.previewImage({ | ||
| 169 | urls: [config.baseUrl_api + url], | ||
| 170 | success: function(res) { | ||
| 171 | console.log(url,'222') | ||
| 172 | } | ||
| 173 | }) | ||
| 174 | } | ||
| 175 | } else { | ||
| 176 | if(url.indexOf('http')>-1){ | ||
| 177 | goWebView(url) | ||
| 178 | } else { | ||
| 179 | goWebView(config.baseUrl_api + url) | ||
| 180 | } | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 184 | function goWebView(url) { | ||
| 185 | url = url.replace("http://", "https://") | ||
| 186 | uni.showLoading({ | ||
| 187 | title: '下载中' | ||
| 188 | }); | ||
| 189 | uni.downloadFile({ | ||
| 190 | url: url, | ||
| 191 | success: function(res) { | ||
| 192 | uni.hideLoading(); | ||
| 193 | var filePath = res.tempFilePath; | ||
| 194 | uni.showLoading({ | ||
| 195 | title: '正在打开' | ||
| 196 | }); | ||
| 197 | uni.openDocument({ | ||
| 198 | filePath: filePath, | ||
| 199 | showMenu: true, | ||
| 200 | success: function(res) { | ||
| 201 | uni.hideLoading(); | ||
| 202 | }, | ||
| 203 | fail: function(err) { | ||
| 204 | uni.hideLoading(); | ||
| 205 | uni.showToast({ | ||
| 206 | title: err, | ||
| 207 | icon: 'none', | ||
| 208 | duration: 2000 | ||
| 209 | }); | ||
| 210 | } | ||
| 211 | }); | ||
| 212 | }, | ||
| 213 | fail: function(error) { | ||
| 214 | uni.hideLoading(); | ||
| 215 | uni.showToast({ | ||
| 216 | title:`下载失败`, | ||
| 217 | icon: 'none', | ||
| 218 | duration: 2000 | ||
| 219 | }); | ||
| 220 | } | ||
| 221 | }); | ||
| 222 | } | ||
| 223 | function getInstitutionInfo(memId) { | ||
| 224 | loading.value = true | ||
| 225 | api.getGroupMemberInfoById(memId).then(res => { | ||
| 226 | loading.value = false | ||
| 227 | if (res.data) { | ||
| 228 | form.value = res.data | ||
| 229 | form.value.businessLicense = JSON.parse((form.value.businessLicense)) | ||
| 230 | // 处理图片字段 | ||
| 231 | if (form.value.pictures && typeof form.value.pictures === 'string') { | ||
| 232 | form.value.pictures = form.value.pictures.split(',').filter(Boolean) | ||
| 233 | } | ||
| 234 | if (form.value.legalIdcPhoto && typeof form.value.legalIdcPhoto === 'string') { | ||
| 235 | form.value.legalIdcPhoto = form.value.legalIdcPhoto.split(',').filter(Boolean) | ||
| 236 | } | ||
| 237 | } | ||
| 238 | }).catch(err => { | ||
| 239 | loading.value = false | ||
| 240 | console.error('获取机构资料失败', err) | ||
| 241 | uni.showToast({ | ||
| 242 | title: '获取机构资料失败', | ||
| 243 | icon: 'none' | ||
| 244 | }) | ||
| 245 | }) | ||
| 246 | } | ||
| 247 | |||
| 248 | function getImageUrl(path) { | ||
| 249 | if (!path) return '' | ||
| 250 | if (path.startsWith('http')) return path | ||
| 251 | return config.baseUrl_api + path | ||
| 252 | } | ||
| 253 | |||
| 254 | function previewImage(images, currentIndex) { | ||
| 255 | const urls = images.map(img => getImageUrl(img)) | ||
| 256 | uni.previewImage({ | ||
| 257 | urls: urls, | ||
| 258 | current: currentIndex | ||
| 259 | }) | ||
| 260 | } | ||
| 261 | </script> | ||
| 262 | |||
| 263 | <style lang="scss" scoped> | ||
| 264 | .institution-page { | ||
| 265 | min-height: 100vh; | ||
| 266 | background-color: #f5f5f5; | ||
| 267 | padding: 20rpx; | ||
| 268 | padding-bottom: 40rpx; | ||
| 269 | } | ||
| 270 | |||
| 271 | .loading-wrap { | ||
| 272 | padding: 100rpx 0; | ||
| 273 | text-align: center; | ||
| 274 | } | ||
| 275 | |||
| 276 | .section { | ||
| 277 | background-color: #fff; | ||
| 278 | border-radius: 16rpx; | ||
| 279 | padding: 30rpx; | ||
| 280 | margin-bottom: 20rpx; | ||
| 281 | } | ||
| 282 | |||
| 283 | .section-header { | ||
| 284 | display: flex; | ||
| 285 | align-items: center; | ||
| 286 | margin-bottom: 24rpx; | ||
| 287 | |||
| 288 | .section-title { | ||
| 289 | font-size: 30rpx; | ||
| 290 | font-weight: 600; | ||
| 291 | color: #333; | ||
| 292 | margin-left: 10rpx; | ||
| 293 | } | ||
| 294 | } | ||
| 295 | |||
| 296 | .info-card { | ||
| 297 | .info-row { | ||
| 298 | display: flex; | ||
| 299 | justify-content: space-between; | ||
| 300 | padding: 16rpx 0; | ||
| 301 | border-bottom: 1px solid #f0f0f0; | ||
| 302 | |||
| 303 | &:last-child { | ||
| 304 | border-bottom: none; | ||
| 305 | } | ||
| 306 | |||
| 307 | .label { | ||
| 308 | font-size: 26rpx; | ||
| 309 | color: #999; | ||
| 310 | flex-shrink: 0; | ||
| 311 | } | ||
| 312 | |||
| 313 | .value { | ||
| 314 | font-size: 26rpx; | ||
| 315 | color: #333; | ||
| 316 | text-align: right; | ||
| 317 | margin-left: 20rpx; | ||
| 318 | flex: 1; | ||
| 319 | word-break: break-all; | ||
| 320 | } | ||
| 321 | } | ||
| 322 | } | ||
| 323 | |||
| 324 | .image-list { | ||
| 325 | display: flex; | ||
| 326 | flex-wrap: wrap; | ||
| 327 | gap: 20rpx; | ||
| 328 | |||
| 329 | .preview-image { | ||
| 330 | width: 200rpx; | ||
| 331 | height: 200rpx; | ||
| 332 | border-radius: 12rpx; | ||
| 333 | background-color: #f5f5f5; | ||
| 334 | } | ||
| 335 | } | ||
| 336 | </style> |
level/ztx/mail.vue
0 → 100644
| 1 | <template> | ||
| 2 | <view class="cert-mail-page"> | ||
| 3 | <!-- 列表区域 --> | ||
| 4 | <view class="appList"> | ||
| 5 | <view class="appItem" v-for="(item, index) in infoList" :key="index"> | ||
| 6 | <view @click="handleView(item)"> | ||
| 7 | <view class="status"> | ||
| 8 | <text :class="item.postStatus == 1 ? 'text-success' : 'text-warning'"> | ||
| 9 | {{ item.postStatus == 1 ? '已邮寄' : '未邮寄' }} | ||
| 10 | </text> | ||
| 11 | </view> | ||
| 12 | <view class="date" v-if="item.submitTime"> | ||
| 13 | <view class="text-primary" v-if="item.payCode">{{ item.payCode }}</view> | ||
| 14 | </view> | ||
| 15 | |||
| 16 | <view class="name mt0">{{ item.name }}</view> | ||
| 17 | <view class="flexbox"> | ||
| 18 | <view> | ||
| 19 | 缴费单位 | ||
| 20 | <view>{{ item.memberName }}</view> | ||
| 21 | </view> | ||
| 22 | <view> | ||
| 23 | 证书人数 | ||
| 24 | <view>{{ item.totalNum }}</view> | ||
| 25 | </view> | ||
| 26 | </view> | ||
| 27 | <view class="flex f-j-s"> | ||
| 28 | <view class="mail-time" v-if="item.submitTime"> | ||
| 29 | 邮寄时间:{{ formatDate(item.submitTime) }} | ||
| 30 | </view> | ||
| 31 | <view class="mail-time" v-if="item.postCode "> | ||
| 32 | <view>物流编号{{ item.postCode || '-' }}</view> | ||
| 33 | </view> | ||
| 34 | </view> | ||
| 35 | </view> | ||
| 36 | <view class="func"> | ||
| 37 | <button | ||
| 38 | v-if="deptType == '1' && item.postStatus != 1" | ||
| 39 | class="btn-mail" | ||
| 40 | @click.stop="handleMail(item)" | ||
| 41 | >邮寄证书</button> | ||
| 42 | <button class="btn-logistics" @click.stop="handleLogistics(item)">物流跟踪</button> | ||
| 43 | </view> | ||
| 44 | </view> | ||
| 45 | </view> | ||
| 46 | |||
| 47 | <!-- 空数据 --> | ||
| 48 | <view class="nodata" v-if="infoList.length == 0 && !loading"> | ||
| 49 | <image mode="aspectFit" src="/static/nodata.png"></image> | ||
| 50 | <text>暂无数据</text> | ||
| 51 | </view> | ||
| 52 | |||
| 53 | <!-- 上拉加载 --> | ||
| 54 | <view class="loading"> | ||
| 55 | <uni-load-more :status="loadStatus" :contentText="loadMoreText"></uni-load-more> | ||
| 56 | </view> | ||
| 57 | </view> | ||
| 58 | </template> | ||
| 59 | |||
| 60 | <script setup> | ||
| 61 | import * as api from '@/common/api.js' | ||
| 62 | import { ref, computed } from 'vue' | ||
| 63 | import { onLoad, onShow, onReachBottom } from '@dcloudio/uni-app' | ||
| 64 | |||
| 65 | const app = getApp() | ||
| 66 | const loading = ref(false) | ||
| 67 | |||
| 68 | // 加载状态 | ||
| 69 | const loadStatus = ref('more') // more / loading / nomore | ||
| 70 | const loadMoreText = { | ||
| 71 | contentdown: '上拉加载更多', | ||
| 72 | contentrefresh: '正在加载...', | ||
| 73 | contentnomore: '没有更多了' | ||
| 74 | } | ||
| 75 | |||
| 76 | // 请求参数 | ||
| 77 | const queryParams = ref({ | ||
| 78 | pageNum: 1, | ||
| 79 | pageSize: 10, | ||
| 80 | type: '1' | ||
| 81 | }) | ||
| 82 | |||
| 83 | // 列表数据 | ||
| 84 | const infoList = ref([]) | ||
| 85 | const total = ref(0) | ||
| 86 | const deptType = ref('') | ||
| 87 | |||
| 88 | onLoad((options) => { | ||
| 89 | if (options.type) { | ||
| 90 | queryParams.value.type = options.type | ||
| 91 | } | ||
| 92 | }) | ||
| 93 | |||
| 94 | onShow(() => { | ||
| 95 | if (app.globalData.isLogin) { | ||
| 96 | init() | ||
| 97 | } else { | ||
| 98 | app.firstLoadCallback = () => { | ||
| 99 | init() | ||
| 100 | } | ||
| 101 | } | ||
| 102 | }) | ||
| 103 | |||
| 104 | // 初始化(刷新) | ||
| 105 | function init() { | ||
| 106 | deptType.value = app.globalData.deptType | ||
| 107 | // 重置列表和页码 | ||
| 108 | infoList.value = [] | ||
| 109 | queryParams.value.pageNum = 1 | ||
| 110 | loadStatus.value = 'more' | ||
| 111 | getList() | ||
| 112 | } | ||
| 113 | |||
| 114 | // 获取列表 | ||
| 115 | function getList() { | ||
| 116 | // 没有更多数据直接返回 | ||
| 117 | if (loadStatus.value === 'nomore') return | ||
| 118 | |||
| 119 | loading.value = true | ||
| 120 | loadStatus.value = 'loading' | ||
| 121 | uni.showLoading({ title: '加载中' }) | ||
| 122 | |||
| 123 | api.paymentList({ ...queryParams.value }).then(res => { | ||
| 124 | const data = res.rows || [] | ||
| 125 | const totalData = res.total || 0 | ||
| 126 | |||
| 127 | // 拼接数据 | ||
| 128 | infoList.value = [...infoList.value, ...data] | ||
| 129 | total.value = totalData | ||
| 130 | |||
| 131 | // 判断是否还有更多 | ||
| 132 | if (infoList.value.length >= totalData) { | ||
| 133 | loadStatus.value = 'nomore' | ||
| 134 | } else { | ||
| 135 | loadStatus.value = 'more' | ||
| 136 | } | ||
| 137 | |||
| 138 | loading.value = false | ||
| 139 | uni.hideLoading() | ||
| 140 | }).catch(() => { | ||
| 141 | loading.value = false | ||
| 142 | uni.hideLoading() | ||
| 143 | loadStatus.value = 'more' | ||
| 144 | }) | ||
| 145 | } | ||
| 146 | |||
| 147 | // 上拉加载下一页 | ||
| 148 | onReachBottom(() => { | ||
| 149 | if (loadStatus.value !== 'more' || loading.value) return | ||
| 150 | queryParams.value.pageNum++ | ||
| 151 | getList() | ||
| 152 | }) | ||
| 153 | |||
| 154 | // 查看详情 | ||
| 155 | function handleView(item) { | ||
| 156 | uni.navigateTo({ | ||
| 157 | url: `/level/ztx/certDetail?examId=${item.examId}` | ||
| 158 | }) | ||
| 159 | } | ||
| 160 | |||
| 161 | // 邮寄证书 | ||
| 162 | async function handleMail(item) { | ||
| 163 | const res = await uni.showModal({ | ||
| 164 | title: '提示', | ||
| 165 | content: '是否确认寄送快递?', | ||
| 166 | confirmText: '确认', | ||
| 167 | cancelText: '取消' | ||
| 168 | }) | ||
| 169 | |||
| 170 | if (res.confirm) { | ||
| 171 | uni.showLoading({ title: '操作中' }) | ||
| 172 | api.postCert(item.payId).then(() => { | ||
| 173 | uni.hideLoading() | ||
| 174 | uni.showToast({ title: '操作成功', icon: 'success' }) | ||
| 175 | // 操作成功后刷新列表 | ||
| 176 | init() | ||
| 177 | }).catch(() => { | ||
| 178 | uni.hideLoading() | ||
| 179 | }) | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 183 | // 物流跟踪 | ||
| 184 | function handleLogistics(item) { | ||
| 185 | if (item.postStatus != 1 || !item.postCode) { | ||
| 186 | uni.showToast({ title: '暂无物流信息', icon: 'none' }) | ||
| 187 | return | ||
| 188 | } | ||
| 189 | uni.navigateTo({ | ||
| 190 | url: `/level/ztx/certLogistics?payId=${item.payId}&postCode=${item.postCode}&postStatus=${item.postStatus}&submitTime=${item.submitTime || ''}` | ||
| 191 | }) | ||
| 192 | } | ||
| 193 | |||
| 194 | // 时间格式化 | ||
| 195 | function formatDate(dateStr) { | ||
| 196 | if (!dateStr) return '-' | ||
| 197 | return dateStr.substring(0, 10) | ||
| 198 | } | ||
| 199 | |||
| 200 | // 等级转中文 | ||
| 201 | function levelToChinese(level) { | ||
| 202 | const levelMap = { | ||
| 203 | '1': '一', '2': '二', '3': '三', '4': '四', '5': '五', | ||
| 204 | '6': '六', '7': '七', '8': '八', '9': '九', '10': '十' | ||
| 205 | } | ||
| 206 | return levelMap[String(level)] || level | ||
| 207 | } | ||
| 208 | </script> | ||
| 209 | |||
| 210 | <style lang="scss" scoped> | ||
| 211 | .cert-mail-page { | ||
| 212 | min-height: 100vh; | ||
| 213 | background-color: #f5f5f5; | ||
| 214 | padding-bottom: 20rpx; | ||
| 215 | } | ||
| 216 | |||
| 217 | /* 列表区域 */ | ||
| 218 | .appList { | ||
| 219 | padding: 0 20rpx; | ||
| 220 | } | ||
| 221 | |||
| 222 | .appItem { | ||
| 223 | background-color: #fff; | ||
| 224 | border-radius: 16rpx; | ||
| 225 | padding: 30rpx; | ||
| 226 | margin-bottom: 20rpx; | ||
| 227 | box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05); | ||
| 228 | |||
| 229 | .status { | ||
| 230 | display: inline-block; | ||
| 231 | padding: 6rpx 20rpx; | ||
| 232 | border-radius: 20rpx; | ||
| 233 | font-size: 24rpx; | ||
| 234 | margin-bottom: 16rpx; | ||
| 235 | |||
| 236 | .text-success { | ||
| 237 | color: #4caf50; | ||
| 238 | } | ||
| 239 | |||
| 240 | .text-warning { | ||
| 241 | color: #ff9800; | ||
| 242 | } | ||
| 243 | } | ||
| 244 | |||
| 245 | .date { | ||
| 246 | font-size: 24rpx; | ||
| 247 | color: #999; | ||
| 248 | } | ||
| 249 | |||
| 250 | .text-primary { | ||
| 251 | font-size: 28rpx; | ||
| 252 | color: #AD181F; | ||
| 253 | } | ||
| 254 | |||
| 255 | .name { | ||
| 256 | font-size: 28rpx; | ||
| 257 | font-weight: 600; | ||
| 258 | color: #333; | ||
| 259 | margin-bottom: 20rpx; | ||
| 260 | margin-top: 10rpx; | ||
| 261 | |||
| 262 | &.mt0 { | ||
| 263 | margin-top: 0; | ||
| 264 | } | ||
| 265 | } | ||
| 266 | |||
| 267 | .flexbox { | ||
| 268 | display: flex; | ||
| 269 | justify-content: space-between; | ||
| 270 | background-color: #fafafa; | ||
| 271 | border-radius: 12rpx; | ||
| 272 | padding: 20rpx; | ||
| 273 | margin: 20rpx 0; | ||
| 274 | |||
| 275 | view { | ||
| 276 | flex: 1; | ||
| 277 | text-align: center; | ||
| 278 | font-size: 24rpx; | ||
| 279 | color: #999; | ||
| 280 | |||
| 281 | view { | ||
| 282 | font-size: 28rpx; | ||
| 283 | color: #333; | ||
| 284 | font-weight: 500; | ||
| 285 | margin-top: 8rpx; | ||
| 286 | } | ||
| 287 | } | ||
| 288 | } | ||
| 289 | |||
| 290 | .mail-time { | ||
| 291 | font-size: 24rpx; | ||
| 292 | color: #666; | ||
| 293 | margin-top: 16rpx; | ||
| 294 | } | ||
| 295 | |||
| 296 | .func { | ||
| 297 | display: flex; | ||
| 298 | gap: 20rpx; | ||
| 299 | margin-top: 24rpx; | ||
| 300 | padding-top: 24rpx; | ||
| 301 | border-top: 1px solid #f0f0f0; | ||
| 302 | justify-content: flex-end; | ||
| 303 | |||
| 304 | button { | ||
| 305 | height: 64rpx; | ||
| 306 | line-height: 64rpx; | ||
| 307 | font-size: 26rpx; | ||
| 308 | border-radius: 32rpx; | ||
| 309 | border: none; | ||
| 310 | } | ||
| 311 | |||
| 312 | .btn-mail { | ||
| 313 | width: 100px; | ||
| 314 | background: linear-gradient(135deg, #4caf50, #66bb6a); | ||
| 315 | color: #fff; | ||
| 316 | } | ||
| 317 | |||
| 318 | .btn-logistics { | ||
| 319 | width: 100px; | ||
| 320 | background: linear-gradient(135deg, #2196f3, #42a5f5); | ||
| 321 | color: #fff; | ||
| 322 | } | ||
| 323 | } | ||
| 324 | } | ||
| 325 | |||
| 326 | .nodata { | ||
| 327 | display: flex; | ||
| 328 | flex-direction: column; | ||
| 329 | align-items: center; | ||
| 330 | justify-content: center; | ||
| 331 | padding: 100rpx 0; | ||
| 332 | |||
| 333 | image { | ||
| 334 | width: 300rpx; | ||
| 335 | height: 300rpx; | ||
| 336 | } | ||
| 337 | |||
| 338 | text { | ||
| 339 | font-size: 28rpx; | ||
| 340 | color: #999; | ||
| 341 | margin-top: 20rpx; | ||
| 342 | } | ||
| 343 | } | ||
| 344 | |||
| 345 | .loading { | ||
| 346 | padding: 30rpx 0; | ||
| 347 | text-align: center; | ||
| 348 | } | ||
| 349 | </style> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
level/ztx/memberAudit.vue
0 → 100644
| 1 | <template> | ||
| 2 | <view class="audit-page"> | ||
| 3 | <!-- 顶部标签栏 --> | ||
| 4 | <view class="tab-bar"> | ||
| 5 | <view | ||
| 6 | v-for="tab in tabs" | ||
| 7 | :key="tab.value" | ||
| 8 | class="tab-item" | ||
| 9 | :class="{ active: currentTab === tab.value }" | ||
| 10 | @click="onTabChange(tab.value)" | ||
| 11 | > | ||
| 12 | <text class="tab-text">{{ tab.label }}</text> | ||
| 13 | <view class="tab-indicator" v-if="currentTab === tab.value"></view> | ||
| 14 | </view> | ||
| 15 | </view> | ||
| 16 | |||
| 17 | <!-- 列表内容 --> | ||
| 18 | <scroll-view | ||
| 19 | scroll-y | ||
| 20 | class="list-content" | ||
| 21 | @scrolltolower="onLoadMore" | ||
| 22 | > | ||
| 23 | <view class="loading-wrap" v-if="loading && list.length === 0"> | ||
| 24 | <uni-load-more status="loading"></uni-load-more> | ||
| 25 | </view> | ||
| 26 | |||
| 27 | <view class="empty-wrap" v-else-if="!loading && list.length === 0"> | ||
| 28 | <uni-load-more status="noMore"></uni-load-more> | ||
| 29 | </view> | ||
| 30 | |||
| 31 | <view class="card-list" v-else> | ||
| 32 | <view | ||
| 33 | class="card-item" | ||
| 34 | v-for="item in list" | ||
| 35 | :key="item.recordId || item.id" | ||
| 36 | @click="goDetail(item)" | ||
| 37 | > | ||
| 38 | <view class="card-header"> | ||
| 39 | <text class="company-name">{{ item.memName || '-' }}</text> | ||
| 40 | <text class="status-badge" :class="getStatusClass(item.shenAuditStatus)"> | ||
| 41 | {{ getStatusText(item.shenAuditStatus) }} | ||
| 42 | </text> | ||
| 43 | </view> | ||
| 44 | |||
| 45 | <view class="card-body"> | ||
| 46 | <view class="info-row"> | ||
| 47 | <text class="label">所属协会</text> | ||
| 48 | <text class="value">{{ item.shenMemName || '-' }}</text> | ||
| 49 | </view> | ||
| 50 | <view class="info-row"> | ||
| 51 | <text class="label">会员编号</text> | ||
| 52 | <text class="value">{{ item.wfCode || '-' }}</text> | ||
| 53 | </view> | ||
| 54 | <view class="info-row"> | ||
| 55 | <text class="label">认证年限</text> | ||
| 56 | <text class="value">{{ item.renewYear ? item.renewYear + '年' : '-' }}</text> | ||
| 57 | </view> | ||
| 58 | <view class="info-row"> | ||
| 59 | <text class="label">付款费用</text> | ||
| 60 | <text class="value text-red">¥{{ Number(item.finalPrice || 0).toFixed(2) }}</text> | ||
| 61 | </view> | ||
| 62 | <view class="info-row"> | ||
| 63 | <text class="label">提交日期</text> | ||
| 64 | <text class="value">{{ formatDate(item.commitTime) }}</text> | ||
| 65 | </view> | ||
| 66 | </view> | ||
| 67 | |||
| 68 | <view class="card-footer"> | ||
| 69 | <view class="tag-row"> | ||
| 70 | <view class="tag" :class="item.isNew == 1 ? 'tag-new' : 'tag-renew'"> | ||
| 71 | {{ item.isNew == 1 ? '新会员' : '续费' }} | ||
| 72 | </view> | ||
| 73 | </view> | ||
| 74 | <view class="btn-row"> | ||
| 75 | <view class="btn btn-default" @click.stop="goInstitutionInfo(item)">机构资料</view> | ||
| 76 | <view class="btn btn-primary" @click.stop="goAudit(item)" v-if="item.shenAuditStatus == 1">审核</view> | ||
| 77 | </view> | ||
| 78 | </view> | ||
| 79 | </view> | ||
| 80 | </view> | ||
| 81 | |||
| 82 | <view class="load-more-wrap" v-if="list.length > 0"> | ||
| 83 | <uni-load-more :status="loadStatus"></uni-load-more> | ||
| 84 | </view> | ||
| 85 | </scroll-view> | ||
| 86 | </view> | ||
| 87 | </template> | ||
| 88 | |||
| 89 | <script setup> | ||
| 90 | import * as api from '@/common/api_exam.js' | ||
| 91 | import { ref } from 'vue' | ||
| 92 | import { onLoad } from '@dcloudio/uni-app' | ||
| 93 | |||
| 94 | const tabs = [ | ||
| 95 | { label: '全部', value: '' }, | ||
| 96 | { label: '审核中', value: '1' }, | ||
| 97 | { label: '审核通过', value: '2' }, | ||
| 98 | { label: '审核拒绝', value: '3' } | ||
| 99 | ] | ||
| 100 | |||
| 101 | const currentTab = ref('') | ||
| 102 | const list = ref([]) | ||
| 103 | const loading = ref(false) | ||
| 104 | const loadStatus = ref('more') | ||
| 105 | const queryParams = ref({ | ||
| 106 | pageNum: 1, | ||
| 107 | pageSize: 10, | ||
| 108 | auditFlag:'1', | ||
| 109 | |||
| 110 | }) | ||
| 111 | |||
| 112 | onLoad(() => { | ||
| 113 | getList() | ||
| 114 | }) | ||
| 115 | |||
| 116 | function onTabChange(value) { | ||
| 117 | currentTab.value = value | ||
| 118 | list.value = [] | ||
| 119 | queryParams.value.pageNum = 1 | ||
| 120 | getList() | ||
| 121 | } | ||
| 122 | |||
| 123 | function getList() { | ||
| 124 | if (loading.value) return | ||
| 125 | loading.value = true | ||
| 126 | loadStatus.value = 'loading' | ||
| 127 | |||
| 128 | const params = { | ||
| 129 | ...queryParams.value, | ||
| 130 | shenAuditStatus: currentTab.value | ||
| 131 | } | ||
| 132 | |||
| 133 | api.certifiedNewList(params).then(res => { | ||
| 134 | if (res.rows) { | ||
| 135 | if (queryParams.value.pageNum === 1) { | ||
| 136 | list.value = res.rows | ||
| 137 | } else { | ||
| 138 | list.value = [...list.value, ...res.rows] | ||
| 139 | } | ||
| 140 | loadStatus.value = res.rows.length >= queryParams.value.pageSize ? 'more' : 'noMore' | ||
| 141 | } else { | ||
| 142 | list.value = [] | ||
| 143 | loadStatus.value = 'noMore' | ||
| 144 | } | ||
| 145 | }).catch(err => { | ||
| 146 | console.error('获取会员审核列表失败', err) | ||
| 147 | loadStatus.value = 'noMore' | ||
| 148 | }).finally(() => { | ||
| 149 | loading.value = false | ||
| 150 | }) | ||
| 151 | } | ||
| 152 | |||
| 153 | function onLoadMore() { | ||
| 154 | if (loadStatus.value === 'noMore' || loading.value) return | ||
| 155 | queryParams.value.pageNum++ | ||
| 156 | getList() | ||
| 157 | } | ||
| 158 | |||
| 159 | function getStatusText(status) { | ||
| 160 | const map = { 1: '审核中', 2: '审核通过', 3: '审核拒绝', 4: '已撤回' } | ||
| 161 | return map[status] || '-' | ||
| 162 | } | ||
| 163 | |||
| 164 | function getStatusClass(status) { | ||
| 165 | const map = { | ||
| 166 | 1: 'status-warning', | ||
| 167 | 2: 'status-success', | ||
| 168 | 3: 'status-danger', | ||
| 169 | 4: 'status-gray' | ||
| 170 | } | ||
| 171 | return map[status] || '' | ||
| 172 | } | ||
| 173 | |||
| 174 | function formatDate(dateStr) { | ||
| 175 | if (!dateStr) return '-' | ||
| 176 | if (typeof dateStr === 'string' && dateStr.indexOf('T') > -1) { | ||
| 177 | return dateStr.slice(0, 10) | ||
| 178 | } | ||
| 179 | return dateStr | ||
| 180 | } | ||
| 181 | |||
| 182 | function goDetail(item) { | ||
| 183 | uni.navigateTo({ | ||
| 184 | url: `/group/groupOrderDetail?form=${encodeURIComponent(JSON.stringify(item))}` | ||
| 185 | }) | ||
| 186 | } | ||
| 187 | |||
| 188 | function goInstitutionInfo(item) { | ||
| 189 | uni.navigateTo({ | ||
| 190 | url: `/level/ztx/institutionInfo?memId=${item.memId}` | ||
| 191 | }) | ||
| 192 | } | ||
| 193 | |||
| 194 | function goAudit(item) { | ||
| 195 | uni.navigateTo({ | ||
| 196 | url: `/level/ztx/memberAuditPage?type=single&ids=${item.recordId || item.id}` | ||
| 197 | }) | ||
| 198 | } | ||
| 199 | </script> | ||
| 200 | |||
| 201 | <style lang="scss" scoped> | ||
| 202 | .audit-page { | ||
| 203 | min-height: 100vh; | ||
| 204 | background-color: #f5f5f5; | ||
| 205 | } | ||
| 206 | |||
| 207 | .tab-bar { | ||
| 208 | display: flex; | ||
| 209 | background-color: #fff; | ||
| 210 | padding: 0 20rpx; | ||
| 211 | position: sticky; | ||
| 212 | top: 0; | ||
| 213 | z-index: 100; | ||
| 214 | |||
| 215 | .tab-item { | ||
| 216 | flex: 1; | ||
| 217 | display: flex; | ||
| 218 | flex-direction: column; | ||
| 219 | align-items: center; | ||
| 220 | padding: 24rpx 0; | ||
| 221 | position: relative; | ||
| 222 | |||
| 223 | .tab-text { | ||
| 224 | font-size: 28rpx; | ||
| 225 | color: #666; | ||
| 226 | } | ||
| 227 | |||
| 228 | .tab-indicator { | ||
| 229 | position: absolute; | ||
| 230 | bottom: 0; | ||
| 231 | left: 50%; | ||
| 232 | transform: translateX(-50%); | ||
| 233 | width: 80rpx; | ||
| 234 | height: 6rpx; | ||
| 235 | background-color: #AD181F; | ||
| 236 | border-radius: 3rpx; | ||
| 237 | } | ||
| 238 | |||
| 239 | &.active { | ||
| 240 | .tab-text { | ||
| 241 | color: #AD181F; | ||
| 242 | font-weight: 600; | ||
| 243 | } | ||
| 244 | } | ||
| 245 | } | ||
| 246 | } | ||
| 247 | |||
| 248 | .list-content { | ||
| 249 | height: calc(100vh - 100rpx); | ||
| 250 | padding: 20rpx; | ||
| 251 | box-sizing: border-box; | ||
| 252 | } | ||
| 253 | |||
| 254 | .loading-wrap, | ||
| 255 | .empty-wrap { | ||
| 256 | padding: 100rpx 0; | ||
| 257 | text-align: center; | ||
| 258 | } | ||
| 259 | |||
| 260 | .card-list { | ||
| 261 | .card-item { | ||
| 262 | background-color: #fff; | ||
| 263 | border-radius: 16rpx; | ||
| 264 | padding: 30rpx; | ||
| 265 | margin-bottom: 20rpx; | ||
| 266 | box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05); | ||
| 267 | |||
| 268 | .card-header { | ||
| 269 | display: flex; | ||
| 270 | justify-content: space-between; | ||
| 271 | align-items: center; | ||
| 272 | margin-bottom: 24rpx; | ||
| 273 | padding-bottom: 20rpx; | ||
| 274 | border-bottom: 1rpx solid #f0f0f0; | ||
| 275 | |||
| 276 | .company-name { | ||
| 277 | font-size: 32rpx; | ||
| 278 | font-weight: 600; | ||
| 279 | color: #333; | ||
| 280 | flex: 1; | ||
| 281 | margin-right: 20rpx; | ||
| 282 | } | ||
| 283 | |||
| 284 | .status-badge { | ||
| 285 | font-size: 24rpx; | ||
| 286 | padding: 6rpx 16rpx; | ||
| 287 | border-radius: 20rpx; | ||
| 288 | flex-shrink: 0; | ||
| 289 | |||
| 290 | &.status-warning { | ||
| 291 | background-color: #fff7e6; | ||
| 292 | color: #fa8c16; | ||
| 293 | } | ||
| 294 | |||
| 295 | &.status-success { | ||
| 296 | background-color: #f6ffed; | ||
| 297 | color: #52c41a; | ||
| 298 | } | ||
| 299 | |||
| 300 | &.status-danger { | ||
| 301 | background-color: #fff1f0; | ||
| 302 | color: #f5222d; | ||
| 303 | } | ||
| 304 | |||
| 305 | &.status-gray { | ||
| 306 | background-color: #f5f5f5; | ||
| 307 | color: #999; | ||
| 308 | } | ||
| 309 | } | ||
| 310 | } | ||
| 311 | |||
| 312 | .card-body { | ||
| 313 | .info-row { | ||
| 314 | display: flex; | ||
| 315 | justify-content: space-between; | ||
| 316 | padding: 12rpx 0; | ||
| 317 | |||
| 318 | .label { | ||
| 319 | font-size: 26rpx; | ||
| 320 | color: #999; | ||
| 321 | flex-shrink: 0; | ||
| 322 | } | ||
| 323 | |||
| 324 | .value { | ||
| 325 | font-size: 26rpx; | ||
| 326 | color: #333; | ||
| 327 | text-align: right; | ||
| 328 | flex: 1; | ||
| 329 | margin-left: 20rpx; | ||
| 330 | } | ||
| 331 | |||
| 332 | .text-red { | ||
| 333 | color: #AD181F; | ||
| 334 | } | ||
| 335 | } | ||
| 336 | } | ||
| 337 | |||
| 338 | .card-footer { | ||
| 339 | display: flex; | ||
| 340 | justify-content: space-between; | ||
| 341 | align-items: center; | ||
| 342 | margin-top: 20rpx; | ||
| 343 | padding-top: 20rpx; | ||
| 344 | border-top: 1rpx solid #f0f0f0; | ||
| 345 | |||
| 346 | .tag-row { | ||
| 347 | display: flex; | ||
| 348 | gap: 12rpx; | ||
| 349 | |||
| 350 | .tag { | ||
| 351 | font-size: 24rpx; | ||
| 352 | padding: 6rpx 16rpx; | ||
| 353 | border-radius: 20rpx; | ||
| 354 | font-weight: 500; | ||
| 355 | |||
| 356 | &.tag-new { | ||
| 357 | background-color: rgba(#AD181F, 0.1); | ||
| 358 | color: #AD181F; | ||
| 359 | } | ||
| 360 | |||
| 361 | &.tag-renew { | ||
| 362 | background-color: rgba(#999, 0.1); | ||
| 363 | color: #666; | ||
| 364 | } | ||
| 365 | } | ||
| 366 | } | ||
| 367 | |||
| 368 | .btn-row { | ||
| 369 | display: flex; | ||
| 370 | gap: 16rpx; | ||
| 371 | |||
| 372 | .btn { | ||
| 373 | font-size: 26rpx; | ||
| 374 | padding: 12rpx 24rpx; | ||
| 375 | border-radius: 8rpx; | ||
| 376 | } | ||
| 377 | |||
| 378 | .btn-default { | ||
| 379 | background-color: #f5f5f5; | ||
| 380 | color: #666; | ||
| 381 | } | ||
| 382 | |||
| 383 | .btn-primary { | ||
| 384 | background-color: #AD181F; | ||
| 385 | color: #fff; | ||
| 386 | } | ||
| 387 | } | ||
| 388 | } | ||
| 389 | } | ||
| 390 | } | ||
| 391 | |||
| 392 | .load-more-wrap { | ||
| 393 | padding: 20rpx 0; | ||
| 394 | text-align: center; | ||
| 395 | } | ||
| 396 | </style> |
level/ztx/memberAuditPage.vue
0 → 100644
| 1 | <template> | ||
| 2 | <view class="audit-page"> | ||
| 3 | <!-- 提示信息 --> | ||
| 4 | <!-- <view class="tips-box"> | ||
| 5 | <uni-icons type="info" size="18" color="#C4121B"></uni-icons> | ||
| 6 | <text class="tips-text" v-if="type === 'batch'">批量审核 {{ ids.split(',').length }} 条记录</text> | ||
| 7 | <text class="tips-text" v-else>单个审核</text> | ||
| 8 | </view> --> | ||
| 9 | |||
| 10 | <!-- 审核表单 --> | ||
| 11 | <view class="form-section"> | ||
| 12 | <view class="section-header"> | ||
| 13 | <uni-icons type="edit" size="18" color="#AD181F"></uni-icons> | ||
| 14 | <text class="section-title">审核信息</text> | ||
| 15 | </view> | ||
| 16 | |||
| 17 | <view class="form-card"> | ||
| 18 | <view class="form-item"> | ||
| 19 | <text class="form-label">审批结果</text> | ||
| 20 | <view class="radio-group"> | ||
| 21 | <view | ||
| 22 | class="radio-item" | ||
| 23 | :class="{ selected: form.flag === '1' }" | ||
| 24 | @click="form.flag = '1'" | ||
| 25 | > | ||
| 26 | <view class="radio-circle"> | ||
| 27 | <uni-icons v-if="form.flag === '1'" type="checkmark" size="10" color="#fff"></uni-icons> | ||
| 28 | </view> | ||
| 29 | <text>审批通过</text> | ||
| 30 | </view> | ||
| 31 | <view | ||
| 32 | class="radio-item" | ||
| 33 | :class="{ selected: form.flag === '0' }" | ||
| 34 | @click="form.flag = '0'" | ||
| 35 | > | ||
| 36 | <view class="radio-circle"> | ||
| 37 | <uni-icons v-if="form.flag === '0'" type="checkmark" size="10" color="#fff"></uni-icons> | ||
| 38 | </view> | ||
| 39 | <text>审批拒绝</text> | ||
| 40 | </view> | ||
| 41 | </view> | ||
| 42 | </view> | ||
| 43 | |||
| 44 | <view class="form-item"> | ||
| 45 | <text class="form-label">备注</text> | ||
| 46 | <textarea | ||
| 47 | v-model="form.reason" | ||
| 48 | class="textarea" | ||
| 49 | placeholder="请输入备注信息(拒绝时必填)" | ||
| 50 | :maxlength="500" | ||
| 51 | /> | ||
| 52 | </view> | ||
| 53 | </view> | ||
| 54 | </view> | ||
| 55 | |||
| 56 | <!-- 提交按钮 --> | ||
| 57 | <view class="submit-wrap"> | ||
| 58 | <button class="btn-cancel" @click="goBack">取消</button> | ||
| 59 | <button class="btn-submit" @click="doSubmit" :disabled="submitting"> | ||
| 60 | <text v-if="!submitting">确认提交</text> | ||
| 61 | <text v-else>提交中...</text> | ||
| 62 | </button> | ||
| 63 | </view> | ||
| 64 | </view> | ||
| 65 | </template> | ||
| 66 | |||
| 67 | <script setup> | ||
| 68 | import * as api from '@/common/api_exam.js' | ||
| 69 | import { ref } from 'vue' | ||
| 70 | import { onLoad } from '@dcloudio/uni-app' | ||
| 71 | |||
| 72 | const type = ref('single') // single 或 batch | ||
| 73 | const ids = ref('') | ||
| 74 | const submitting = ref(false) | ||
| 75 | |||
| 76 | const form = ref({ | ||
| 77 | flag: '1', | ||
| 78 | reason: '' | ||
| 79 | }) | ||
| 80 | |||
| 81 | onLoad((options) => { | ||
| 82 | if (options.type) { | ||
| 83 | type.value = options.type | ||
| 84 | } | ||
| 85 | if (options.ids) { | ||
| 86 | ids.value = options.ids | ||
| 87 | } | ||
| 88 | }) | ||
| 89 | |||
| 90 | function goBack() { | ||
| 91 | uni.navigateBack() | ||
| 92 | } | ||
| 93 | |||
| 94 | function doSubmit() { | ||
| 95 | if (form.value.flag === '0' && !form.value.reason) { | ||
| 96 | uni.showToast({ | ||
| 97 | title: '请输入拒绝理由', | ||
| 98 | icon: 'none' | ||
| 99 | }) | ||
| 100 | return | ||
| 101 | } | ||
| 102 | |||
| 103 | if (submitting.value) return | ||
| 104 | submitting.value = true | ||
| 105 | |||
| 106 | const params = { | ||
| 107 | ids: ids.value, | ||
| 108 | flag: form.value.flag, | ||
| 109 | reason: form.value.reason || '' | ||
| 110 | } | ||
| 111 | |||
| 112 | api.shenAudit(params).then(res => { | ||
| 113 | uni.showToast({ | ||
| 114 | title: '操作成功', | ||
| 115 | icon: 'success' | ||
| 116 | }) | ||
| 117 | setTimeout(() => { | ||
| 118 | uni.navigateBack() | ||
| 119 | }, 1500) | ||
| 120 | }).catch(err => { | ||
| 121 | console.error('审核失败', err) | ||
| 122 | uni.showToast({ | ||
| 123 | title: '操作失败', | ||
| 124 | icon: 'none' | ||
| 125 | }) | ||
| 126 | submitting.value = false | ||
| 127 | }) | ||
| 128 | } | ||
| 129 | </script> | ||
| 130 | |||
| 131 | <style lang="scss" scoped> | ||
| 132 | .audit-page { | ||
| 133 | min-height: 100vh; | ||
| 134 | background-color: #f5f5f5; | ||
| 135 | padding: 20rpx; | ||
| 136 | // padding-bottom: 120rpx; | ||
| 137 | box-sizing: border-box; | ||
| 138 | } | ||
| 139 | |||
| 140 | .tips-box { | ||
| 141 | background-color: #e8f8f7; | ||
| 142 | border-radius: 12rpx; | ||
| 143 | padding: 24rpx; | ||
| 144 | margin-bottom: 20rpx; | ||
| 145 | display: flex; | ||
| 146 | align-items: center; | ||
| 147 | gap: 12rpx; | ||
| 148 | |||
| 149 | .tips-text { | ||
| 150 | font-size: 26rpx; | ||
| 151 | color: #C4121B; | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | .form-section { | ||
| 156 | background-color: #fff; | ||
| 157 | border-radius: 16rpx; | ||
| 158 | padding: 30rpx; | ||
| 159 | margin-bottom: 20rpx; | ||
| 160 | } | ||
| 161 | |||
| 162 | .section-header { | ||
| 163 | display: flex; | ||
| 164 | align-items: center; | ||
| 165 | margin-bottom: 30rpx; | ||
| 166 | |||
| 167 | .section-title { | ||
| 168 | font-size: 30rpx; | ||
| 169 | font-weight: 600; | ||
| 170 | color: #333; | ||
| 171 | margin-left: 10rpx; | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | .form-card { | ||
| 176 | .form-item { | ||
| 177 | margin-bottom: 30rpx; | ||
| 178 | |||
| 179 | &:last-child { | ||
| 180 | margin-bottom: 0; | ||
| 181 | } | ||
| 182 | |||
| 183 | .form-label { | ||
| 184 | display: block; | ||
| 185 | font-size: 28rpx; | ||
| 186 | color: #333; | ||
| 187 | margin-bottom: 16rpx; | ||
| 188 | font-weight: 500; | ||
| 189 | } | ||
| 190 | |||
| 191 | .radio-group { | ||
| 192 | display: flex; | ||
| 193 | gap: 40rpx; | ||
| 194 | } | ||
| 195 | |||
| 196 | .radio-item { | ||
| 197 | display: flex; | ||
| 198 | align-items: center; | ||
| 199 | gap: 12rpx; | ||
| 200 | font-size: 28rpx; | ||
| 201 | color: #333; | ||
| 202 | |||
| 203 | .radio-circle { | ||
| 204 | width: 36rpx; | ||
| 205 | height: 36rpx; | ||
| 206 | border-radius: 50%; | ||
| 207 | border: 2rpx solid #ddd; | ||
| 208 | display: flex; | ||
| 209 | align-items: center; | ||
| 210 | justify-content: center; | ||
| 211 | } | ||
| 212 | |||
| 213 | &.selected { | ||
| 214 | .radio-circle { | ||
| 215 | background-color: #C4121B; | ||
| 216 | border-color: #C4121B; | ||
| 217 | } | ||
| 218 | } | ||
| 219 | } | ||
| 220 | |||
| 221 | .textarea { | ||
| 222 | width: 100%; | ||
| 223 | height: 200rpx; | ||
| 224 | border: 1rpx solid #eee; | ||
| 225 | border-radius: 12rpx; | ||
| 226 | padding: 20rpx; | ||
| 227 | font-size: 28rpx; | ||
| 228 | color: #333; | ||
| 229 | background-color: #fafafa; | ||
| 230 | box-sizing: border-box; | ||
| 231 | } | ||
| 232 | } | ||
| 233 | } | ||
| 234 | |||
| 235 | .submit-wrap { | ||
| 236 | position: fixed; | ||
| 237 | bottom: 0; | ||
| 238 | left: 0; | ||
| 239 | right: 0; | ||
| 240 | height: 110rpx; | ||
| 241 | background-color: #fff; | ||
| 242 | display: flex; | ||
| 243 | align-items: center; | ||
| 244 | justify-content: center; | ||
| 245 | gap: 30rpx; | ||
| 246 | padding: 0 30rpx; | ||
| 247 | box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.05); | ||
| 248 | |||
| 249 | button { | ||
| 250 | flex: 1; | ||
| 251 | height: 80rpx; | ||
| 252 | line-height: 80rpx; | ||
| 253 | font-size: 28rpx; | ||
| 254 | border-radius: 40rpx; | ||
| 255 | border: none; | ||
| 256 | } | ||
| 257 | |||
| 258 | .btn-cancel { | ||
| 259 | background-color: #f5f5f5; | ||
| 260 | color: #666; | ||
| 261 | } | ||
| 262 | |||
| 263 | .btn-submit { | ||
| 264 | background: #C4121B; | ||
| 265 | // background: linear-gradient(135deg, #C4121B, #15c5c1); | ||
| 266 | color: #fff; | ||
| 267 | |||
| 268 | &[disabled] { | ||
| 269 | background: #ccc; | ||
| 270 | } | ||
| 271 | } | ||
| 272 | } | ||
| 273 | </style> |
| ... | @@ -38,7 +38,7 @@ | ... | @@ -38,7 +38,7 @@ |
| 38 | "quickapp" : {}, | 38 | "quickapp" : {}, |
| 39 | /* 小程序特有相关 */ | 39 | /* 小程序特有相关 */ |
| 40 | "mp-weixin" : { | 40 | "mp-weixin" : { |
| 41 | "appid" : "wx523ee37fff4fea9d", | 41 | "appid" : "wx5d51e8ed31bbdbb7", |
| 42 | "setting" : { | 42 | "setting" : { |
| 43 | "urlCheck" : false, | 43 | "urlCheck" : false, |
| 44 | "minified" : false, | 44 | "minified" : false, | ... | ... |
| ... | @@ -738,6 +738,110 @@ | ... | @@ -738,6 +738,110 @@ |
| 738 | 738 | ||
| 739 | }, | 739 | }, |
| 740 | { | 740 | { |
| 741 | "path": "ztx/mail", | ||
| 742 | "style": { | ||
| 743 | "navigationBarTitleText": "证书邮寄", | ||
| 744 | "enablePullDownRefresh": false | ||
| 745 | } | ||
| 746 | |||
| 747 | }, | ||
| 748 | { | ||
| 749 | "path": "ztx/certDetail", | ||
| 750 | "style": { | ||
| 751 | "navigationBarTitleText": "考试详情", | ||
| 752 | "enablePullDownRefresh": false | ||
| 753 | } | ||
| 754 | |||
| 755 | }, | ||
| 756 | { | ||
| 757 | "path": "ztx/certLogistics", | ||
| 758 | "style": { | ||
| 759 | "navigationBarTitleText": "物流跟踪", | ||
| 760 | "enablePullDownRefresh": false | ||
| 761 | } | ||
| 762 | |||
| 763 | }, | ||
| 764 | { | ||
| 765 | "path": "ztx/examinationVerification", | ||
| 766 | "style": { | ||
| 767 | "navigationBarTitleText": "考点审核", | ||
| 768 | "enablePullDownRefresh": false | ||
| 769 | } | ||
| 770 | |||
| 771 | }, | ||
| 772 | { | ||
| 773 | "path": "ztx/examinationDetail", | ||
| 774 | "style": { | ||
| 775 | "navigationBarTitleText": "查看详情", | ||
| 776 | "enablePullDownRefresh": false | ||
| 777 | } | ||
| 778 | |||
| 779 | }, | ||
| 780 | { | ||
| 781 | "path": "ztx/examinationAudit", | ||
| 782 | "style": { | ||
| 783 | "navigationBarTitleText": "单位会员认证审核", | ||
| 784 | "enablePullDownRefresh": false | ||
| 785 | } | ||
| 786 | |||
| 787 | }, | ||
| 788 | { | ||
| 789 | "path": "ztx/institutionInfo", | ||
| 790 | "style": { | ||
| 791 | "navigationBarTitleText": "机构资料", | ||
| 792 | "enablePullDownRefresh": false | ||
| 793 | } | ||
| 794 | |||
| 795 | }, | ||
| 796 | { | ||
| 797 | "path": "ztx/memberAudit", | ||
| 798 | "style": { | ||
| 799 | "navigationBarTitleText": "会员审核", | ||
| 800 | "enablePullDownRefresh": false | ||
| 801 | } | ||
| 802 | |||
| 803 | }, | ||
| 804 | { | ||
| 805 | "path": "ztx/memberAuditPage", | ||
| 806 | "style": { | ||
| 807 | "navigationBarTitleText": "审核", | ||
| 808 | "enablePullDownRefresh": false | ||
| 809 | } | ||
| 810 | |||
| 811 | }, | ||
| 812 | { | ||
| 813 | "path": "ztx/costSettlement", | ||
| 814 | "style": { | ||
| 815 | "navigationBarTitleText": "费用结算", | ||
| 816 | "enablePullDownRefresh": false | ||
| 817 | } | ||
| 818 | |||
| 819 | }, | ||
| 820 | { | ||
| 821 | "path": "ztx/costSettlementDetail", | ||
| 822 | "style": { | ||
| 823 | "navigationBarTitleText": "结算详情", | ||
| 824 | "enablePullDownRefresh": false | ||
| 825 | } | ||
| 826 | |||
| 827 | }, | ||
| 828 | { | ||
| 829 | "path": "ztx/costSettlementAdd", | ||
| 830 | "style": { | ||
| 831 | "navigationBarTitleText": "新建结算申请", | ||
| 832 | "enablePullDownRefresh": false | ||
| 833 | } | ||
| 834 | |||
| 835 | }, | ||
| 836 | { | ||
| 837 | "path": "ztx/costSettlementConfirm", | ||
| 838 | "style": { | ||
| 839 | "navigationBarTitleText": "结算申请确认", | ||
| 840 | "enablePullDownRefresh": false | ||
| 841 | } | ||
| 842 | |||
| 843 | }, | ||
| 844 | { | ||
| 741 | "path": "examStudentList", | 845 | "path": "examStudentList", |
| 742 | "style": { | 846 | "style": { |
| 743 | "navigationBarTitleText": "考生信息", | 847 | "navigationBarTitleText": "考生信息", | ... | ... |
This diff is collapsed.
Click to expand it.
-
Please register or sign in to post a comment