7f5a246b by lttnew

费用结算+考点审核+证书邮寄+会员审核

1 parent f6e7f935
...@@ -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;}
......
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>
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>
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
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>
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>
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>
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>
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
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>
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": "考生信息",
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!