8cf99911 by lttnew

证书

1 parent cdac517b
1 <template>
2 <view class="cert-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.name || '-' }}</text>
13 </view>
14 <view class="info-row">
15 <text class="label">申请日期</text>
16 <text class="value">{{ formatDate(form.applyTime) }}</text>
17 </view>
18 <view class="info-row">
19 <text class="label">申请单位</text>
20 <text class="value">{{ form.memberName || '-' }}</text>
21 </view>
22 <view class="info-row">
23 <text class="label">考官</text>
24 <text class="value">{{ form.examinerNames || '-' }}</text>
25 </view>
26 <view class="info-row">
27 <text class="label">考试时间</text>
28 <text class="value">{{ form.startTime ? formatDateTime(form.startTime) : '-' }}</text>
29 </view>
30 <view class="info-row">
31 <text class="label">考级地点</text>
32 <text class="value">{{ form.address || '-' }}</text>
33 </view>
34 <view class="info-row" v-if="form.totalAmount">
35 <text class="label">总金额</text>
36 <text class="value text-red">¥{{ (form.totalAmount * 1).toFixed(2) }}</text>
37 </view>
38 </view>
39 </view>
40
41 <!-- 收货地址 -->
42 <view class="section">
43 <view class="section-header">
44 <uni-icons type="location-filled" size="18" color="#AD181F"></uni-icons>
45 <text class="section-title">收货地址</text>
46 </view>
47 <view class="info-card">
48 <view class="info-row">
49 <text class="label">姓名</text>
50 <text class="value">{{ addressForm.name || '-' }}</text>
51 </view>
52 <view class="info-row">
53 <text class="label">联系方式</text>
54 <text class="value">{{ addressForm.phone || '-' }}</text>
55 </view>
56 <view class="info-row">
57 <text class="label">收件地址</text>
58 <text class="value">{{ addressForm.address || '-' }}</text>
59 </view>
60 </view>
61 </view>
62
63 <!-- 考生信息 -->
64 <view class="section">
65 <view class="section-header">
66 <uni-icons type="person" size="18" color="#AD181F"></uni-icons>
67 <text class="section-title">考生信息</text>
68 <view class="person-summary">
69 {{ personSummary.total }}
70 </view>
71 </view>
72
73 <view class="person-stats" v-if="personSummary.levelArr && personSummary.levelArr.length > 0">
74 <view class="stat-item" v-for="item in personSummary.levelArr" :key="item.level">
75 {{ levelToChinese(item.level) }}级:{{ item.num }}
76 </view>
77 </view>
78
79 <view class="person-table">
80 <view class="table-header">
81 <view class="th th-name">姓名</view>
82 <!-- <view class="th th-idtype">证件类型</view> -->
83 <view class="th th-idcard">证件号码</view>
84 <view class="th th-level">级别</view>
85 </view>
86 <scroll-view scroll-y class="table-body-wrapper">
87 <view class="table-body">
88 <view class="table-row" v-for="(person, idx) in infoList" :key="idx">
89 <view class="td td-name">{{ person.realName }}</view>
90 <view class="td td-idtype">{{ person.idcTypeStr || '-' }}</view>
91 <view class="td td-idcard">{{ person.idcCode || '-' }}</view>
92 <view class="td td-level">
93 {{ levelToChinese(person.levelNew) }}
94 <text class="level-old" v-if="person.levelOld">({{ levelToChinese(person.levelOld) }}级)</text>
95 </view>
96 </view>
97 </view>
98 </scroll-view>
99 <view class="no-data" v-if="infoList.length == 0">
100 <text>暂无考生信息</text>
101 </view>
102 </view>
103
104 <view class="pagination-wrap" v-if="total > pageSize">
105 <view class="page-btn" @click="prevPage" :class="{ disabled: pageNum <= 1 }">
106 <uni-icons type="left" size="14" color="#666"></uni-icons>
107 </view>
108 <view class="page-num">{{ pageNum }}/{{ totalPage }}</view>
109 <view class="page-btn" @click="nextPage" :class="{ disabled: pageNum >= totalPage }">
110 <uni-icons type="right" size="14" color="#666"></uni-icons>
111 </view>
112 </view>
113 </view>
114
115 <!-- 审核信息 -->
116 <view class="section" v-if="recordList.length > 0">
117 <view class="section-header">
118 <uni-icons type="checkmark-circle" size="18" color="#AD181F"></uni-icons>
119 <text class="section-title">审核信息</text>
120 </view>
121 <view class="audit-table">
122 <view class="table-header">
123 <view class="th th-dept">审核协会</view>
124 <view class="th th-time">审核时间</view>
125 <view class="th th-status">审核状态</view>
126 <view class="th th-remark">备注</view>
127 </view>
128 <view class="table-body">
129 <view class="table-row" v-for="(record, idx) in recordList" :key="idx">
130 <view class="td td-dept">{{ record.auditDeptName || '-' }}</view>
131 <view class="td td-time">{{ formatDateTime(record.auditTime) }}</view>
132 <view class="td td-status">
133 <text :class="record.auditResult == '1' ? 'text-success' : 'text-danger'">
134 {{ record.auditResult == '1' ? '通过' : '未通过' }}
135 </text>
136 </view>
137 <view class="td td-remark">{{ record.auditMsg || '-' }}</view>
138 </view>
139 </view>
140 </view>
141 </view>
142 </view>
143 </template>
144
145 <script setup>
146 import * as api from '@/common/api.js'
147 import { ref, computed } from 'vue'
148 import { onLoad } from '@dcloudio/uni-app'
149
150 const loading = ref(false)
151 const examId = ref('')
152 const pageNum = ref(1)
153 const pageSize = ref(50)
154
155 const form = ref({})
156 const addressForm = ref({})
157 const infoList = ref([])
158 const personSummary = ref({ total: 0, levelArr: [] })
159 const total = ref(0)
160 const totalPage = computed(() => Math.ceil(total.value / pageSize.value))
161 const recordList = ref([])
162
163 onLoad((options) => {
164 if (options.examId) {
165 examId.value = options.examId
166 getExamInfo()
167 getStudentList()
168 getAuditRecords()
169 }
170 })
171
172 function getExamInfo() {
173 uni.showLoading({ title: '加载中' })
174 api.getExamInfo(examId.value).then(res => {
175 uni.hideLoading()
176 if (res.data) {
177 form.value = res.data
178 addressForm.value = res.data.postAddress || {}
179 }
180 }).catch(err => {
181 uni.hideLoading()
182 console.error('获取考试详情失败', err)
183 uni.showToast({ title: '获取详情失败', icon: 'none' })
184 })
185 }
186
187 function getStudentList() {
188 uni.showLoading({ title: '加载中' })
189 api.getStudentList({
190 examId: examId.value,
191 pageNum: pageNum.value,
192 pageSize: pageSize.value
193 }).then(res => {
194 uni.hideLoading()
195 if (res.rows) {
196 infoList.value = res.rows
197 total.value = res.total || 0
198
199 // 统计各级别人数
200 const levelMap = {}
201 res.rows.forEach(person => {
202 const level = person.levelNew
203 if (level) {
204 levelMap[level] = (levelMap[level] || 0) + 1
205 }
206 })
207
208 const levelArr = Object.keys(levelMap).map(key => ({
209 level: key,
210 num: levelMap[key]
211 })).sort((a, b) => b.level - a.level)
212
213 personSummary.value = {
214 total: total.value,
215 levelArr: levelArr
216 }
217 } else {
218 uni.hideLoading()
219 }
220 }).catch(err => {
221 uni.hideLoading()
222 console.error('获取考生列表失败', err)
223 })
224 }
225
226 function prevPage() {
227 if (pageNum.value > 1) {
228 pageNum.value--
229 getStudentList()
230 }
231 }
232
233 function nextPage() {
234 if (pageNum.value < totalPage.value) {
235 pageNum.value++
236 getStudentList()
237 }
238 }
239
240 function getAuditRecords() {
241 api.getLogs(examId.value, 1).then(res => {
242 recordList.value = res.data || []
243 }).catch(err => {
244 console.error('获取审核记录失败', err)
245 })
246 }
247
248 function formatDate(dateStr) {
249 if (!dateStr) return '-'
250 return dateStr.substring(0, 10)
251 }
252
253 function formatDateTime(dateStr) {
254 if (!dateStr) return '-'
255 return dateStr.replace('T', ' ').substring(0, 19)
256 }
257
258 function levelToChinese(level) {
259 if (!level) return '-'
260 const levelMap = {
261 '1': '一', '2': '二', '3': '三', '4': '四', '5': '五',
262 '6': '六', '7': '七', '8': '八', '9': '九', '10': '十'
263 }
264 return levelMap[String(level)] || level
265 }
266 </script>
267
268 <style lang="scss" scoped>
269 .cert-detail-page {
270 min-height: 100vh;
271 background-color: #f5f5f5;
272 padding: 20rpx;
273 padding-bottom: 40rpx;
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 .person-summary {
296 margin-left: auto;
297 font-size: 26rpx;
298 color: #AD181F;
299 }
300 }
301
302 .info-card {
303 .info-row {
304 display: flex;
305 justify-content: space-between;
306 padding: 16rpx 0;
307 border-bottom: 1px solid #f0f0f0;
308
309 &:last-child {
310 border-bottom: none;
311 }
312
313 .label {
314 font-size: 26rpx;
315 color: #999;
316 flex-shrink: 0;
317 }
318
319 .value {
320 font-size: 26rpx;
321 color: #333;
322 text-align: right;
323 margin-left: 20rpx;
324
325 &.text-red {
326 color: #AD181F;
327 font-weight: 600;
328 }
329 }
330 }
331 }
332
333 .person-stats {
334 display: flex;
335 flex-wrap: wrap;
336 gap: 16rpx;
337 margin-bottom: 24rpx;
338 padding: 20rpx;
339 background-color: #fafafa;
340 border-radius: 12rpx;
341
342 .stat-item {
343 font-size: 24rpx;
344 color: #666;
345 padding: 8rpx 16rpx;
346 background-color: #fff;
347 border-radius: 20rpx;
348 }
349 }
350
351 .person-table {
352 border: 1px solid #eee;
353 border-radius: 12rpx;
354 overflow: hidden;
355 }
356
357 .table-header {
358 display: flex;
359 background-color: #f5f5f5;
360
361 .th {
362 padding: 20rpx 0;
363 text-align: center;
364 font-size: 24rpx;
365 color: #666;
366 font-weight: 500;
367 }
368 }
369
370 .table-body-wrapper {
371 max-height: 600rpx;
372 }
373
374 .table-body {
375 .table-row {
376 display: flex;
377 border-bottom: 1px solid #eee;
378
379 &:last-child {
380 border-bottom: none;
381 }
382
383 .td {
384 padding: 20rpx 0;
385 text-align: center;
386 font-size: 24rpx;
387 color: #333;
388 overflow: hidden;
389 text-overflow: ellipsis;
390 white-space: nowrap;
391 }
392 }
393 }
394
395 .th-name, .td-name { width: 20%; }
396 // .th-idtype, .td-idtype { width: 18%; }
397 .th-idcard, .td-idcard { width: 60%; }
398 .th-level, .td-level { width: 20%; }
399
400 .level-old {
401 color: #999;
402 font-size: 20rpx;
403 margin-left: 4rpx;
404 }
405
406 .no-data {
407 padding: 60rpx 0;
408 text-align: center;
409 color: #999;
410 font-size: 26rpx;
411 }
412
413 .pagination-wrap {
414 display: flex;
415 justify-content: center;
416 align-items: center;
417 gap: 30rpx;
418 margin-top: 30rpx;
419 padding-top: 30rpx;
420 border-top: 1px solid #f0f0f0;
421
422 .page-btn {
423 width: 60rpx;
424 height: 60rpx;
425 border-radius: 50%;
426 background-color: #f5f5f5;
427 display: flex;
428 align-items: center;
429 justify-content: center;
430
431 &.disabled {
432 opacity: 0.4;
433 }
434 }
435
436 .page-num {
437 font-size: 28rpx;
438 color: #333;
439 min-width: 120rpx;
440 text-align: center;
441 }
442 }
443
444 /* 审核信息表格 */
445 .audit-table {
446 border: 1px solid #eee;
447 border-radius: 12rpx;
448 overflow: hidden;
449
450 .table-header {
451 display: flex;
452 background-color: #f5f5f5;
453
454 .th {
455 padding: 20rpx 0;
456 text-align: center;
457 font-size: 24rpx;
458 color: #666;
459 font-weight: 500;
460 }
461 }
462
463 .table-body {
464 .table-row {
465 display: flex;
466 border-bottom: 1px solid #eee;
467
468 &:last-child {
469 border-bottom: none;
470 }
471
472 .td {
473 padding: 16rpx 0;
474 text-align: center;
475 font-size: 22rpx;
476 color: #333;
477 overflow: hidden;
478 text-overflow: ellipsis;
479 white-space: nowrap;
480 }
481 }
482 }
483
484 .th-dept, .td-dept { width: 25%; }
485 .th-time, .td-time { width: 25%; }
486 .th-status, .td-status { width: 15%; }
487 .th-remark, .td-remark { width: 35%; }
488
489 .text-success {
490 color: #4caf50;
491 }
492
493 .text-danger {
494 color: #f56c6c;
495 }
496 }
497 </style>
1 <template> 1 <template>
2 <view class="logistics-page"> 2 <view class="logistics-page">
3 <!-- 物流信息卡片 -->
4 <view class="logistics-info-card"> 3 <view class="logistics-info-card">
5 <view class="info-header"> 4 <view class="info-header">
6 <uni-icons type=" truck" size="20" color="#AD181F"></uni-icons> 5 <uni-icons type="paperplane-filled" size="18" color="#AD181F"></uni-icons>
7 <text class="header-title">物流信息</text> 6 <text class="header-title">物流信息</text>
8 </view> 7 </view>
9 <view class="info-content"> 8 <view class="info-content">
10 <view class="info-row"> 9 <view class="info-row">
11 <text class="label">运单号</text> 10 <text class="label">运单号</text>
12 <text class="value tracking-number" @click="copyTracking">{{ currentItem.postCode || '-' }} 11 <text class="value tracking-number" @click="copyTracking">
13 <text class="copy-btn">复制</text> 12 {{ currentItem.postCode || '-' }}
14 </text> 13 </text>
15 </view> 14 </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> 15 </view>
26 </view> 16 </view>
27 17
28 <!-- 物流时间线 -->
29 <view class="timeline-section"> 18 <view class="timeline-section">
30 <view class="section-header"> 19 <view class="section-header">
31 <uni-icons type="location-filled" size="18" color="#AD181F"></uni-icons> 20 <uni-icons type="location-filled" size="20" color="#AD181F"></uni-icons>
32 <text class="section-title">运输轨迹</text> 21 <text class="section-title">运输轨迹</text>
33 </view> 22 </view>
34 23
...@@ -39,28 +28,28 @@ ...@@ -39,28 +28,28 @@
39 <view class="timeline-wrap" v-else> 28 <view class="timeline-wrap" v-else>
40 <view class="timeline-list" v-if="trackingNodes.length > 0"> 29 <view class="timeline-list" v-if="trackingNodes.length > 0">
41 <view 30 <view
42 class="timeline-item"
43 :class="{ first: idx === 0 }"
44 v-for="(node, idx) in trackingNodes" 31 v-for="(node, idx) in trackingNodes"
45 :key="idx" 32 :key="idx"
33 class="timeline-item"
34 :class="{ first: idx === 0 }"
46 > 35 >
47 <view class="timeline-left"> 36 <view class="timeline-left">
48 <view class="timeline-dot"> 37 <view class="timeline-dot">
49 <uni-icons v-if="idx === 0" type="check" size="12" color="#fff"></uni-icons> 38 <text v-if="idx === 0" class="timeline-check"></text>
50 </view> 39 </view>
51 <view class="timeline-line" v-if="idx < trackingNodes.length - 1"></view> 40 <view v-if="idx < trackingNodes.length - 1" class="timeline-line"></view>
52 </view> 41 </view>
53 <view class="timeline-right"> 42 <view class="timeline-right">
54 <view class="timeline-content"> 43 <view class="timeline-content">
55 <view class="timeline-title">{{ node.categoryName }}</view> 44 <view class="timeline-title">{{ node.categoryName || '物流更新' }}</view>
56 <view class="timeline-time">{{ node.operationTime }}</view> 45 <view class="timeline-time">{{ node.operationTime || '-' }}</view>
57 <view class="timeline-desc">{{ node.operationRemark }}</view> 46 <view class="timeline-desc">{{ node.operationRemark || '-' }}</view>
58 </view> 47 </view>
59 </view> 48 </view>
60 </view> 49 </view>
61 </view> 50 </view>
62 51
63 <view class="no-logistics" v-else> 52 <view class="nodata" v-else>
64 <image mode="aspectFit" :src="config.baseUrl_api + '/fs/static/nodata.png'"></image> 53 <image mode="aspectFit" :src="config.baseUrl_api + '/fs/static/nodata.png'"></image>
65 <text>暂无物流信息</text> 54 <text>暂无物流信息</text>
66 </view> 55 </view>
...@@ -81,26 +70,25 @@ const currentItem = ref({}) ...@@ -81,26 +70,25 @@ const currentItem = ref({})
81 const trackingNodes = ref([]) 70 const trackingNodes = ref([])
82 71
83 onLoad((options) => { 72 onLoad((options) => {
84 if (options.payId) { 73 if (!options.payId) return
85 payId.value = options.payId 74 payId.value = options.payId
86 if (options.postCode) currentItem.value.postCode = options.postCode 75 if (options.postCode) currentItem.value.postCode = options.postCode
87 if (options.postStatus) currentItem.value.postStatus = parseInt(options.postStatus) 76 if (options.postStatus) currentItem.value.postStatus = parseInt(options.postStatus)
88 if (options.submitTime) currentItem.value.submitTime = options.submitTime 77 if (options.submitTime) currentItem.value.submitTime = options.submitTime
89 getLogisticsInfo() 78 getLogisticsInfo()
90 }
91 }) 79 })
92 80
93 function getLogisticsInfo() { 81 function getLogisticsInfo() {
94 if (!payId.value) return 82 if (!payId.value) return
95 83
96 loading.value = true 84 loading.value = true
97 api.queryTrace(payId.value).then(res => { 85 api.queryTrace(payId.value).then((res) => {
98 loading.value = false
99 trackingNodes.value = res.data || [] 86 trackingNodes.value = res.data || []
100 }).catch(err => { 87 }).catch((err) => {
101 loading.value = false
102 console.error('获取物流信息失败', err) 88 console.error('获取物流信息失败', err)
103 uni.showToast({ title: '获取物流信息失败', icon: 'none' }) 89 uni.showToast({ title: '获取物流信息失败', icon: 'none' })
90 }).finally(() => {
91 loading.value = false
104 }) 92 })
105 } 93 }
106 94
...@@ -113,11 +101,6 @@ function copyTracking() { ...@@ -113,11 +101,6 @@ function copyTracking() {
113 } 101 }
114 }) 102 })
115 } 103 }
116
117 function formatDateTime(dateStr) {
118 if (!dateStr) return '-'
119 return dateStr.replace('T', ' ').substring(0, 19)
120 }
121 </script> 104 </script>
122 105
123 <style lang="scss" scoped> 106 <style lang="scss" scoped>
...@@ -128,7 +111,6 @@ function formatDateTime(dateStr) { ...@@ -128,7 +111,6 @@ function formatDateTime(dateStr) {
128 padding-bottom: 40rpx; 111 padding-bottom: 40rpx;
129 } 112 }
130 113
131 /* 物流信息卡片 */
132 .logistics-info-card { 114 .logistics-info-card {
133 background-color: #fff; 115 background-color: #fff;
134 border-radius: 16rpx; 116 border-radius: 16rpx;
...@@ -155,11 +137,6 @@ function formatDateTime(dateStr) { ...@@ -155,11 +137,6 @@ function formatDateTime(dateStr) {
155 justify-content: space-between; 137 justify-content: space-between;
156 align-items: center; 138 align-items: center;
157 padding: 16rpx 0; 139 padding: 16rpx 0;
158 border-bottom: 1px solid #f0f0f0;
159
160 &:last-child {
161 border-bottom: none;
162 }
163 140
164 .label { 141 .label {
165 font-size: 26rpx; 142 font-size: 26rpx;
...@@ -170,32 +147,15 @@ function formatDateTime(dateStr) { ...@@ -170,32 +147,15 @@ function formatDateTime(dateStr) {
170 font-size: 26rpx; 147 font-size: 26rpx;
171 color: #333; 148 color: #333;
172 149
173 &.status-sended {
174 color: #4caf50;
175 }
176
177 &.status-pending {
178 color: #ff9800;
179 }
180
181 &.tracking-number { 150 &.tracking-number {
182 display: flex; 151 max-width: 460rpx;
183 align-items: center; 152 text-align: right;
184 gap: 10rpx; 153 word-break: break-all;
185 } 154 }
186 } 155 }
187
188 .copy-btn {
189 font-size: 22rpx;
190 color: #AD181F;
191 background-color: #fef0f0;
192 padding: 4rpx 12rpx;
193 border-radius: 16rpx;
194 }
195 } 156 }
196 } 157 }
197 158
198 /* 时间线 */
199 .timeline-section { 159 .timeline-section {
200 background-color: #fff; 160 background-color: #fff;
201 border-radius: 16rpx; 161 border-radius: 16rpx;
...@@ -207,6 +167,36 @@ function formatDateTime(dateStr) { ...@@ -207,6 +167,36 @@ function formatDateTime(dateStr) {
207 align-items: center; 167 align-items: center;
208 margin-bottom: 30rpx; 168 margin-bottom: 30rpx;
209 169
170 .section-icon {
171 position: relative;
172 width: 22rpx;
173 height: 22rpx;
174 margin-right: 10rpx;
175 flex-shrink: 0;
176
177 .section-icon-ring {
178 width: 100%;
179 height: 100%;
180 border: 2rpx solid #c4121b;
181 border-radius: 50%;
182 box-sizing: border-box;
183 background: #fff;
184 }
185
186 .section-icon-dot {
187 position: absolute;
188 left: 50%;
189 top: 50%;
190 width: 8rpx;
191 height: 8rpx;
192 margin-left: -4rpx;
193 margin-top: -4rpx;
194 border-radius: 50%;
195 background: #c4121b;
196 box-shadow: 0 0 0 4rpx rgba(196, 18, 27, 0.08);
197 }
198 }
199
210 .section-title { 200 .section-title {
211 font-size: 30rpx; 201 font-size: 30rpx;
212 font-weight: 600; 202 font-weight: 600;
...@@ -249,8 +239,8 @@ function formatDateTime(dateStr) { ...@@ -249,8 +239,8 @@ function formatDateTime(dateStr) {
249 } 239 }
250 240
251 .timeline-dot { 241 .timeline-dot {
252 width: 28rpx; 242 width: 32rpx;
253 height: 28rpx; 243 height: 32rpx;
254 border-radius: 50%; 244 border-radius: 50%;
255 border: 2px solid #ccc; 245 border: 2px solid #ccc;
256 background-color: #fff; 246 background-color: #fff;
...@@ -261,12 +251,19 @@ function formatDateTime(dateStr) { ...@@ -261,12 +251,19 @@ function formatDateTime(dateStr) {
261 z-index: 1; 251 z-index: 1;
262 } 252 }
263 253
254 .timeline-check {
255 color: #fff;
256 font-size: 20rpx;
257 font-weight: 700;
258 line-height: 1;
259 }
260
264 .timeline-line { 261 .timeline-line {
265 width: 2rpx; 262 width: 2rpx;
266 flex: 1; 263 flex: 1;
267 background-color: #e0e0e0; 264 background-color: #e0e0e0;
268 margin: 8rpx 0; 265 margin: 10rpx 0;
269 min-height: 60rpx; 266 min-height: 64rpx;
270 } 267 }
271 268
272 .timeline-right { 269 .timeline-right {
...@@ -297,24 +294,24 @@ function formatDateTime(dateStr) { ...@@ -297,24 +294,24 @@ function formatDateTime(dateStr) {
297 border-radius: 8rpx; 294 border-radius: 8rpx;
298 } 295 }
299 } 296 }
297 }
300 298
301 .no-logistics { 299 .nodata {
302 display: flex; 300 display: flex;
303 flex-direction: column; 301 flex-direction: column;
304 align-items: center; 302 align-items: center;
305 justify-content: center; 303 justify-content: center;
306 padding: 80rpx 0; 304 padding: 80rpx 0;
307 305
308 image { 306 image {
309 width: 200rpx; 307 width: 200rpx;
310 height: 200rpx; 308 height: 200rpx;
311 } 309 }
312 310
313 text { 311 text {
314 font-size: 28rpx; 312 font-size: 28rpx;
315 color: #999; 313 color: #999;
316 margin-top: 20rpx; 314 margin-top: 20rpx;
317 }
318 } 315 }
319 } 316 }
320 </style> 317 </style>
......
1 <template> 1 <template>
2 <view class="cert-mail-page"> 2 <view class="mail-page" :class="{ 'no-scroll': showMailPopup }">
3 <!-- 列表区域 --> 3 <scroll-view
4 <view class="appList"> 4 scroll-y
5 <view class="appItem" v-for="(item, index) in infoList" :key="index"> 5 class="mail-list-scroll"
6 <view @click="handleView(item)"> 6 :enhanced="true"
7 <view class="status"> 7 :show-scrollbar="false"
8 <text :class="item.postStatus == 1 ? 'text-success' : 'text-warning'"> 8 :scroll-enabled="!showMailPopup"
9 {{ item.postStatus == 1 ? '已邮寄' : '未邮寄' }} 9 lower-threshold="200"
10 </text> 10 @scrolltolower="loadMore"
11 </view> 11 >
12 <view class="date" v-if="item.submitTime"> 12 <view class="mail-list">
13 <view class="text-primary" v-if="item.payCode">{{ item.payCode }}</view> 13 <view v-if="infoList.length > 0">
14 </view> 14 <view
15 15 v-for="(item, index) in infoList"
16 <view class="name mt0">{{ item.name }}</view> 16 :key="item.payId || index"
17 <view class="flexbox"> 17 class="order-card-new"
18 <view> 18 @click="handleView(item)"
19 缴费单位 19 >
20 <view>{{ item.memberName }}</view> 20 <view class="card-header">
21 <view class="date">
22 <view class="data-header">
23 <text class="value">{{ item.payCode || '—' }} ·{{ item.memberName || '—' }}</text>
24 </view>
25 <text
26 class="status-tag"
27 :class="item.postStatus == 1 ? 'status-success' : 'status-pending'"
28 >
29 {{ item.postStatus == 1 ? '已邮寄' : '未邮寄' }}
30 </text>
31 </view>
21 </view> 32 </view>
22 <view> 33
23 证书人数 34 <view class="member-time">
24 <view>{{ item.totalNum }}</view> 35 <view class="label">
36 {{ item.name || '—' }}
37 </view>
38 <view >{{ item.totalNum || 0 }}</view>
25 </view> 39 </view>
26 </view> 40
27 <view class="flex f-j-s"> 41 <view class="info-summary">
28 <view class="mail-time" v-if="item.submitTime"> 42 <view class="summary-right">
29 邮寄时间:{{ formatDate(item.submitTime) }} 43 </view>
30 </view> 44 </view>
31 <view class="mail-time" v-if="item.postCode "> 45
32 <view>物流编号{{ item.postCode || '-' }}</view> 46 <view class="detail-rows">
47 <view class="detail-col">
48 <text class="detail-label">邮寄时间</text>
49 <text class="detail-value">{{ item.submitTime ? formatDate(item.submitTime) : '—' }}</text>
50 </view>
51 <view class="detail-divider"></view>
52 <view class="detail-col">
53 <text class="detail-label">物流编号</text>
54 <text class="detail-value">{{ item.postCode || '—' }}</text>
55 </view>
56 </view>
57
58 <view class="btn-group">
59 <button
60 v-if="showMailButton(item)"
61 class="btn btn-mail"
62 @click.stop="openMailPopup(item)"
63 >
64 邮寄证书
65 </button>
66 <button class="btn btn-logistics" @click.stop="handleLogistics(item)">
67 物流跟踪
68 </button>
33 </view> 69 </view>
34 </view> 70 </view>
35 </view> 71 </view>
36 <view class="func"> 72
37 <button 73 <view v-else-if="!loading" class="empty">
38 v-if="deptType == '1' && item.postStatus != 1" 74 <image
39 class="btn-mail" 75 class="empty-img"
40 @click.stop="handleMail(item)" 76 mode="aspectFit"
41 >邮寄证书</button> 77 :src="config.baseUrl_api + '/fs/static/nodata.png'"
42 <button class="btn-logistics" @click.stop="handleLogistics(item)">物流跟踪</button> 78 ></image>
79 <text class="empty-text">暂无数据</text>
80 </view>
81
82 <view class="loading-tip" v-if="loading">加载中...</view>
83 <view class="no-more" v-if="!loading && loadStatus === 'nomore' && infoList.length">
84 没有更多了
43 </view> 85 </view>
44 </view> 86 </view>
45 </view> 87 </scroll-view>
88
89 <view v-if="showMailPopup" class="popup-mask" @touchmove.stop.prevent>
90 <view class="custom-modal" @click.stop>
91 <view class="modal-title">邮寄证书</view>
92 <view class="mail-form">
93 <view class="form-item">
94 <text class="form-label">邮寄方式</text>
95 <radio-group class="radio-group" @change="handleMailTypeChange">
96 <label class="radio-item" @click.stop>
97 <radio value="1" color="#C4121B" :checked="mailForm.type === '1'" />
98 <text>自动邮寄</text>
99 </label>
100 <label class="radio-item" @click.stop>
101 <radio value="2" color="#C4121B" :checked="mailForm.type === '2'" />
102 <text>人工邮寄</text>
103 </label>
104 </radio-group>
105 </view>
46 106
47 <!-- 空数据 --> 107 <view v-if="mailForm.type === '2'" class="form-item">
48 <view class="nodata" v-if="infoList.length == 0 && !loading"> 108 <text class="form-label">快递公司</text>
49 <image mode="aspectFit" :src="config.baseUrl_api + '/fs/static/nodata.png'"></image> 109 <input
50 <text>暂无数据</text> 110 v-model.trim="mailForm.tt"
51 </view> 111 class="form-input"
112 placeholder="请输入快递公司"
113 maxlength="30"
114 />
115 </view>
116
117 <view v-if="mailForm.type === '2'" class="form-item">
118 <text class="form-label">快递号</text>
119 <input
120 v-model.trim="mailForm.code"
121 class="form-input"
122 placeholder="请输入快递号"
123 maxlength="40"
124 />
125 </view>
126 </view>
52 127
53 <!-- 上拉加载 --> 128 <view class="modal-btns">
54 <view class="loading"> 129 <button class="modal-btn-cancel" @click="closeMailPopup">取消</button>
55 <uni-load-more :status="loadStatus" :contentText="loadMoreText"></uni-load-more> 130 <button class="modal-btn-confirm" @click="submitMail">确定</button>
131 </view>
132 </view>
56 </view> 133 </view>
57 </view> 134 </view>
58 </template> 135 </template>
...@@ -60,31 +137,31 @@ ...@@ -60,31 +137,31 @@
60 <script setup> 137 <script setup>
61 import * as api from '@/common/api.js' 138 import * as api from '@/common/api.js'
62 import config from '@/config.js' 139 import config from '@/config.js'
63 import { ref, computed } from 'vue' 140 import { ref } from 'vue'
64 import { onLoad, onShow, onReachBottom } from '@dcloudio/uni-app' 141 import { onLoad, onShow, onReachBottom } from '@dcloudio/uni-app'
65 142
66 const app = getApp() 143 const app = getApp()
67 const loading = ref(false)
68 144
69 // 加载状态 145 const loading = ref(false)
70 const loadStatus = ref('more') // more / loading / nomore 146 const infoList = ref([])
71 const loadMoreText = { 147 const total = ref(0)
72 contentdown: '上拉加载更多', 148 const deptType = ref('')
73 contentrefresh: '正在加载...', 149 const loadStatus = ref('more')
74 contentnomore: '没有更多了' 150 const showMailPopup = ref(false)
75 } 151 const currentRow = ref(null)
76 152
77 // 请求参数
78 const queryParams = ref({ 153 const queryParams = ref({
79 pageNum: 1, 154 pageNum: 1,
80 pageSize: 10, 155 pageSize: 10,
81 type: '1' 156 type: '1'
82 }) 157 })
83 158
84 // 列表数据 159 const mailForm = ref({
85 const infoList = ref([]) 160 payId: '',
86 const total = ref(0) 161 type: '1',
87 const deptType = ref('') 162 tt: '',
163 code: ''
164 })
88 165
89 onLoad((options) => { 166 onLoad((options) => {
90 if (options.type) { 167 if (options.type) {
...@@ -102,88 +179,122 @@ onShow(() => { ...@@ -102,88 +179,122 @@ onShow(() => {
102 } 179 }
103 }) 180 })
104 181
105 // 初始化(刷新) 182 onReachBottom(() => {
183 if (loading.value || loadStatus.value !== 'more' || showMailPopup.value) return
184 queryParams.value.pageNum++
185 getList()
186 })
187
106 function init() { 188 function init() {
107 deptType.value = app.globalData.deptType 189 deptType.value = String(app.globalData.deptType || '')
108 // 重置列表和页码
109 infoList.value = [] 190 infoList.value = []
191 total.value = 0
110 queryParams.value.pageNum = 1 192 queryParams.value.pageNum = 1
111 loadStatus.value = 'more' 193 loadStatus.value = 'more'
112 getList() 194 getList()
113 } 195 }
114 196
115 // 获取列表
116 function getList() { 197 function getList() {
117 // 没有更多数据直接返回 198 if (loadStatus.value === 'nomore' || loading.value) return
118 if (loadStatus.value === 'nomore') return 199
119
120 loading.value = true 200 loading.value = true
121 loadStatus.value = 'loading' 201 if (queryParams.value.pageNum === 1) {
122 uni.showLoading({ title: '加载中' }) 202 uni.showLoading({ title: '加载中' })
123 203 }
124 api.paymentList({ ...queryParams.value }).then(res => { 204
125 const data = res.rows || [] 205 api.paymentList({ ...queryParams.value }).then((res) => {
126 const totalData = res.total || 0 206 const rows = res.rows || []
127 207 total.value = res.total || 0
128 // 拼接数据 208
129 infoList.value = [...infoList.value, ...data] 209 if (queryParams.value.pageNum === 1) {
130 total.value = totalData 210 infoList.value = rows
131
132 // 判断是否还有更多
133 if (infoList.value.length >= totalData) {
134 loadStatus.value = 'nomore'
135 } else { 211 } else {
136 loadStatus.value = 'more' 212 infoList.value = infoList.value.concat(rows)
137 } 213 }
138 214
139 loading.value = false 215 loadStatus.value = infoList.value.length >= total.value ? 'nomore' : 'more'
140 uni.hideLoading() 216 }).catch((err) => {
141 }).catch(() => { 217 if (queryParams.value.pageNum > 1) {
218 queryParams.value.pageNum--
219 }
220 loadStatus.value = 'more'
221 console.error('获取邮寄列表失败', err)
222 uni.showToast({ title: '加载失败', icon: 'none' })
223 }).finally(() => {
142 loading.value = false 224 loading.value = false
143 uni.hideLoading() 225 uni.hideLoading()
144 loadStatus.value = 'more'
145 }) 226 })
146 } 227 }
147 228
148 // 上拉加载下一页 229 function loadMore() {
149 onReachBottom(() => { 230 if (loading.value || loadStatus.value !== 'more' || showMailPopup.value) return
150 if (loadStatus.value !== 'more' || loading.value) return
151 queryParams.value.pageNum++ 231 queryParams.value.pageNum++
152 getList() 232 getList()
153 }) 233 }
154 234
155 // 查看详情
156 function handleView(item) { 235 function handleView(item) {
157 uni.navigateTo({ 236 uni.navigateTo({
158 url: `/level/ztx/certDetail?examId=${item.examId}` 237 url: `/pages/rank/applyDetail?examId=${item.examId}&type=${queryParams.value.type}`
159 }) 238 })
160 } 239 }
161 240
162 // 邮寄证书 241 function showMailButton(item) {
163 async function handleMail(item) { 242 return deptType.value === '1' && String(item.postStatus) !== '1'
164 const res = await uni.showModal({ 243 }
165 title: '提示',
166 content: '是否确认寄送快递?',
167 confirmText: '确认',
168 cancelText: '取消'
169 })
170 244
171 if (res.confirm) { 245 function openMailPopup(item) {
172 uni.showLoading({ title: '操作中' }) 246 currentRow.value = item
173 api.postCert(item.payId).then(() => { 247 mailForm.value = {
174 uni.hideLoading() 248 payId: item.payId,
175 uni.showToast({ title: '操作成功', icon: 'success' }) 249 type: '1',
176 // 操作成功后刷新列表 250 tt: '',
177 init() 251 code: ''
178 }).catch(() => { 252 }
179 uni.hideLoading() 253 showMailPopup.value = true
180 }) 254 }
255
256 function closeMailPopup() {
257 showMailPopup.value = false
258 currentRow.value = null
259 }
260
261 function handleMailTypeChange(e) {
262 mailForm.value.type = e.detail.value
263 if (mailForm.value.type === '1') {
264 mailForm.value.tt = ''
265 mailForm.value.code = ''
266 }
267 }
268
269 async function submitMail() {
270 if (!mailForm.value.payId) return
271
272 if (mailForm.value.type === '2') {
273 if (!mailForm.value.tt) {
274 uni.showToast({ title: '请输入快递公司', icon: 'none' })
275 return
276 }
277 if (!mailForm.value.code) {
278 uni.showToast({ title: '请输入快递号', icon: 'none' })
279 return
280 }
281 }
282
283 try {
284 uni.showLoading({ title: '提交中' })
285 await api.postCert(mailForm.value.payId)
286 uni.showToast({ title: '操作成功', icon: 'success' })
287 closeMailPopup()
288 init()
289 } catch (err) {
290 console.error('邮寄证书失败', err)
291 } finally {
292 uni.hideLoading()
181 } 293 }
182 } 294 }
183 295
184 // 物流跟踪
185 function handleLogistics(item) { 296 function handleLogistics(item) {
186 if (item.postStatus != 1 || !item.postCode) { 297 if (String(item.postStatus) !== '1' || !item.postCode) {
187 uni.showToast({ title: '暂无物流信息', icon: 'none' }) 298 uni.showToast({ title: '暂无物流信息', icon: 'none' })
188 return 299 return
189 } 300 }
...@@ -192,159 +303,395 @@ function handleLogistics(item) { ...@@ -192,159 +303,395 @@ function handleLogistics(item) {
192 }) 303 })
193 } 304 }
194 305
195 // 时间格式化
196 function formatDate(dateStr) { 306 function formatDate(dateStr) {
197 if (!dateStr) return '-' 307 if (!dateStr) return '—'
198 return dateStr.substring(0, 10) 308 return String(dateStr).replace('T', ' ').substring(0, 10)
199 }
200
201 // 等级转中文
202 function levelToChinese(level) {
203 const levelMap = {
204 '1': '一', '2': '二', '3': '三', '4': '四', '5': '五',
205 '6': '六', '7': '七', '8': '八', '9': '九', '10': '十'
206 }
207 return levelMap[String(level)] || level
208 } 309 }
209 </script> 310 </script>
210 311
211 <style lang="scss" scoped> 312 <style lang="scss" scoped>
212 .cert-mail-page { 313 .mail-page {
314 background: #ededf0;
315 height: 100vh;
213 min-height: 100vh; 316 min-height: 100vh;
214 background-color: #f5f5f5; 317 display: flex;
215 padding-bottom: 20rpx; 318 flex-direction: column;
216 } 319 overflow: hidden;
217 320
218 /* 列表区域 */ 321 &.no-scroll {
219 .appList { 322 overflow: hidden;
220 padding: 0 20rpx; 323 height: 100vh;
324 }
221 } 325 }
222 326
223 .appItem { 327 .mail-list-scroll {
224 background-color: #fff; 328 flex: 1;
225 border-radius: 16rpx; 329 height: 0;
226 padding: 30rpx; 330 min-height: 0;
227 margin-bottom: 20rpx; 331 overflow: hidden;
228 box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05); 332 background: #ededf0;
229 333 }
230 .status {
231 display: inline-block;
232 padding: 6rpx 20rpx;
233 border-radius: 20rpx;
234 font-size: 24rpx;
235 margin-bottom: 16rpx;
236 334
237 .text-success { 335 .mail-list {
238 color: #4caf50; 336 min-height: 100%;
239 } 337 box-sizing: border-box;
338 padding: 18rpx 22rpx 30rpx;
339 }
240 340
241 .text-warning { 341 .empty {
242 color: #ff9800; 342 display: flex;
243 } 343 flex-direction: column;
244 } 344 justify-content: center;
345 align-items: center;
346 padding: 120rpx 0;
245 347
246 .date { 348 .empty-img {
247 font-size: 24rpx; 349 width: 300rpx;
248 color: #999; 350 height: 300rpx;
249 } 351 }
250 352
251 .text-primary { 353 .empty-text {
354 color: #666;
252 font-size: 28rpx; 355 font-size: 28rpx;
253 color: #AD181F; 356 margin-top: 20rpx;
254 } 357 }
358 }
255 359
256 .name { 360 .loading-tip,
257 font-size: 28rpx; 361 .no-more {
258 font-weight: 600; 362 text-align: center;
259 color: #333; 363 padding: 20rpx 0;
260 margin-bottom: 20rpx; 364 color: #999;
261 margin-top: 10rpx; 365 font-size: 26rpx;
366 }
262 367
263 &.mt0 { 368 .order-card-new {
264 margin-top: 0; 369 background: #fff;
265 } 370 margin-bottom: 20rpx;
266 } 371 padding: 20rpx 18rpx 16rpx;
372 box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
373 border-radius: 18rpx;
374 display: flex;
375 flex-direction: column;
267 376
268 .flexbox { 377 .card-header {
269 display: flex; 378 display: flex;
270 justify-content: space-between; 379 justify-content: space-between;
271 background-color: #fafafa; 380 align-items: center;
272 border-radius: 12rpx; 381 padding-bottom: 8rpx;
273 padding: 20rpx; 382
274 margin: 20rpx 0; 383 .date {
275 384 width: 100%;
276 view { 385 display: flex;
277 flex: 1; 386 align-items: center;
278 text-align: center; 387 justify-content: space-between;
388 gap: 12rpx;
279 font-size: 24rpx; 389 font-size: 24rpx;
280 color: #999;
281 390
282 view { 391 .data-header {
283 font-size: 28rpx; 392 display: flex;
284 color: #333; 393 align-items: center;
285 font-weight: 500; 394 min-width: 0;
286 margin-top: 8rpx; 395 flex: 1;
396 margin-right: 16rpx;
287 } 397 }
288 }
289 }
290 398
291 .mail-time { 399 .value {
292 font-size: 24rpx; 400 color: #c30d23;
293 color: #666; 401 font-size: 30rpx;
294 margin-top: 16rpx; 402 font-weight: bold;
403 max-width: 520rpx;
404 overflow: hidden;
405 white-space: nowrap;
406 text-overflow: ellipsis;
407 line-height: 1.25;
408 }
409
410 .status-tag {
411 font-size: 22rpx;
412 flex-shrink: 0;
413 line-height: 1.2;
414
415 &.status-pending {
416 color: #faad14;
417 }
418
419 &.status-success {
420 color: #52c41a;
421 }
422 }
423 }
295 } 424 }
296 425
297 .func { 426 .member-time {
427 width: 100%;
428 padding-bottom: 2rpx;
298 display: flex; 429 display: flex;
430 justify-content: space-between;
431 align-items: flex-start;
299 gap: 20rpx; 432 gap: 20rpx;
300 margin-top: 24rpx; 433
301 padding-top: 24rpx; 434 .label {
302 border-top: 1px solid #f0f0f0; 435 color: #333;
303 justify-content: flex-end; 436 flex: 1;
304 437 min-width: 0;
305 button { 438 font-size: 28rpx;
306 height: 64rpx; 439 font-weight: 700;
307 line-height: 64rpx; 440 line-height: 1.45;
441 word-break: break-word;
442
443 .star {
444 color: #777;
445 font-size: 22rpx;
446 margin-right: 10rpx;
447 vertical-align: 2rpx;
448 }
449 }
450
451 view:last-child {
452 flex-shrink: 0;
308 font-size: 26rpx; 453 font-size: 26rpx;
309 border-radius: 32rpx; 454 color: #222;
310 border: none; 455 font-weight: 500;
456 line-height: 1.3;
457 padding-top: 2rpx;
311 } 458 }
459 }
460 }
312 461
313 .btn-mail { 462 .info-summary {
314 width: 100px; 463 display: flex;
315 background: #AD181F; 464 justify-content: flex-end;
316 color: #fff; 465 margin-top: 4rpx;
466
467 .summary-right {
468 text-align: right;
469
470 .summary-top {
471 font-size: 26rpx;
472 color: #333;
473 font-weight: 500;
317 } 474 }
318 475
319 .btn-logistics { 476 .summary-bottom {
320 width: 100px; 477 margin-top: 8rpx;
321 background: linear-gradient(135deg, #2196f3, #42a5f5); 478 font-size: 24rpx;
322 color: #fff; 479 color: #999;
323 } 480 }
324 } 481 }
325 } 482 }
326 483
327 .nodata { 484 .detail-rows {
485 margin-top: 12rpx;
486 background: #f3f6fc;
487 border-radius: 14rpx;
488 padding: 14rpx 18rpx;
328 display: flex; 489 display: flex;
490 align-items: stretch;
491 justify-content: space-between;
492 }
493
494 .detail-col {
495 display: flex;
496 flex: 1;
497 min-width: 0;
329 flex-direction: column; 498 flex-direction: column;
330 align-items: center;
331 justify-content: center; 499 justify-content: center;
332 padding: 100rpx 0; 500 align-items: center;
501 box-sizing: border-box;
502 }
333 503
334 image { 504 .detail-divider {
335 width: 300rpx; 505 width: 1rpx;
336 height: 300rpx; 506 background: #d8deea;
337 } 507 margin: 4rpx 18rpx;
508 flex-shrink: 0;
509 }
338 510
339 text { 511 // .detail-col:last-child {
340 font-size: 28rpx; 512 // align-items: flex-end;
513 // }
514
515 .detail-row {
516 display: flex;
517 justify-content: space-between;
518 align-items: center;
519 flex: 1;
520 min-width: 0;
521 padding: 10rpx 0;
522 font-size: 24rpx;
523
524 .detail-label {
341 color: #999; 525 color: #999;
342 margin-top: 20rpx; 526 flex-shrink: 0;
527 margin-right: 12rpx;
528 }
529
530 .detail-value {
531 color: #333;
532 flex: 1;
533 text-align: right;
534 word-break: break-all;
535 font-size: 25rpx;
343 } 536 }
344 } 537 }
345 538
346 .loading { 539 .detail-col .detail-label {
347 padding: 30rpx 0; 540 color: #999;
541 font-size: 22rpx;
542 line-height: 1.2;
543 }
544
545 .detail-col .detail-value {
546 margin-top: 10rpx;
547 color: #333;
548 font-size: 26rpx;
549 line-height: 1.3;
550 max-width: 100%;
551 word-break: break-all;
552 }
553
554 .btn-group {
555 display: flex;
556 justify-content: flex-end;
557 align-items: center;
558 gap: 14rpx;
559 width: 100%;
560 margin-top: 14rpx;
561 flex-wrap: wrap;
562
563 .btn {
564 min-width: 138rpx;
565 height: 50rpx;
566 line-height: 48rpx;
567 padding: 0 18rpx;
568 border-radius: 12rpx;
569 font-size: 24rpx;
570 white-space: nowrap;
571 font-weight: 500;
572 background: transparent;
573 text-align: center;
574 margin: 0;
575 border: none;
576
577 &::after {
578 border: none;
579 display: none;
580 }
581 }
582
583 .btn-mail {
584 color: #c30d23;
585 border: 1rpx solid #c30d23;
586 background: #fff;
587 }
588
589 .btn-logistics {
590 color: #666;
591 border: 1rpx solid #ccc;
592 background: #fff;
593 }
594 }
595
596 .popup-mask {
597 position: fixed;
598 top: 0;
599 left: 0;
600 right: 0;
601 bottom: 0;
602 background-color: rgba(0, 0, 0, 0.5);
603 display: flex;
604 align-items: center;
605 justify-content: center;
606 z-index: 999;
607 }
608
609 .custom-modal {
610 width: 620rpx;
611 background: #fff;
612 border-radius: 20rpx;
613 padding: 36rpx 30rpx 30rpx;
614 box-sizing: border-box;
615 box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.2);
616 }
617
618 .modal-title {
619 font-size: 36rpx;
620 font-weight: 600;
621 color: #333;
348 text-align: center; 622 text-align: center;
349 } 623 }
350 </style>
...\ No newline at end of file ...\ No newline at end of file
624
625 .mail-form {
626 margin-top: 32rpx;
627 }
628
629 .form-item {
630 margin-bottom: 24rpx;
631 }
632
633 .form-label {
634 display: block;
635 margin-bottom: 12rpx;
636 font-size: 28rpx;
637 color: #333;
638 font-weight: 500;
639 }
640
641 .radio-group {
642 display: flex;
643 gap: 36rpx;
644 flex-wrap: wrap;
645 }
646
647 .radio-item {
648 display: inline-flex;
649 align-items: center;
650 font-size: 28rpx;
651 color: #333;
652 }
653
654 .form-input {
655 width: 100%;
656 height: 84rpx;
657 padding: 0 24rpx;
658 border-radius: 14rpx;
659 background: #f5f6f8;
660 box-sizing: border-box;
661 font-size: 28rpx;
662 color: #333;
663 }
664
665 .modal-btns {
666 display: flex;
667 justify-content: space-between;
668 gap: 20rpx;
669 margin-top: 30rpx;
670 }
671
672 .modal-btn-cancel,
673 .modal-btn-confirm {
674 flex: 1;
675 height: 80rpx;
676 line-height: 80rpx;
677 border-radius: 40rpx;
678 font-size: 32rpx;
679 border: none;
680 margin: 0;
681 padding: 0;
682
683 &::after {
684 border: none;
685 }
686 }
687
688 .modal-btn-cancel {
689 background: #f5f5f5;
690 color: #666;
691 }
692
693 .modal-btn-confirm {
694 background: #c4121b;
695 color: #fff;
696 }
697 </style>
......
...@@ -918,13 +918,6 @@ ...@@ -918,13 +918,6 @@
918 } 918 }
919 }, 919 },
920 { 920 {
921 "path": "ztx/certDetail",
922 "style": {
923 "navigationBarTitleText": "考试详情",
924 "enablePullDownRefresh": false
925 }
926 },
927 {
928 "path": "ztx/certLogistics", 921 "path": "ztx/certLogistics",
929 "style": { 922 "style": {
930 "navigationBarTitleText": "物流跟踪", 923 "navigationBarTitleText": "物流跟踪",
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!