ab9493d5 by lttnew

添加考生

1 parent 91e9e0c4
...@@ -705,6 +705,15 @@ export function editLevel(data) { ...@@ -705,6 +705,15 @@ export function editLevel(data) {
705 }) 705 })
706 } 706 }
707 707
708 // 添加考生(考级)
709 export function addPerson(data) {
710 return request({
711 url: '/exam/person',
712 method: 'post',
713 params: data
714 })
715 }
716
708 export function getVerityList(params) { 717 export function getVerityList(params) {
709 return request({ 718 return request({
710 url: '/exam/info/verityList', 719 url: '/exam/info/verityList',
...@@ -2173,3 +2182,11 @@ export function getSmsCode(data) { ...@@ -2173,3 +2182,11 @@ export function getSmsCode(data) {
2173 params: data 2182 params: data
2174 }) 2183 })
2175 } 2184 }
2185
2186 export function inMyMember(params) {
2187 return request({
2188 url: `/person/info/inMyMember/`,
2189 method: 'get',
2190 params
2191 })
2192 }
......
...@@ -15,13 +15,13 @@ ...@@ -15,13 +15,13 @@
15 </uni-list-item> 15 </uni-list-item>
16 <uni-list-item title="会员编号" v-if="form.menCode" :rightText="form.menCode" /> 16 <uni-list-item title="会员编号" v-if="form.menCode" :rightText="form.menCode" />
17 <uni-list-item title="机构名称" :rightText="form.name" /> 17 <uni-list-item title="机构名称" :rightText="form.name" />
18 <uni-list-item title="所属省份"> 18 <!-- <uni-list-item title="所属省份">
19 <template v-slot:footer> 19 <template v-slot:footer>
20 <uni-data-select :clear="false" disabled 20 <uni-data-select :clear="false" disabled
21 v-model="form.belongProvinceId" :localdata="regionsList"> 21 v-model="form.belongProvinceId" :localdata="regionsList">
22 </uni-data-select> 22 </uni-data-select>
23 </template> 23 </template>
24 </uni-list-item> 24 </uni-list-item> -->
25 <uni-list-item title="社会信用代码" :rightText="form.creditCode" /> 25 <uni-list-item title="社会信用代码" :rightText="form.creditCode" />
26 <uni-list-item v-if="isR" title="联系人" :rightText="form.certSiteContact" /> 26 <uni-list-item v-if="isR" title="联系人" :rightText="form.certSiteContact" />
27 <uni-list-item v-else title="联系人" :rightText="form.siteContact" /> 27 <uni-list-item v-else title="联系人" :rightText="form.siteContact" />
......
...@@ -73,10 +73,22 @@ ...@@ -73,10 +73,22 @@
73 </view> 73 </view>
74 74
75 <!-- 操作栏(红框顶部统计+添加按钮) --> 75 <!-- 操作栏(红框顶部统计+添加按钮) -->
76 <button class="btn-add-student" @click="goChooseStudent"> 76 <view class="action-bar flex f-j-s">
77 <uni-icons color="#fff" size="16" type="plus"></uni-icons> 77 <view class="btn-group">
78 添加考生 78
79 </button> 79 <button class="btn-add-student btn-outline" @click="goChooseStudent">
80 在线选择
81 </button>
82
83 </view>
84 <view >
85 <button class="btn-add-student" @click="handleAdd">
86 <uni-icons color="#fff" size="18" type="plus"></uni-icons>
87 添加
88 </button>
89 <!-- <uni-icons color="#faad14" size="18" type="warning"></uni-icons> 支持添加外部人员 -->
90 </view>
91 </view>
80 <view class="action-bar"> 92 <view class="action-bar">
81 <view class="stat-info"> 93 <view class="stat-info">
82 <text class="stat-total">{{ tablePersonInfo.total || 0 }}</text> 94 <text class="stat-total">{{ tablePersonInfo.total || 0 }}</text>
...@@ -86,7 +98,6 @@ ...@@ -86,7 +98,6 @@
86 </view> 98 </view>
87 </view> 99 </view>
88 </view> 100 </view>
89
90 </view> 101 </view>
91 102
92 <!-- 考生列表(红框主体) --> 103 <!-- 考生列表(红框主体) -->
...@@ -154,7 +165,40 @@ ...@@ -154,7 +165,40 @@
154 <button class="btn-red-kx" style="width: 25%;" @click="submitForm2(0)">保存</button> 165 <button class="btn-red-kx" style="width: 25%;" @click="submitForm2(0)">保存</button>
155 <button class="btn-red" style="width: 30%;" @click="submitForm2(1)">提交审核</button> 166 <button class="btn-red" style="width: 30%;" @click="submitForm2(1)">提交审核</button>
156 </view> 167 </view>
157 168
169 <!-- 添加考生弹框 -->
170 <uni-popup ref="addPopup" type="center" :mask-click="false" style="z-index: 99999">
171 <view class="add-popup">
172 <view class="popup-title">添加考生</view>
173 <view class="popup-content">
174 <!-- <view class="form-item">
175 <view class="form-label">姓名</view>
176 <view class="form-input">
177 <input v-model="addForm.name" placeholder="请输入姓名" placeholder-class="placeholder-class"/>
178 </view>
179 </view> -->
180 <view class="form-item">
181 <view class="form-label">证件类型</view>
182 <view class="form-input">
183 <picker :value="idcTypeIndex" :range="idcTypeList" range-key="text" @change="onIdcTypeChange">
184 <view class="picker-value">{{ idcTypeList[idcTypeIndex]?.text || '请选择证件类型' }}</view>
185 </picker>
186 </view>
187 </view>
188 <view class="form-item">
189 <view class="form-label">证件号</view>
190 <view class="form-input">
191 <input v-model="addForm.idcCode" placeholder="请输入证件号" placeholder-class="placeholder-class"/>
192 </view>
193 </view>
194 </view>
195 <view class="popup-btns">
196 <view class="popup-btn cancel" @click="closeAddPopup">取消</view>
197 <view class="popup-btn confirm" @click="confirmAdd">确定</view>
198 </view>
199 </view>
200 </uni-popup>
201
158 </view> 202 </view>
159 </template> 203 </template>
160 204
...@@ -220,6 +264,20 @@ const range = ref([{ ...@@ -220,6 +264,20 @@ const range = ref([{
220 text: '否' 264 text: '否'
221 }]) 265 }])
222 266
267 // 添加考生弹框相关
268 const addPopup = ref(null)
269 const addForm = ref({
270 name: '',
271 idcType: '0',
272 idcCode: ''
273 })
274 const idcTypeList = ref([
275 { value: '0', text: '身份证' },
276 { value: '1', text: '护照' },
277 { value: '2', text: '军官证' }
278 ])
279 const idcTypeIndex = ref(0)
280
223 let examId 281 let examId
224 282
225 onLoad(option => { 283 onLoad(option => {
...@@ -254,6 +312,7 @@ function initData(option) { ...@@ -254,6 +312,7 @@ function initData(option) {
254 } 312 }
255 313
256 onShow(() => { 314 onShow(() => {
315 console.log('addApply onShow called, examId:', examId, 'form.examId:', form.value.examId)
257 uni.$on('chosen', updateData) 316 uni.$on('chosen', updateData)
258 const curExamId = examId || form.value.examId 317 const curExamId = examId || form.value.examId
259 if (curExamId) { 318 if (curExamId) {
...@@ -405,6 +464,90 @@ function goChooseStudent() { ...@@ -405,6 +464,90 @@ function goChooseStudent() {
405 }) 464 })
406 } 465 }
407 466
467 // 打开添加弹框
468 function handleAdd() {
469 addForm.value = {
470 name: '',
471 idcType: '0',
472 idcCode: ''
473 }
474 idcTypeIndex.value = 0
475 addPopup.value?.open()
476 }
477
478 // 关闭添加弹框
479 function closeAddPopup() {
480 addPopup.value?.close()
481 }
482
483 // 证件类型选择
484 function onIdcTypeChange(e) {
485 idcTypeIndex.value = e.detail.value
486 addForm.value.idcType = idcTypeList.value[idcTypeIndex.value].value
487 }
488
489 // 确认添加考生
490 async function confirmAdd() {
491 if (!addForm.value.idcCode) {
492 uni.showToast({ title: '请输入证件号', icon: 'none' })
493 return
494 }
495
496 uni.showLoading({ title: '校验中...', mask: true })
497
498 try {
499 const checkRes = await api.inMyMember({ idcCode: addForm.value.idcCode })
500 uni.hideLoading()
501
502 if (checkRes.data) {
503 // 人员已存在,直接添加
504 await handelAddPerson()
505 } else {
506 // 人员不在本机构,弹出确认框
507 uni.showModal({
508 title: '系统提示',
509 content: '该人员已在其他机构登记,是否申请调入?如仅办理业务,请前往业务页面,点击【添加】直接办理。',
510 confirmText: '添加',
511 cancelText: '调动',
512 success: async function (res) {
513 if (res.confirm) {
514 await handelAddPerson()
515 } else if (res.cancel) {
516 // 跳转调动页面
517 uni.navigateTo({
518 url: '/personal/memberTransfer'
519 })
520 }
521 }
522 })
523 }
524 } catch (err) {
525 uni.hideLoading()
526 console.log(err)
527 }
528 }
529
530 // 执行添加考生
531 async function handelAddPerson() {
532 uni.showLoading({ title: '添加中...', mask: true })
533 try {
534 // 调用 /exam/person 接口添加考生
535 await api.addPerson({
536 examId: form.value.examId,
537 idcCode: addForm.value.idcCode,
538 idcType: addForm.value.idcType,
539 name: addForm.value.name || ''
540 })
541 uni.hideLoading()
542 uni.showToast({ title: '添加成功', icon: 'success' })
543 closeAddPopup()
544 getChosedStudentList()
545 } catch (err) {
546 uni.hideLoading()
547 console.log(err)
548 }
549 }
550
408 // 格式化日期时间 551 // 格式化日期时间
409 function formatDateTime(dateStr) { 552 function formatDateTime(dateStr) {
410 if (!dateStr) return '-' 553 if (!dateStr) return '-'
...@@ -781,19 +924,46 @@ function handleDelete(row) { ...@@ -781,19 +924,46 @@ function handleDelete(row) {
781 display: flex; 924 display: flex;
782 align-items: center; 925 align-items: center;
783 justify-content: center; 926 justify-content: center;
784 padding: 0 30rpx; 927 padding: 0 40rpx;
785 height: 64rpx; 928 height: 64rpx;
786 background: linear-gradient(135deg, #AD181F 0%, #c42a2a 100%); 929 background: linear-gradient(135deg, #AD181F 0%, #c42a2a 100%);
787 border-radius: 32rpx; 930 border-radius: 32rpx;
788 font-size: 26rpx; 931 font-size: 26rpx;
789 color: #fff; 932 color: #fff;
790 box-shadow: 0 4rpx 16rpx rgba(173, 24, 31, 0.3); 933 box-shadow: 0 4rpx 16rpx rgba(173, 24, 31, 0.3);
934
935 &.btn-outline {
936 background: #fff;
937 color: #AD181F;
938 border: 2rpx solid #AD181F;
939 box-shadow: none;
940 margin-left: 20rpx;
941 }
942 }
943
944 .btn-group {
945 display: flex;
946 align-items: center;
947 }
948
949 .hint-text {
950 font-size: 24rpx;
951 color: #faad14;
952 margin-top: 16rpx;
953 display: flex;
954 align-items: center;
955
956
791 } 957 }
792 958
793 /* 考生列表(核心优化) */ 959 /* 考生列表(核心优化) */
794 .student-list { 960 .student-list {
961 position: relative;
962 z-index: 1;
963
795 .student-card { 964 .student-card {
796 position: relative; 965 position: relative;
966 z-index: 1;
797 // display: flex; 967 // display: flex;
798 968
799 // align-items: center; 969 // align-items: center;
...@@ -863,6 +1033,8 @@ function handleDelete(row) { ...@@ -863,6 +1033,8 @@ function handleDelete(row) {
863 margin-top: 20rpx; 1033 margin-top: 20rpx;
864 margin-left: 100rpx; 1034 margin-left: 100rpx;
865 height: 100rpx; 1035 height: 100rpx;
1036 position: relative;
1037 z-index: 1;
866 // flex-direction: column; 1038 // flex-direction: column;
867 // align-items: flex-end; 1039 // align-items: flex-end;
868 // gap: 16rpx; 1040 // gap: 16rpx;
...@@ -887,13 +1059,7 @@ function handleDelete(row) { ...@@ -887,13 +1059,7 @@ function handleDelete(row) {
887 .select-wrapper { 1059 .select-wrapper {
888 width: 160rpx; 1060 width: 160rpx;
889 position: relative; 1061 position: relative;
890 z-index: 99; 1062 z-index: 1;
891 }
892
893 .exam-level-select {
894 position: relative;
895 z-index: 999;
896 margin-bottom: 300rpx;
897 } 1063 }
898 } 1064 }
899 } 1065 }
...@@ -990,4 +1156,88 @@ function handleDelete(row) { ...@@ -990,4 +1156,88 @@ function handleDelete(row) {
990 font-weight: 600; 1156 font-weight: 600;
991 } 1157 }
992 } 1158 }
1159
1160 /* 添加考生弹框 */
1161 .add-popup {
1162 width: 600rpx;
1163 background: #ffffff;
1164 border-radius: 24rpx;
1165 overflow: hidden;
1166 position: relative;
1167 z-index: 9999;
1168 }
1169
1170 .popup-title {
1171 font-size: 32rpx;
1172 font-weight: 500;
1173 color: #333;
1174 text-align: center;
1175 padding: 40rpx 30rpx 20rpx;
1176 }
1177
1178 .popup-content {
1179 padding: 20rpx 30rpx 40rpx;
1180 }
1181
1182 .form-item {
1183 display: flex;
1184 align-items: center;
1185 margin-bottom: 24rpx;
1186 }
1187
1188 .form-item:last-child {
1189 margin-bottom: 0;
1190 }
1191
1192 .form-label {
1193 width: 120rpx;
1194 font-size: 28rpx;
1195 color: #333;
1196 flex-shrink: 0;
1197 }
1198
1199 .form-input {
1200 flex: 1;
1201 background: #f5f5f5;
1202 border-radius: 12rpx;
1203 padding: 20rpx 24rpx;
1204 }
1205
1206 .form-input input {
1207 font-size: 28rpx;
1208 color: #333;
1209 width: 100%;
1210 }
1211
1212 .placeholder-class {
1213 color: #999;
1214 }
1215
1216 .picker-value {
1217 font-size: 28rpx;
1218 color: #333;
1219 }
1220
1221 .popup-btns {
1222 display: flex;
1223 border-top: 1rpx solid #eee;
1224 }
1225
1226 .popup-btn {
1227 flex: 1;
1228 height: 100rpx;
1229 line-height: 100rpx;
1230 text-align: center;
1231 font-size: 30rpx;
1232 }
1233
1234 .popup-btn.cancel {
1235 color: #666;
1236 border-right: 1rpx solid #eee;
1237 }
1238
1239 .popup-btn.confirm {
1240 color: #C4121B;
1241 font-weight: 500;
1242 }
993 </style> 1243 </style>
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
45 </view> 45 </view>
46 <view class="info-row" v-if="form.fileUrl"> 46 <view class="info-row" v-if="form.fileUrl">
47 <text class="label">发票</text> 47 <text class="label">发票</text>
48 <text class="value text-primary" @click="downloadInvoice">下载发票</text> 48 <text class="value text-primary" @click="downloadInvoice">查看发票</text>
49 </view> 49 </view>
50 </view> 50 </view>
51 </view> 51 </view>
...@@ -190,18 +190,58 @@ function downloadInvoice() { ...@@ -190,18 +190,58 @@ function downloadInvoice() {
190 try { 190 try {
191 const invoice = JSON.parse(form.value.fileUrl) 191 const invoice = JSON.parse(form.value.fileUrl)
192 if (invoice && invoice[0]?.url) { 192 if (invoice && invoice[0]?.url) {
193 let fileUrl = invoice[0].url 193 let url = invoice[0].url
194 if (!fileUrl.startsWith('http')) { 194 if (!url.startsWith('http')) {
195 fileUrl = config.baseUrl_api + fileUrl 195 url = config.baseUrl_api + url
196 } 196 }
197 uni.previewImage({ 197 // 从 URL 中获取文件名判断类型
198 urls: [fileUrl], 198 let ext = ''
199 success: () => { 199 const urlParts = url.split('/')
200 console.log('previewImage success') 200 const fileNameFromUrl = urlParts[urlParts.length - 1] || ''
201 if (fileNameFromUrl) {
202 const nameParts = fileNameFromUrl.split('.')
203 if (nameParts.length > 1) {
204 ext = nameParts[nameParts.length - 1].toLowerCase()
205 }
206 }
207 const isImage = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'].includes(ext)
208
209 uni.showLoading({ title: '加载中' })
210 uni.downloadFile({
211 url: url,
212 success: (res) => {
213 uni.hideLoading()
214 if (res.statusCode === 200) {
215 if (isImage) {
216 // 图片预览
217 uni.previewImage({
218 urls: [res.tempFilePath]
219 })
220 } else {
221 // 文件下载后打开
222 uni.saveFile({
223 tempFilePath: res.tempFilePath,
224 success: (saveRes) => {
225 uni.openDocument({
226 filePath: saveRes.savedFilePath,
227 showMenu: true,
228 fail: () => {
229 uni.showToast({ title: '打开失败', icon: 'none' })
230 }
231 })
232 },
233 fail: () => {
234 uni.showToast({ title: '保存失败', icon: 'none' })
235 }
236 })
237 }
238 } else {
239 uni.showToast({ title: '下载失败', icon: 'none' })
240 }
201 }, 241 },
202 fail: (err) => { 242 fail: () => {
203 console.error('previewImage fail:', err) 243 uni.hideLoading()
204 uni.showToast({ title: '打开图片失败', icon: 'none' }) 244 uni.showToast({ title: '下载失败', icon: 'none' })
205 } 245 }
206 }) 246 })
207 } 247 }
......
...@@ -54,18 +54,22 @@ ...@@ -54,18 +54,22 @@
54 <view class="name mt0">{{ item.name || '-' }}</view> 54 <view class="name mt0">{{ item.name || '-' }}</view>
55 <view class="flexbox"> 55 <view class="flexbox">
56 <view> 56 <view>
57 结算单位
58 <view>{{ item.memName || '-' }}</view>
59 </view>
60 <view>
61 结算金额 57 结算金额
62 <view class="text-red">¥{{ Number(item.price || 0).toFixed(2) }}</view> 58 <view class="text-red">¥{{ Number(item.price || 0).toFixed(2) }}</view>
63 </view> 59 </view>
60 <view>
61 费用合计
62 <view class="text-red">¥{{ Number(item.originPrice || 0).toFixed(2) }}</view>
63 </view>
64
64 </view> 65 </view>
65 <view class="flex f-j-s"> 66 <view class="flex f-j-s">
66 <view class="info-time" v-if="item.commitTime"> 67 <view class="info-time" v-if="item.commitTime">
67 提交时间:{{ formatDate(item.commitTime) }} 68 提交时间:{{ formatDate(item.commitTime) }}
68 </view> 69 </view>
70 <view class="info-time" v-if="item.auditTime">
71 审核时间:{{ formatDate(item.auditTime) }}
72 </view>
69 </view> 73 </view>
70 </view> 74 </view>
71 </view> 75 </view>
...@@ -202,7 +206,7 @@ function formatDate(dateStr) { ...@@ -202,7 +206,7 @@ function formatDate(dateStr) {
202 if (typeof dateStr === 'string' && dateStr.indexOf('T') > -1) { 206 if (typeof dateStr === 'string' && dateStr.indexOf('T') > -1) {
203 return dateStr.slice(0, 10) 207 return dateStr.slice(0, 10)
204 } 208 }
205 return dateStr 209 return dateStr.slice(0, 10)
206 } 210 }
207 211
208 function goDetail(item) { 212 function goDetail(item) {
......
...@@ -18,18 +18,24 @@ ...@@ -18,18 +18,24 @@
18 </view> 18 </view>
19 19
20 <view class="appList" v-else> 20 <view class="appList" v-else>
21 <view class="appItem" v-for="(item, index) in list" :key="item.payId || index" @click="toggleSelect(item)"> 21 <view class="appItem" v-for="(item, index) in list" :key="item.payId || index">
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"> 22 <view class="item-content">
26 <view class="status"> 23 <view class="item-top">
27 <text :class="getStatusClass(item.verityStatus)"> 24 <checkbox-group @change="onCheckboxChange(item.payId)" class="inline-checkbox">
28 {{ item.verityStatusStr || '审核中' }} 25 <label>
29 </text> 26 <checkbox :value="item.payId" :checked="isSelected(item.payId)" color="#C4121B" />
30 </view> 27 </label>
31 <view class="date"> 28 </checkbox-group>
32 <view class="text-primary" v-if="item.payCode">{{ item.payCode }}</view> 29 <view class="paycode-wrap">
30 <view class="date1">
31 <view class="text-primary" v-if="item.payCode">{{ item.payCode }}</view>
32 </view>
33 <view class="status">
34 <text :class="getStatusClass(item.verityStatus)">
35 {{ item.verityStatusStr || '审核中' }}
36 </text>
37 </view>
38 </view>
33 </view> 39 </view>
34 40
35 <view class="name mt0">{{ item.name || '-' }}</view> 41 <view class="name mt0">{{ item.name || '-' }}</view>
...@@ -174,18 +180,17 @@ function formatDate(dateStr) { ...@@ -174,18 +180,17 @@ function formatDate(dateStr) {
174 return dateStr 180 return dateStr
175 } 181 }
176 182
177 function toggleSelect(item) { 183 function onCheckboxChange(payId) {
178 if (selectedIds.value.has(item.payId)) { 184 if (selectedIds.value.has(payId)) {
179 selectedIds.value.delete(item.payId) 185 selectedIds.value.delete(payId)
180 } else { 186 } else {
181 selectedIds.value.add(item.payId) 187 selectedIds.value.add(payId)
182 } 188 }
183 selectedIds.value = new Set(selectedIds.value) 189 selectedIds.value = new Set(selectedIds.value)
184 } 190 }
185 191
186 // 修复:这里传 item 而不是 payId 192 function isSelected(payId) {
187 function isSelected(item) { 193 return selectedIds.value.has(payId)
188 return selectedIds.value.has(item.payId)
189 } 194 }
190 195
191 function handleSettlement() { 196 function handleSettlement() {
...@@ -227,60 +232,58 @@ function handleSettlement() { ...@@ -227,60 +232,58 @@ function handleSettlement() {
227 padding: 30rpx; 232 padding: 30rpx;
228 margin-bottom: 20rpx; 233 margin-bottom: 20rpx;
229 box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05); 234 box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
230 display: flex;
231 align-items: center;
232 position: relative; 235 position: relative;
233 236
234 // 选择框 - 修复样式
235 .select-indicator {
236 width: 36rpx;
237 height: 36rpx;
238 border-radius: 50%;
239 border: 2rpx solid #ddd;
240 display: flex;
241 align-items: center;
242 justify-content: center;
243 margin-right: 20rpx;
244 flex-shrink: 0;
245 transition: all 0.2s;
246
247 &.selected {
248 background-color: #AD181F;
249 border-color: #AD181F;
250 }
251 }
252
253 .item-content { 237 .item-content {
254 flex: 1; 238 flex: 1;
255 min-width: 0; 239 min-width: 0;
256 } 240 }
257 241
258 .status { 242 .item-top {
259 display: inline-block; 243 display: flex;
260 padding: 6rpx 20rpx; 244 align-items: center;
261 border-radius: 20rpx;
262 font-size: 24rpx;
263 margin-bottom: 16rpx; 245 margin-bottom: 16rpx;
264 246 border-bottom: 1px dashed #e5e5e5;
265 .text-success { 247 .inline-checkbox {
266 color: #4caf50; 248 display: inline-flex;
249 margin-right: 10rpx;
250 width: 50rpx;
251 margin-bottom: 10rpx;
252
253 checkbox {
254 transform: scale(0.85);
255 }
267 } 256 }
268 .text-warning { 257
269 color: #ff9800; 258 .paycode-wrap {
259 display: flex;
260 align-items: center;
261 flex: 1;
270 } 262 }
271 .text-danger { 263
272 color: #f5222d; 264 .date1 {
265 display: inline-flex;
266 align-items: center;
273 } 267 }
274 }
275 268
276 .date { 269 .status {
277 font-size: 24rpx; 270 display: inline-block;
278 color: #999; 271 padding: 6rpx 20rpx;
279 } 272 border-radius: 20rpx;
273 font-size: 24rpx;
274 background: #f5f5f5;
275 margin-top: 10rpx;
280 276
281 .text-primary { 277 .text-success {
282 font-size: 28rpx; 278 color: #4caf50;
283 color: #AD181F; 279 }
280 .text-warning {
281 color: #ff9800;
282 }
283 .text-danger {
284 color: #f5222d;
285 }
286 }
284 } 287 }
285 288
286 .name { 289 .name {
...@@ -295,6 +298,11 @@ function handleSettlement() { ...@@ -295,6 +298,11 @@ function handleSettlement() {
295 } 298 }
296 } 299 }
297 300
301 .text-primary {
302 font-size: 28rpx;
303 color: #AD181F;
304 }
305
298 .flexbox { 306 .flexbox {
299 display: flex; 307 display: flex;
300 justify-content: space-between; 308 justify-content: space-between;
......
...@@ -85,8 +85,8 @@ onLoad((options) => { ...@@ -85,8 +85,8 @@ onLoad((options) => {
85 85
86 // 数字转汉字 86 // 数字转汉字
87 function szToHz(num) { 87 function szToHz(num) {
88 const arr = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十'] 88 const hzArr = ['〇', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十']
89 return arr[num] || num + 1 89 return hzArr[parseInt(num)]
90 } 90 }
91 91
92 async function getConfirm(ids) { 92 async function getConfirm(ids) {
...@@ -213,7 +213,7 @@ async function handleSubmit() { ...@@ -213,7 +213,7 @@ async function handleSubmit() {
213 padding: 30rpx; 213 padding: 30rpx;
214 margin-bottom: 20rpx; 214 margin-bottom: 20rpx;
215 box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05); 215 box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
216 border-left: 8rpx solid #27a9e7; 216 // border-left: 8rpx solid #27a9e7;
217 217
218 .section-title { 218 .section-title {
219 font-size: 28rpx; 219 font-size: 28rpx;
......
...@@ -44,8 +44,8 @@ ...@@ -44,8 +44,8 @@
44 <text class="value"> {{ form.auditTime }}</text> 44 <text class="value"> {{ form.auditTime }}</text>
45 </view> 45 </view>
46 <view class="info-item"> 46 <view class="info-item">
47 <text class="label">下载发票</text> 47 <text class="label">发票</text>
48 <text class="value link" @click="handelInvoice(form.fileUrl)"> 下载发票</text> 48 <text class="value link" @click="handelInvoice(form.fileUrl)"> 查看发票</text>
49 </view> 49 </view>
50 </view> 50 </view>
51 </view> 51 </view>
...@@ -266,7 +266,6 @@ function getVerityStatusClass(status) { ...@@ -266,7 +266,6 @@ function getVerityStatusClass(status) {
266 } 266 }
267 267
268 function handelInvoice(fileUrl) { 268 function handelInvoice(fileUrl) {
269 console.log('fileUrl', fileUrl)
270 if (!fileUrl) { 269 if (!fileUrl) {
271 uni.showToast({ title: '暂无发票', icon: 'none' }) 270 uni.showToast({ title: '暂无发票', icon: 'none' })
272 return 271 return
...@@ -274,61 +273,61 @@ function handelInvoice(fileUrl) { ...@@ -274,61 +273,61 @@ function handelInvoice(fileUrl) {
274 try { 273 try {
275 const invoice = JSON.parse(fileUrl) 274 const invoice = JSON.parse(fileUrl)
276 if (invoice && invoice.length > 0) { 275 if (invoice && invoice.length > 0) {
277 let url = invoice[0].url 276 let url = invoice[0].url || ''
278 const fileName = invoice[0].name || '' 277 if (!url) {
279 // 避免使用可选链操作符,确保兼容性 278 uni.showToast({ title: '暂无发票', icon: 'none' })
280 let ext = '' 279 return
281 if (fileName) {
282 const parts = fileName.split('.')
283 if (parts.length > 1) {
284 ext = parts[parts.length - 1].toLowerCase()
285 }
286 } 280 }
287 console.log('发票信息:', { url, fileName, ext })
288 // 判断是否需要拼接 baseUrl 281 // 判断是否需要拼接 baseUrl
289 if (url.indexOf('http') === -1) { 282 if (url.indexOf('http') === -1) {
290 url = config.baseUrl_api + url 283 url = config.baseUrl_api + url
291 } 284 }
292 console.log('完整下载地址:', url) 285 // 从 URL 中获取文件名判断类型
293 uni.showLoading({ title: '下载中' }) 286 let ext = ''
287 const urlParts = url.split('/')
288 const fileNameFromUrl = urlParts[urlParts.length - 1] || ''
289 if (fileNameFromUrl) {
290 const nameParts = fileNameFromUrl.split('.')
291 if (nameParts.length > 1) {
292 ext = nameParts[nameParts.length - 1].toLowerCase()
293 }
294 }
295 const isImage = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'].includes(ext)
296
297 uni.showLoading({ title: '加载中' })
294 uni.downloadFile({ 298 uni.downloadFile({
295 url: url, 299 url: url,
296 success: (res) => { 300 success: (res) => {
297 console.log('下载成功:', res)
298 uni.hideLoading() 301 uni.hideLoading()
299 if (res.statusCode === 200) { 302 if (res.statusCode === 200) {
300 // 图片类型用 previewImage 预览 303 if (isImage) {
301 if (['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'].includes(ext)) { 304 // 图片预览
302 uni.previewImage({ 305 uni.previewImage({
303 urls: [res.tempFilePath], 306 urls: [res.tempFilePath]
304 success: () => {
305 console.log('预览成功')
306 },
307 fail: (err) => {
308 console.error('预览失败:', err)
309 uni.showToast({ title: '预览失败', icon: 'none' })
310 }
311 }) 307 })
312 } else { 308 } else {
313 // PDF 等文档用 openDocument 打开 309 // 文件下载后打开
314 uni.openDocument({ 310 uni.saveFile({
315 filePath: res.tempFilePath, 311 tempFilePath: res.tempFilePath,
316 showMenu: true, 312 success: (saveRes) => {
317 success: () => { 313 uni.openDocument({
318 console.log('打开文档成功') 314 filePath: saveRes.savedFilePath,
315 showMenu: true,
316 fail: () => {
317 uni.showToast({ title: '打开失败', icon: 'none' })
318 }
319 })
319 }, 320 },
320 fail: (err) => { 321 fail: () => {
321 console.error('打开失败:', err) 322 uni.showToast({ title: '保存失败', icon: 'none' })
322 uni.showToast({ title: '打开失败', icon: 'none' })
323 } 323 }
324 }) 324 })
325 } 325 }
326 } else { 326 } else {
327 uni.showToast({ title: '下载失败: ' + res.statusCode, icon: 'none' }) 327 uni.showToast({ title: '下载失败', icon: 'none' })
328 } 328 }
329 }, 329 },
330 fail: (err) => { 330 fail: () => {
331 console.error('下载失败:', err)
332 uni.hideLoading() 331 uni.hideLoading()
333 uni.showToast({ title: '下载失败', icon: 'none' }) 332 uni.showToast({ title: '下载失败', icon: 'none' })
334 } 333 }
......
...@@ -239,18 +239,31 @@ let hasOpenedBindPopup = false ...@@ -239,18 +239,31 @@ let hasOpenedBindPopup = false
239 239
240 onShow(() => { 240 onShow(() => {
241 let webUserName = uni.getStorageSync('webUserName') 241 let webUserName = uni.getStorageSync('webUserName')
242 console.log(webUserName)
243 if (!webUserName) { 242 if (!webUserName) {
244 wxLogin().then(getWebInfo) 243 // 登录后需要等待数据加载完成
244 wxLogin().then(res => {
245 getWebInfo().then(() => {
246 // 数据加载完成后检查是否需要弹出绑定框
247 checkAndOpenBindPopup()
248 })
249 })
250 } else {
251 // 已登录,直接检查
252 checkAndOpenBindPopup()
245 } 253 }
246 // 只有当 perInfo 数据存在且 perCode 为空时才弹出 254 })
247 if (perInfo.value && !perInfo.value.perCode && !hasOpenedBindPopup) { 255
256 // 检查是否需要弹出绑定框
257 const checkAndOpenBindPopup = () => {
258 // 确保 userStore 数据已更新
259 const currentPerInfo = userStore.perInfo
260 if (currentPerInfo && !currentPerInfo.perCode && !hasOpenedBindPopup) {
248 hasOpenedBindPopup = true 261 hasOpenedBindPopup = true
249 nextTick(() => { 262 nextTick(() => {
250 openBindPopup() 263 openBindPopup()
251 }) 264 })
252 } 265 }
253 }) 266 }
254 267
255 268
256 // watch(() => perInfo.value, (newVal, oldVal) => { 269 // watch(() => perInfo.value, (newVal, oldVal) => {
......
...@@ -119,6 +119,10 @@ ...@@ -119,6 +119,10 @@
119 <text class="more" @click.stop="goToDetail(item)">更多</text> 119 <text class="more" @click.stop="goToDetail(item)">更多</text>
120 </view> 120 </view>
121 <view class="btn-flex"> 121 <view class="btn-flex">
122 <!-- 待缴费:去缴费 -->
123 <!-- <template v-if="item.payStatus == 0">
124 <button class="btn btn-pay" @click.stop="goPay(item)">去缴费</button>
125 </template> -->
122 <button class="btn btn-info" @click.stop="goToDetail(item)">查看明细</button> 126 <button class="btn btn-info" @click.stop="goToDetail(item)">查看明细</button>
123 <!-- 已缴费:申请开票/已开票(需要审核通过才能开票) --> 127 <!-- 已缴费:申请开票/已开票(需要审核通过才能开票) -->
124 <template v-if="item.payStatus == 1 && item.invoiceStatus != 1 && item.auditStatus == 2 && item.price > 0"> 128 <template v-if="item.payStatus == 1 && item.invoiceStatus != 1 && item.auditStatus == 2 && item.price > 0">
...@@ -368,6 +372,21 @@ const goToDetail = (item) => { ...@@ -368,6 +372,21 @@ const goToDetail = (item) => {
368 uni.navigateTo({url: `/personalVip/orderDetail?rangeId=${item.sourceId || item.id}&type=${queryParams.type}`}); 372 uni.navigateTo({url: `/personalVip/orderDetail?rangeId=${item.sourceId || item.id}&type=${queryParams.type}`});
369 }; 373 };
370 374
375 // 去缴费
376 const goPay = (item) => {
377 const baseFormData = {
378 rangeId: item.sourceId || item.id,
379 payYear: item.content?.yearCount || 1,
380 sourceId: item.sourceId || item.id,
381 tradeNo: item.tradeNo,
382 price: item.price
383 };
384 const formStr = encodeURIComponent(JSON.stringify(baseFormData));
385 uni.navigateTo({
386 url: `/personal/goPay_per?baseFormData=${formStr}`
387 });
388 };
389
371 // 删除订单 390 // 删除订单
372 const handleDelete = (item) => { 391 const handleDelete = (item) => {
373 currentOrder.value = item; 392 currentOrder.value = item;
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!