考点添加照片
Showing
10 changed files
with
535 additions
and
25 deletions
| ... | @@ -1690,13 +1690,21 @@ export function selfAdd(ids) { | ... | @@ -1690,13 +1690,21 @@ export function selfAdd(ids) { |
| 1690 | }) | 1690 | }) |
| 1691 | } | 1691 | } |
| 1692 | 1692 | ||
| 1693 | export function commitExamPointApply(params) { | 1693 | export function commitExamPointApply(params) { |
| 1694 | return request({ | 1694 | const data = {...(params || {})} |
| 1695 | url: `/member/examPointApply/commit?selfSelect=${params.selfSelect}`, | 1695 | if (Array.isArray(data.photos)) { |
| 1696 | method: 'post', | 1696 | data.photos = data.photos.filter(Boolean).join(',') |
| 1697 | params | 1697 | } |
| 1698 | }) | 1698 | const query = Object.keys(data) |
| 1699 | } | 1699 | .filter(key => data[key] !== undefined && data[key] !== null && data[key] !== '') |
| 1700 | .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`) | ||
| 1701 | .join('&') | ||
| 1702 | return request({ | ||
| 1703 | url: `/member/examPointApply/commit${query ? `?${query}` : ''}`, | ||
| 1704 | method: 'post', | ||
| 1705 | params: {} | ||
| 1706 | }) | ||
| 1707 | } | ||
| 1700 | 1708 | ||
| 1701 | export function getMyStatus(options = {}) { | 1709 | export function getMyStatus(options = {}) { |
| 1702 | return request({ | 1710 | return request({ | ... | ... |
| 1 | // dev | 1 | // dev |
| 2 | // const baseUrl_api = 'http://192.168.1.159:8787' | 2 | const baseUrl_api = 'http://192.168.1.159:8787' |
| 3 | // const baseUrl_api = 'http://47.98.186.233:8787' | 3 | // const baseUrl_api = 'http://47.98.186.233:8787' |
| 4 | const baseUrl_api = 'https://tk001.wxjylt.com/stage-api/' | 4 | // const baseUrl_api = 'https://tk001.wxjylt.com/stage-api/' |
| 5 | const loginImage_api = 'https://tk001.wxjylt.com/stage-api' | 5 | const loginImage_api = 'https://tk001.wxjylt.com/stage-api' |
| 6 | const payUrl = 'https://wxpay.cmbc.com.cn/mobilePlatform/appserver/lcbpPay.do' | 6 | const payUrl = 'https://wxpay.cmbc.com.cn/mobilePlatform/appserver/lcbpPay.do' |
| 7 | 7 | ... | ... |
| ... | @@ -7,6 +7,66 @@ | ... | @@ -7,6 +7,66 @@ |
| 7 | <text v-else class="tips-text">单个审核</text> | 7 | <text v-else class="tips-text">单个审核</text> |
| 8 | </view> --> | 8 | </view> --> |
| 9 | 9 | ||
| 10 | <!-- 申请详情 --> | ||
| 11 | <view v-if="type === 'single' && detailForm.id" class="detail-section"> | ||
| 12 | <view class="section-header"> | ||
| 13 | <uni-icons color="#AD181F" size="18" type="paperclip"></uni-icons> | ||
| 14 | <text class="section-title">基本信息</text> | ||
| 15 | </view> | ||
| 16 | <view class="info-card"> | ||
| 17 | <view class="info-row"> | ||
| 18 | <text class="label">申请单位</text> | ||
| 19 | <text class="value">{{ detailForm.memName || '-' }}</text> | ||
| 20 | </view> | ||
| 21 | <view class="info-row"> | ||
| 22 | <text class="label">所属协会</text> | ||
| 23 | <text class="value">{{ detailForm.shenMemName || '-' }}</text> | ||
| 24 | </view> | ||
| 25 | <view class="info-row"> | ||
| 26 | <text class="label">审核状态</text> | ||
| 27 | <text :class="getStatusClass(getCurrentAuditStatus())" class="value"> | ||
| 28 | {{ getStatusText(getCurrentAuditStatus()) }} | ||
| 29 | </text> | ||
| 30 | </view> | ||
| 31 | <view class="info-row"> | ||
| 32 | <text class="label">是否需要省级协会指派</text> | ||
| 33 | <text class="value">{{ detailForm.selfSelect == 1 ? '否' : '是' }}</text> | ||
| 34 | </view> | ||
| 35 | <view class="info-row"> | ||
| 36 | <text class="label">会员有效期</text> | ||
| 37 | <text class="value">{{ formatDate(detailForm.memValidDate) }}</text> | ||
| 38 | </view> | ||
| 39 | <view class="info-row"> | ||
| 40 | <text class="label">申请日期</text> | ||
| 41 | <text class="value">{{ formatDate(detailForm.commitTime) }}</text> | ||
| 42 | </view> | ||
| 43 | <view class="info-row"> | ||
| 44 | <text class="label">审核日期</text> | ||
| 45 | <text class="value">{{ formatDate(getCurrentAuditTime()) }}</text> | ||
| 46 | </view> | ||
| 47 | <view class="info-row"> | ||
| 48 | <text class="label">考官</text> | ||
| 49 | <text class="value">{{ detailForm.examiners || '-' }}</text> | ||
| 50 | </view> | ||
| 51 | <!-- <view v-if="photoList.length > 0" class="venue-block"> | ||
| 52 | <view class="venue-title"> | ||
| 53 | <uni-icons color="#AD181F" size="16" type="image"></uni-icons> | ||
| 54 | <text>场馆照片</text> | ||
| 55 | </view> | ||
| 56 | <view class="photo-list"> | ||
| 57 | <image | ||
| 58 | v-for="(item, index) in photoList" | ||
| 59 | :key="item" | ||
| 60 | class="venue-photo" | ||
| 61 | :src="item" | ||
| 62 | mode="aspectFill" | ||
| 63 | @click="previewPhoto(index)" | ||
| 64 | /> | ||
| 65 | </view> | ||
| 66 | </view> --> | ||
| 67 | </view> | ||
| 68 | </view> | ||
| 69 | |||
| 10 | <!-- 审核表单 --> | 70 | <!-- 审核表单 --> |
| 11 | <view class="form-section"> | 71 | <view class="form-section"> |
| 12 | <view class="section-header"> | 72 | <view class="section-header"> |
| ... | @@ -57,7 +117,7 @@ | ... | @@ -57,7 +117,7 @@ |
| 57 | </view> | 117 | </view> |
| 58 | 118 | ||
| 59 | 119 | ||
| 60 | <view v-if="userType==2&&selfSelect==0" class="section"> | 120 | <!-- <view v-if="userType==2&&selfSelect==0" class="section"> |
| 61 | <view class="section examiner-section"> | 121 | <view class="section examiner-section"> |
| 62 | <button class="add-btn" @click="handelAddExamine">+ 添加考官</button> | 122 | <button class="add-btn" @click="handelAddExamine">+ 添加考官</button> |
| 63 | </view> | 123 | </view> |
| ... | @@ -72,7 +132,7 @@ | ... | @@ -72,7 +132,7 @@ |
| 72 | <button class="del-btn" @click="handleDel(item)">删除</button> | 132 | <button class="del-btn" @click="handleDel(item)">删除</button> |
| 73 | </view> | 133 | </view> |
| 74 | </view> | 134 | </view> |
| 75 | </view> | 135 | </view> --> |
| 76 | 136 | ||
| 77 | 137 | ||
| 78 | <!-- 提交按钮 --> | 138 | <!-- 提交按钮 --> |
| ... | @@ -101,6 +161,7 @@ | ... | @@ -101,6 +161,7 @@ |
| 101 | 161 | ||
| 102 | <script setup> | 162 | <script setup> |
| 103 | import * as api from '@/common/api_exam.js' | 163 | import * as api from '@/common/api_exam.js' |
| 164 | import { fillImgUrl } from '@/common/utils.js' | ||
| 104 | import {ref} from 'vue' | 165 | import {ref} from 'vue' |
| 105 | import {onLoad, onShow} from '@dcloudio/uni-app' | 166 | import {onLoad, onShow} from '@dcloudio/uni-app' |
| 106 | import {listApi, examinerDel} from "@/common/api.js"; | 167 | import {listApi, examinerDel} from "@/common/api.js"; |
| ... | @@ -113,6 +174,8 @@ const selfSelect = ref('1') | ... | @@ -113,6 +174,8 @@ const selfSelect = ref('1') |
| 113 | const userType = ref('') | 174 | const userType = ref('') |
| 114 | const list = ref([]) | 175 | const list = ref([]) |
| 115 | const memId = ref('') | 176 | const memId = ref('') |
| 177 | const detailForm = ref({}) | ||
| 178 | const photoList = ref([]) | ||
| 116 | const app = getApp(); | 179 | const app = getApp(); |
| 117 | const form = ref({ | 180 | const form = ref({ |
| 118 | flag: '1', | 181 | flag: '1', |
| ... | @@ -145,6 +208,15 @@ onLoad((options) => { | ... | @@ -145,6 +208,15 @@ onLoad((options) => { |
| 145 | 208 | ||
| 146 | } | 209 | } |
| 147 | userType.value = app.globalData.userType | 210 | userType.value = app.globalData.userType |
| 211 | if (options.item) { | ||
| 212 | try { | ||
| 213 | const itemData = JSON.parse(decodeURIComponent(options.item)) | ||
| 214 | detailForm.value = itemData | ||
| 215 | photoList.value = normalizePhotos(itemData.photos) | ||
| 216 | } catch (e) { | ||
| 217 | console.error('解析审核详情失败', e) | ||
| 218 | } | ||
| 219 | } | ||
| 148 | console.log(userType.value) | 220 | console.log(userType.value) |
| 149 | }) | 221 | }) |
| 150 | 222 | ||
| ... | @@ -165,6 +237,49 @@ async function getExaminer() { | ... | @@ -165,6 +237,49 @@ async function getExaminer() { |
| 165 | list.value = res.rows | 237 | list.value = res.rows |
| 166 | } | 238 | } |
| 167 | 239 | ||
| 240 | function normalizePhotos(photos) { | ||
| 241 | if (!photos) return [] | ||
| 242 | const list = Array.isArray(photos) ? photos : String(photos).split(',') | ||
| 243 | return list | ||
| 244 | .map(item => String(item || '').trim()) | ||
| 245 | .filter(Boolean) | ||
| 246 | .map(item => fillImgUrl(item)) | ||
| 247 | } | ||
| 248 | |||
| 249 | function previewPhoto(index) { | ||
| 250 | uni.previewImage({ | ||
| 251 | current: photoList.value[index], | ||
| 252 | urls: photoList.value | ||
| 253 | }) | ||
| 254 | } | ||
| 255 | |||
| 256 | function getStatusText(status) { | ||
| 257 | const statusMap = {1: '审核中', 2: '审核通过', 3: '审核拒绝'} | ||
| 258 | return statusMap[status] || '-' | ||
| 259 | } | ||
| 260 | |||
| 261 | function getStatusClass(status) { | ||
| 262 | const classMap = { | ||
| 263 | 1: 'text-warning', | ||
| 264 | 2: 'text-success', | ||
| 265 | 3: 'text-danger' | ||
| 266 | } | ||
| 267 | return classMap[status] || '' | ||
| 268 | } | ||
| 269 | |||
| 270 | function getCurrentAuditStatus() { | ||
| 271 | return userType.value == 1 ? detailForm.value.auditStatus : detailForm.value.shenAuditStatus | ||
| 272 | } | ||
| 273 | |||
| 274 | function getCurrentAuditTime() { | ||
| 275 | return userType.value == 1 ? detailForm.value.auditTime : detailForm.value.shenAuditTime | ||
| 276 | } | ||
| 277 | |||
| 278 | function formatDate(dateStr) { | ||
| 279 | if (!dateStr) return '-' | ||
| 280 | return String(dateStr).substring(0, 10) | ||
| 281 | } | ||
| 282 | |||
| 168 | 283 | ||
| 169 | function doSubmit() { | 284 | function doSubmit() { |
| 170 | if (form.value.flag == '0' && !form.value.reason) { | 285 | if (form.value.flag == '0' && !form.value.reason) { |
| ... | @@ -272,7 +387,8 @@ async function confirmDel() { | ... | @@ -272,7 +387,8 @@ async function confirmDel() { |
| 272 | } | 387 | } |
| 273 | } | 388 | } |
| 274 | 389 | ||
| 275 | .form-section { | 390 | .form-section, |
| 391 | .detail-section { | ||
| 276 | background-color: #fff; | 392 | background-color: #fff; |
| 277 | border-radius: 16rpx; | 393 | border-radius: 16rpx; |
| 278 | padding: 30rpx; | 394 | padding: 30rpx; |
| ... | @@ -292,6 +408,73 @@ async function confirmDel() { | ... | @@ -292,6 +408,73 @@ async function confirmDel() { |
| 292 | } | 408 | } |
| 293 | } | 409 | } |
| 294 | 410 | ||
| 411 | .info-card { | ||
| 412 | .info-row { | ||
| 413 | display: flex; | ||
| 414 | justify-content: space-between; | ||
| 415 | padding: 16rpx 0; | ||
| 416 | border-bottom: 1px solid #f0f0f0; | ||
| 417 | |||
| 418 | &:last-child { | ||
| 419 | border-bottom: none; | ||
| 420 | } | ||
| 421 | |||
| 422 | .label { | ||
| 423 | font-size: 26rpx; | ||
| 424 | color: #999; | ||
| 425 | flex-shrink: 0; | ||
| 426 | } | ||
| 427 | |||
| 428 | .value { | ||
| 429 | flex: 1; | ||
| 430 | font-size: 26rpx; | ||
| 431 | color: #333; | ||
| 432 | text-align: right; | ||
| 433 | margin-left: 20rpx; | ||
| 434 | word-break: break-all; | ||
| 435 | |||
| 436 | &.text-success { | ||
| 437 | color: #4caf50; | ||
| 438 | } | ||
| 439 | |||
| 440 | &.text-warning { | ||
| 441 | color: #ff9800; | ||
| 442 | } | ||
| 443 | |||
| 444 | &.text-danger { | ||
| 445 | color: #f44336; | ||
| 446 | } | ||
| 447 | } | ||
| 448 | } | ||
| 449 | } | ||
| 450 | |||
| 451 | .photo-list { | ||
| 452 | display: flex; | ||
| 453 | flex-wrap: wrap; | ||
| 454 | gap: 18rpx; | ||
| 455 | } | ||
| 456 | |||
| 457 | .venue-block { | ||
| 458 | padding-top: 22rpx; | ||
| 459 | } | ||
| 460 | |||
| 461 | .venue-title { | ||
| 462 | display: flex; | ||
| 463 | align-items: center; | ||
| 464 | gap: 8rpx; | ||
| 465 | margin-bottom: 18rpx; | ||
| 466 | font-size: 28rpx; | ||
| 467 | font-weight: 600; | ||
| 468 | color: #333; | ||
| 469 | } | ||
| 470 | |||
| 471 | .venue-photo { | ||
| 472 | width: 204rpx; | ||
| 473 | height: 204rpx; | ||
| 474 | border-radius: 14rpx; | ||
| 475 | background: #f5f5f5; | ||
| 476 | } | ||
| 477 | |||
| 295 | .form-card { | 478 | .form-card { |
| 296 | .form-item { | 479 | .form-item { |
| 297 | margin-bottom: 30rpx; | 480 | margin-bottom: 30rpx; | ... | ... |
| ... | @@ -43,6 +43,24 @@ | ... | @@ -43,6 +43,24 @@ |
| 43 | </view> | 43 | </view> |
| 44 | </view> | 44 | </view> |
| 45 | </view> | 45 | </view> |
| 46 | |||
| 47 | <!-- 场馆照片 --> | ||
| 48 | <view v-if="photoList.length > 0" class="section"> | ||
| 49 | <view class="section-header"> | ||
| 50 | <uni-icons color="#AD181F" size="18" type="image"></uni-icons> | ||
| 51 | <text class="section-title">场馆照片</text> | ||
| 52 | </view> | ||
| 53 | <view class="photo-list"> | ||
| 54 | <image | ||
| 55 | v-for="(item, index) in photoList" | ||
| 56 | :key="item" | ||
| 57 | class="venue-photo" | ||
| 58 | :src="item" | ||
| 59 | mode="aspectFill" | ||
| 60 | @click="previewPhoto(index)" | ||
| 61 | /> | ||
| 62 | </view> | ||
| 63 | </view> | ||
| 46 | 64 | ||
| 47 | <!-- 审核记录 --> | 65 | <!-- 审核记录 --> |
| 48 | <view v-if="auditList.length > 0" class="section"> | 66 | <view v-if="auditList.length > 0" class="section"> |
| ... | @@ -94,6 +112,7 @@ | ... | @@ -94,6 +112,7 @@ |
| 94 | 112 | ||
| 95 | <script setup> | 113 | <script setup> |
| 96 | import * as api from '@/common/api_exam.js' | 114 | import * as api from '@/common/api_exam.js' |
| 115 | import { fillImgUrl } from '@/common/utils.js' | ||
| 97 | import {ref} from 'vue' | 116 | import {ref} from 'vue' |
| 98 | import {onLoad} from '@dcloudio/uni-app' | 117 | import {onLoad} from '@dcloudio/uni-app' |
| 99 | 118 | ||
| ... | @@ -101,6 +120,7 @@ const app = getApp() | ... | @@ -101,6 +120,7 @@ const app = getApp() |
| 101 | const form = ref({}) | 120 | const form = ref({}) |
| 102 | const auditList = ref([]) | 121 | const auditList = ref([]) |
| 103 | const examinerList = ref([]) | 122 | const examinerList = ref([]) |
| 123 | const photoList = ref([]) | ||
| 104 | const userType = ref('') | 124 | const userType = ref('') |
| 105 | const auditStatusMap = {1: '审核中', 2: '审核通过', 3: '审核拒绝'} | 125 | const auditStatusMap = {1: '审核中', 2: '审核通过', 3: '审核拒绝'} |
| 106 | 126 | ||
| ... | @@ -113,6 +133,7 @@ onLoad((options) => { | ... | @@ -113,6 +133,7 @@ onLoad((options) => { |
| 113 | if (itemData.auditLogs) { | 133 | if (itemData.auditLogs) { |
| 114 | auditList.value = JSON.parse(itemData.auditLogs) | 134 | auditList.value = JSON.parse(itemData.auditLogs) |
| 115 | } | 135 | } |
| 136 | photoList.value = normalizePhotos(itemData.photos) | ||
| 116 | if (itemData.memId) { | 137 | if (itemData.memId) { |
| 117 | getExaminerList(itemData.memId) | 138 | getExaminerList(itemData.memId) |
| 118 | } | 139 | } |
| ... | @@ -145,6 +166,22 @@ function getStatusClass(status) { | ... | @@ -145,6 +166,22 @@ function getStatusClass(status) { |
| 145 | return classMap[status] || '' | 166 | return classMap[status] || '' |
| 146 | } | 167 | } |
| 147 | 168 | ||
| 169 | function normalizePhotos(photos) { | ||
| 170 | if (!photos) return [] | ||
| 171 | const list = Array.isArray(photos) ? photos : String(photos).split(',') | ||
| 172 | return list | ||
| 173 | .map(item => String(item || '').trim()) | ||
| 174 | .filter(Boolean) | ||
| 175 | .map(item => fillImgUrl(item)) | ||
| 176 | } | ||
| 177 | |||
| 178 | function previewPhoto(index) { | ||
| 179 | uni.previewImage({ | ||
| 180 | current: index, | ||
| 181 | urls: photoList.value | ||
| 182 | }) | ||
| 183 | } | ||
| 184 | |||
| 148 | function getCurrentAuditStatus() { | 185 | function getCurrentAuditStatus() { |
| 149 | return userType.value == 1 ? form.value.auditStatus : form.value.shenAuditStatus | 186 | return userType.value == 1 ? form.value.auditStatus : form.value.shenAuditStatus |
| 150 | } | 187 | } |
| ... | @@ -282,6 +319,19 @@ function formatDateTime(dateStr) { | ... | @@ -282,6 +319,19 @@ function formatDateTime(dateStr) { |
| 282 | } | 319 | } |
| 283 | } | 320 | } |
| 284 | 321 | ||
| 322 | .photo-list { | ||
| 323 | display: flex; | ||
| 324 | flex-wrap: wrap; | ||
| 325 | gap: 18rpx; | ||
| 326 | } | ||
| 327 | |||
| 328 | .venue-photo { | ||
| 329 | width: 204rpx; | ||
| 330 | height: 204rpx; | ||
| 331 | border-radius: 14rpx; | ||
| 332 | background: #f5f5f5; | ||
| 333 | } | ||
| 334 | |||
| 285 | 335 | ||
| 286 | /* 考官表格 */ | 336 | /* 考官表格 */ |
| 287 | .examiner-table { | 337 | .examiner-table { | ... | ... |
| ... | @@ -339,10 +339,9 @@ function goView(item) { | ... | @@ -339,10 +339,9 @@ function goView(item) { |
| 339 | } | 339 | } |
| 340 | 340 | ||
| 341 | function goAudit(item) { | 341 | function goAudit(item) { |
| 342 | 342 | const itemStr = encodeURIComponent(JSON.stringify(item)) | |
| 343 | // const itemStr = encodeURIComponent(JSON.stringify(item)) | ||
| 344 | uni.navigateTo({ | 343 | uni.navigateTo({ |
| 345 | url: `/level/ztx/examinationAudit?ids=${item.id}&type=single&selfSelect=${item.selfSelect}&memId=${item.memId}` | 344 | url: `/level/ztx/examinationAudit?ids=${item.id}&type=single&selfSelect=${item.selfSelect}&memId=${item.memId}&item=${itemStr}` |
| 346 | }) | 345 | }) |
| 347 | } | 346 | } |
| 348 | 347 | ... | ... |
| ... | @@ -92,7 +92,8 @@ function handleAdd() { | ... | @@ -92,7 +92,8 @@ function handleAdd() { |
| 92 | const ids = selectedIds.value.join(',') | 92 | const ids = selectedIds.value.join(',') |
| 93 | 93 | ||
| 94 | uni.showLoading({title: '添加中...'}) | 94 | uni.showLoading({title: '添加中...'}) |
| 95 | api.selfAdd(ids).then(() => { | 95 | const request = memId.value ? api.otherAdd(memId.value, ids) : api.selfAdd(ids) |
| 96 | request.then(() => { | ||
| 96 | uni.hideLoading() | 97 | uni.hideLoading() |
| 97 | uni.showToast({title: '添加成功', icon: 'success'}) | 98 | uni.showToast({title: '添加成功', icon: 'success'}) |
| 98 | uni.navigateBack() | 99 | uni.navigateBack() | ... | ... |
| ... | @@ -21,12 +21,17 @@ | ... | @@ -21,12 +21,17 @@ |
| 21 | 21 | ||
| 22 | <!-- 温馨提示 --> | 22 | <!-- 温馨提示 --> |
| 23 | <view class="tip-box"> | 23 | <view class="tip-box"> |
| 24 | <text class="tip-text">温馨提示: | 24 | <view class="tip-text">温馨提示: |
| 25 | 根据中国跆拳道协会考点管理办法请添加考点考官 | 25 | </view> |
| 26 | <view class="tip-text"> | ||
| 27 | 根据中国跆拳道协会考点管理办法请添加考点考官。 | ||
| 28 | </view> | ||
| 29 | <view class="tip-text"> | ||
| 26 | 如若已有考官:点击【录入考官信息】,根据相关信息填写考官资料进行录入。 | 30 | 如若已有考官:点击【录入考官信息】,根据相关信息填写考官资料进行录入。 |
| 27 | 如若没有考官:点击【申请省跆协指派考官】,选择省内相关考官并及时参加考官培训 | 31 | |
| 28 | 完成考官设置后,才能继续提交考点申报。请您尽快操作,以免影响后续考试安排。 | 32 | </view> |
| 29 | </text> | 33 | <view class="tip-text">如若没有考官:点击【申请省跆协指派考官】,选择省内相关考官并及时参加考官培训 |
| 34 | 完成考官设置后,才能继续提交考点申报。请您尽快操作,以免影响后续考试安排。</view> | ||
| 30 | </view> | 35 | </view> |
| 31 | 36 | ||
| 32 | <!-- 省跆协指派提示 --> | 37 | <!-- 省跆协指派提示 --> |
| ... | @@ -142,7 +147,14 @@ let modalAction = '' // 'del', 'success', 'assign', 'apply' | ... | @@ -142,7 +147,14 @@ let modalAction = '' // 'del', 'success', 'assign', 'apply' |
| 142 | let pendingDelItem = null | 147 | let pendingDelItem = null |
| 143 | 148 | ||
| 144 | onLoad((option) => { | 149 | onLoad((option) => { |
| 145 | // memId.value = app.globalData.memberInfo.memId | 150 | memId.value = option.memId || app.globalData.memberInfo?.memId || '' |
| 151 | if (option.photos) { | ||
| 152 | try { | ||
| 153 | form.value.photos = JSON.parse(decodeURIComponent(option.photos)) | ||
| 154 | } catch (e) { | ||
| 155 | form.value.photos = [] | ||
| 156 | } | ||
| 157 | } | ||
| 146 | getExaminer() | 158 | getExaminer() |
| 147 | }) | 159 | }) |
| 148 | 160 | ||
| ... | @@ -155,7 +167,7 @@ onShow(() => { | ... | @@ -155,7 +167,7 @@ onShow(() => { |
| 155 | 167 | ||
| 156 | async function getExaminer() { | 168 | async function getExaminer() { |
| 157 | loading.value = true | 169 | loading.value = true |
| 158 | const res = await api.listApi({memId: app.globalData.memberInfo.memId}) | 170 | const res = await api.listApi({memId: memId.value || app.globalData.memberInfo?.memId}) |
| 159 | list.value = res.rows | 171 | list.value = res.rows |
| 160 | loading.value = false | 172 | loading.value = false |
| 161 | } | 173 | } |
| ... | @@ -253,7 +265,7 @@ function searchAndAdd() { | ... | @@ -253,7 +265,7 @@ function searchAndAdd() { |
| 253 | // 执行添加考官 | 265 | // 执行添加考官 |
| 254 | function doAddExaminer(row) { | 266 | function doAddExaminer(row) { |
| 255 | uni.showLoading({ title: '添加中' }) | 267 | uni.showLoading({ title: '添加中' }) |
| 256 | api.selfAdd(row.perId).then(() => { | 268 | api.otherAdd(memId.value || app.globalData.memberInfo?.memId, row.perId).then(() => { |
| 257 | uni.hideLoading() | 269 | uni.hideLoading() |
| 258 | uni.showToast({ title: '添加成功', icon: 'success' }) | 270 | uni.showToast({ title: '添加成功', icon: 'success' }) |
| 259 | addPopup.value.close() | 271 | addPopup.value.close() |
| ... | @@ -266,6 +278,12 @@ function doAddExaminer(row) { | ... | @@ -266,6 +278,12 @@ function doAddExaminer(row) { |
| 266 | 278 | ||
| 267 | // 提交申请 | 279 | // 提交申请 |
| 268 | async function handelSubmit() { | 280 | async function handelSubmit() { |
| 281 | if (!form.value.photos || form.value.photos.length === 0) { | ||
| 282 | return uni.showToast({title: '请先上传场馆照片', icon: 'none'}) | ||
| 283 | } | ||
| 284 | if (Array.isArray(form.value.photos)) { | ||
| 285 | form.value.photos = form.value.photos.filter(Boolean).join(',') | ||
| 286 | } | ||
| 269 | if (!form.value.selfSelect) { | 287 | if (!form.value.selfSelect) { |
| 270 | return uni.showToast({title: '请选择考官类型', icon: 'none'}) | 288 | return uni.showToast({title: '请选择考官类型', icon: 'none'}) |
| 271 | } | 289 | } | ... | ... |
| ... | @@ -161,6 +161,13 @@ | ... | @@ -161,6 +161,13 @@ |
| 161 | } | 161 | } |
| 162 | }, | 162 | }, |
| 163 | { | 163 | { |
| 164 | "path": "pages/index/examPointVenueImage", | ||
| 165 | "style": { | ||
| 166 | "navigationBarTitleText": "场馆照片", | ||
| 167 | "enablePullDownRefresh": false | ||
| 168 | } | ||
| 169 | }, | ||
| 170 | { | ||
| 164 | "path": "pages/index/orderList", | 171 | "path": "pages/index/orderList", |
| 165 | "style": { | 172 | "style": { |
| 166 | "navigationBarTitleText": "订单列表", | 173 | "navigationBarTitleText": "订单列表", | ... | ... |
pages/index/examPointVenueImage.vue
0 → 100644
| 1 | <template> | ||
| 2 | <view class="venue-page"> | ||
| 3 | <view class="content-card"> | ||
| 4 | <view class="title">上传场馆照片</view> | ||
| 5 | <view class="desc">请上传 1~3 张清晰的场馆照片,照片将作为考点申请材料提交审核。</view> | ||
| 6 | |||
| 7 | <view class="photo-grid"> | ||
| 8 | <view | ||
| 9 | v-for="(item, index) in photoList" | ||
| 10 | :key="item.url" | ||
| 11 | class="photo-item" | ||
| 12 | > | ||
| 13 | <image class="photo" :src="item.previewUrl" mode="aspectFill" @click="previewPhoto(index)" /> | ||
| 14 | <view class="delete-btn" @click.stop="deletePhoto(index)">×</view> | ||
| 15 | </view> | ||
| 16 | <view v-if="photoList.length < 3" class="upload-card" @click="choosePhoto"> | ||
| 17 | <view class="plus">+</view> | ||
| 18 | <view class="upload-text">添加照片</view> | ||
| 19 | </view> | ||
| 20 | </view> | ||
| 21 | |||
| 22 | <view class="tip">最多上传 3 张,支持从相册选择或拍照上传。</view> | ||
| 23 | </view> | ||
| 24 | |||
| 25 | <view class="footer"> | ||
| 26 | <button class="back-btn" @click="goBack">上一步</button> | ||
| 27 | <button class="next-btn" @click="goNext">下一步</button> | ||
| 28 | </view> | ||
| 29 | </view> | ||
| 30 | </template> | ||
| 31 | |||
| 32 | <script setup> | ||
| 33 | import { ref } from 'vue' | ||
| 34 | import { onLoad } from '@dcloudio/uni-app' | ||
| 35 | import * as api from '@/common/api.js' | ||
| 36 | import { fillImgUrl } from '@/common/utils.js' | ||
| 37 | |||
| 38 | const photoList = ref([]) | ||
| 39 | const memId = ref('') | ||
| 40 | |||
| 41 | onLoad((option) => { | ||
| 42 | memId.value = option.memId || '' | ||
| 43 | }) | ||
| 44 | |||
| 45 | function choosePhoto() { | ||
| 46 | const count = 3 - photoList.value.length | ||
| 47 | if (count <= 0) return | ||
| 48 | uni.chooseImage({ | ||
| 49 | count, | ||
| 50 | sizeType: ['compressed'], | ||
| 51 | sourceType: ['album', 'camera'], | ||
| 52 | success: async (res) => { | ||
| 53 | const paths = res.tempFilePaths || [] | ||
| 54 | for (const path of paths) { | ||
| 55 | if (photoList.value.length >= 3) break | ||
| 56 | await uploadPhoto(path) | ||
| 57 | } | ||
| 58 | } | ||
| 59 | }) | ||
| 60 | } | ||
| 61 | |||
| 62 | async function uploadPhoto(path) { | ||
| 63 | if (!path) return | ||
| 64 | try { | ||
| 65 | uni.showLoading({ title: '上传中', mask: true }) | ||
| 66 | const res = await api.uploadImgCorpPhoto(path) | ||
| 67 | const url = getUploadUrl(res) | ||
| 68 | if (!url) { | ||
| 69 | uni.showToast({ title: '上传返回数据异常', icon: 'none' }) | ||
| 70 | return | ||
| 71 | } | ||
| 72 | photoList.value.push({ | ||
| 73 | url, | ||
| 74 | previewUrl: fillImgUrl(url) | ||
| 75 | }) | ||
| 76 | } catch (err) { | ||
| 77 | uni.showToast({ title: '上传失败,请重新上传', icon: 'none' }) | ||
| 78 | } finally { | ||
| 79 | uni.hideLoading() | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | function getUploadUrl(res) { | ||
| 84 | const data = res?.data | ||
| 85 | if (typeof data === 'string') return data | ||
| 86 | return data?.ms || data?.url || data?.fang || res?.msg || '' | ||
| 87 | } | ||
| 88 | |||
| 89 | function deletePhoto(index) { | ||
| 90 | photoList.value.splice(index, 1) | ||
| 91 | } | ||
| 92 | |||
| 93 | function previewPhoto(index) { | ||
| 94 | uni.previewImage({ | ||
| 95 | current: index, | ||
| 96 | urls: photoList.value.map(item => item.previewUrl) | ||
| 97 | }) | ||
| 98 | } | ||
| 99 | |||
| 100 | function goNext() { | ||
| 101 | if (photoList.value.length === 0) { | ||
| 102 | uni.showToast({ title: '请上传1~3张场馆照片', icon: 'none' }) | ||
| 103 | return | ||
| 104 | } | ||
| 105 | const photos = encodeURIComponent(JSON.stringify(photoList.value.map(item => item.url))) | ||
| 106 | uni.navigateTo({ | ||
| 107 | url: `/myCenter/examPointApply?photos=${photos}&memId=${memId.value || ''}` | ||
| 108 | }) | ||
| 109 | } | ||
| 110 | |||
| 111 | function goBack() { | ||
| 112 | uni.navigateBack({ delta: 1 }) | ||
| 113 | } | ||
| 114 | </script> | ||
| 115 | |||
| 116 | <style lang="scss" scoped> | ||
| 117 | .venue-page { | ||
| 118 | min-height: 100vh; | ||
| 119 | display: flex; | ||
| 120 | flex-direction: column; | ||
| 121 | background: #f5f5f5; | ||
| 122 | } | ||
| 123 | |||
| 124 | .content-card { | ||
| 125 | flex: 1; | ||
| 126 | margin: 30rpx; | ||
| 127 | padding: 36rpx; | ||
| 128 | background: #fff; | ||
| 129 | border-radius: 18rpx; | ||
| 130 | } | ||
| 131 | |||
| 132 | .title { | ||
| 133 | font-size: 34rpx; | ||
| 134 | font-weight: 600; | ||
| 135 | color: #222; | ||
| 136 | } | ||
| 137 | |||
| 138 | .desc { | ||
| 139 | margin-top: 18rpx; | ||
| 140 | color: #777; | ||
| 141 | font-size: 26rpx; | ||
| 142 | line-height: 1.6; | ||
| 143 | } | ||
| 144 | |||
| 145 | .photo-grid { | ||
| 146 | display: flex; | ||
| 147 | flex-wrap: wrap; | ||
| 148 | gap: 22rpx; | ||
| 149 | margin-top: 36rpx; | ||
| 150 | } | ||
| 151 | |||
| 152 | .photo-item, | ||
| 153 | .upload-card { | ||
| 154 | position: relative; | ||
| 155 | width: 196rpx; | ||
| 156 | height: 196rpx; | ||
| 157 | border-radius: 16rpx; | ||
| 158 | overflow: hidden; | ||
| 159 | } | ||
| 160 | |||
| 161 | .photo { | ||
| 162 | width: 100%; | ||
| 163 | height: 100%; | ||
| 164 | } | ||
| 165 | |||
| 166 | .delete-btn { | ||
| 167 | position: absolute; | ||
| 168 | top: 8rpx; | ||
| 169 | right: 8rpx; | ||
| 170 | width: 42rpx; | ||
| 171 | height: 42rpx; | ||
| 172 | line-height: 38rpx; | ||
| 173 | text-align: center; | ||
| 174 | border-radius: 50%; | ||
| 175 | color: #fff; | ||
| 176 | background: #C4121B; | ||
| 177 | font-size: 34rpx; | ||
| 178 | } | ||
| 179 | |||
| 180 | .upload-card { | ||
| 181 | display: flex; | ||
| 182 | flex-direction: column; | ||
| 183 | align-items: center; | ||
| 184 | justify-content: center; | ||
| 185 | border: 2rpx dashed #d7d7d7; | ||
| 186 | background: #fafafa; | ||
| 187 | } | ||
| 188 | |||
| 189 | .plus { | ||
| 190 | color: #C4121B; | ||
| 191 | font-size: 58rpx; | ||
| 192 | line-height: 1; | ||
| 193 | } | ||
| 194 | |||
| 195 | .upload-text { | ||
| 196 | margin-top: 12rpx; | ||
| 197 | color: #777; | ||
| 198 | font-size: 24rpx; | ||
| 199 | } | ||
| 200 | |||
| 201 | .tip { | ||
| 202 | margin-top: 26rpx; | ||
| 203 | color: #999; | ||
| 204 | font-size: 24rpx; | ||
| 205 | } | ||
| 206 | |||
| 207 | .footer { | ||
| 208 | padding: 30rpx; | ||
| 209 | display: flex; | ||
| 210 | justify-content: space-between; | ||
| 211 | background: #fff; | ||
| 212 | box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05); | ||
| 213 | } | ||
| 214 | |||
| 215 | .back-btn, | ||
| 216 | .next-btn { | ||
| 217 | width: 48%; | ||
| 218 | height: 88rpx; | ||
| 219 | line-height: 88rpx; | ||
| 220 | border-radius: 44rpx; | ||
| 221 | font-size: 32rpx; | ||
| 222 | } | ||
| 223 | |||
| 224 | .back-btn { | ||
| 225 | background: #fff; | ||
| 226 | color: #C4121B; | ||
| 227 | border: 1rpx solid #C4121B; | ||
| 228 | } | ||
| 229 | |||
| 230 | .next-btn { | ||
| 231 | background: #C4121B; | ||
| 232 | color: #fff; | ||
| 233 | border: none; | ||
| 234 | } | ||
| 235 | </style> |
| ... | @@ -50,9 +50,18 @@ | ... | @@ -50,9 +50,18 @@ |
| 50 | </template> | 50 | </template> |
| 51 | 51 | ||
| 52 | <script setup> | 52 | <script setup> |
| 53 | import { ref } from 'vue' | ||
| 54 | import { onLoad } from '@dcloudio/uni-app' | ||
| 55 | |||
| 56 | const memId = ref('') | ||
| 57 | |||
| 58 | onLoad((option) => { | ||
| 59 | memId.value = option.memId || '' | ||
| 60 | }) | ||
| 61 | |||
| 53 | function goApply() { | 62 | function goApply() { |
| 54 | uni.navigateTo({ | 63 | uni.navigateTo({ |
| 55 | url: '/myCenter/examPointApply' | 64 | url: `/pages/index/examPointVenueImage?memId=${memId.value || ''}` |
| 56 | }) | 65 | }) |
| 57 | } | 66 | } |
| 58 | function goBack() { | 67 | function goBack() { | ... | ... |
-
Please register or sign in to post a comment