| | |
| | | <head> |
| | | <meta charset="UTF-8"> |
| | | <link rel="icon" href="/favicon.ico"> |
| | | <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| | | <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> |
| | | <title>广东省技能人才评价考务管理系统</title> |
| | | </head> |
| | | <body> |
| | |
| | | }, |
| | | watch: { |
| | | '$route.path': function(){ |
| | | let count = localStorage.getItem('refreshCount') || 0 |
| | | count = Number(count) + 1 |
| | | localStorage.setItem('refreshCount', count++) |
| | | if (isWeixin) { |
| | | getWxSignature(this.$route) |
| | | } |
| | | }, |
| | | }, |
| | | created() { |
| | | console.log('localHost') |
| | | } |
| | | } |
| | | </script> |
| | |
| | | import ReturnBtn from '@/views/main/components/ReturnBtn.vue' |
| | | import DictTag from '@/views/main/components/DictTag.vue' |
| | | import UploadBtn from '@/views/main/components/UploadBtn.vue' |
| | | |
| | | import property from '@/config/property.js' |
| | | import qxueyou from '@/config/qxueyou.js' |
| | | |
| | |
| | | hasTokens() { |
| | | return !!(this.getAccessToken() && this.getRefreshToken()); |
| | | }, |
| | | reLogin() { |
| | | const currentPath = router.currentRoute._value.path |
| | | if (currentPath.includes('/h5/')) { |
| | | router.push({ path: '/h5/login', query: router.currentRoute._value.query }) |
| | | } |
| | | } |
| | | } |
| | | let isRefreshing = false; |
| | | // 刷新 token 期间的请求队列 |
| | |
| | | return response |
| | | } |
| | | if (response.data && resultCode == '401') { |
| | | let filterUrlList = ['/system/wx/js/signature'] |
| | | if (filterUrlList.includes(response.config.url)){ return } |
| | | |
| | | if (!originalRequest._retry && tokenUtils.getRefreshToken) { |
| | | originalRequest._retry = true; |
| | | |
| | |
| | | originalRequest.headers.Authorization = newAccessToken; |
| | | return createAxios(originalRequest) |
| | | } catch (refreshError) { |
| | | console.log(refreshError) |
| | | // 刷新失败,处理队列中的请求 |
| | | refreshQueue.forEach(({ reject }) => { |
| | | reject(refreshError); |
| | | }); |
| | | refreshQueue = []; |
| | | tokenUtils.clearTokens(); |
| | | if (router.currentRoute._value.path.includes('/h5/')) { |
| | | router.push({ path: '/h5/login', query: router.currentRoute._value.query }) |
| | | } |
| | | tokenUtils.reLogin() |
| | | } finally { |
| | | isRefreshing = false; |
| | | } |
| | | } else { |
| | | tokenUtils.clearTokens(); |
| | | if (router.currentRoute._value.path.includes('/h5/')) { |
| | | router.push({ path: '/h5/login', query: router.currentRoute._value.query }) |
| | | tokenUtils.reLogin() |
| | | } |
| | | } |
| | | } |
| | | |
| | | console.log(`url-${response.config.flag} `, response.config.url, response.data) |
| | | return response |
| | | }, |
| | |
| | | > |
| | | <div class="p-7 pt-0" style="display: flex; flex-direction: column; align-items: center;"> |
| | | <div class="image_box" v-if="['unStart', 'auditing'].includes(status)"> |
| | | <el-image :src="base64"></el-image> |
| | | <el-image :src="base64" style="width: 100%;" fit="cover"></el-image> |
| | | <div v-if="status=='auditing'" class="scan-line"></div> |
| | | </div> |
| | | <el-row justify="center" v-else-if="['success', 'fail'].includes(status)"> |
| | |
| | | }, |
| | | async startCapture() { |
| | | if (isWeixin) { |
| | | const photo = await chooseImage() |
| | | this.shootSuccess('data:image/jpg;base64,' + photo) |
| | | let photo = await chooseImage() |
| | | photo = photo.startsWith('data:image') ? photo : ('data:image/jpg;base64,' + photo) |
| | | this.shootSuccess(photo) |
| | | } else { |
| | | this.openCameraFlag = true |
| | | } |
| | |
| | | const data = { |
| | | captchaVerification: '', |
| | | mobile: this.form.mobile, |
| | | scene: 21, |
| | | scene: 31, |
| | | } |
| | | this.sendCodeLoading = true |
| | | this.$axios.post('/system/auth/send-sms-code', data).then(res => { |
| | |
| | | } |
| | | }, |
| | | created() { |
| | | |
| | | tokenUtils.clearTokens() |
| | | this.loginType = isWeixin ? 'weixin' : 'mobilePhone' |
| | | if (isWeixin) { |
| | | this.loginType = 'weixin' |
| | | localStorage.removeItem('weChatRedirectCount') |
| | | this.$router.replace({ path: '/h5/redirect' }) |
| | | } |
| | | }, |
| | |
| | | const data = { |
| | | captchaVerification: '', |
| | | mobile: this.form.mobile, |
| | | scene: 21, |
| | | scene: 31, |
| | | } |
| | | this.sendCodeLoading = true |
| | | this.$axios.post('/system/auth/send-sms-code', data).then(res => { |
| | |
| | | <path d="M395.6 380.4c0 54.7 26.5 103.5 67.6 134.4-3.6 9.8-7.9 19.2-12.8 28.1-4.9 8.9-10.4 17.4-16.6 25.4-6.2 8-13.1 15.4-20.6 22.2-7.5 6.8-15.7 12.8-24.4 17.9-8.7 5.1-18 9.3-27.6 12.5-9.6 3.2-19.6 5.3-29.8 6.3-10.2 1-20.5 0.9-30.6-0.4-10.1-1.3-20-3.8-29.4-7.4-9.4-3.6-18.3-8.3-26.6-14-8.3-5.7-15.9-12.2-22.7-19.6-6.8-7.4-12.7-15.5-17.6-24.3-4.9-8.8-8.8-18.2-11.5-28-2.7-9.8-4.2-19.9-4.5-30.2-0.3-10.3 0.8-20.5 3.2-30.5 2.4-10 6.1-19.6 10.9-28.7 4.8-9.1 10.7-17.5 17.5-25.2 6.8-7.7 14.5-14.5 22.9-20.4 8.4-5.9 17.5-10.8 27.1-14.6 9.6-3.8 19.7-6.4 30-7.9 10.3-1.5 20.8-1.8 31.2-0.7 10.4 1.1 20.6 3.6 30.3 7.4 9.7 3.8 18.8 8.8 27.1 15 8.3 6.2 15.8 13.4 22.4 21.5 6.6 8.1 12.2 16.9 16.6 26.3 4.4 9.4 7.6 19.3 9.5 29.6z" fill="#07C160"/> |
| | | </svg> |
| | | </div> |
| | | <div class="sub-text"> |
| | | 12222222223333 |
| | | <div class="sub-text" v-if="!errorFlag"> |
| | | 微信授权中 |
| | | <span class="dots"> |
| | | <span class="dot"></span> |
| | |
| | | <span class="dot"></span> |
| | | </span> |
| | | </div> |
| | | <div v-else class="sub-text">授权失败</div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | |
| | | }, |
| | | data() { |
| | | return { |
| | | |
| | | redirectCount: 0, |
| | | errorMessage: '' |
| | | } |
| | | }, |
| | | watch() { |
| | |
| | | this.authSuccess() |
| | | } else { |
| | | this.redirectUrl() |
| | | this.redirectCount = localStorage.getItem('weChatRedirectCount') || 0 |
| | | this.redirectCount = Number(this.redirectCount) + 1 |
| | | localStorage.setItem('weChatRedirectCount', redirectCount) |
| | | } |
| | | }, |
| | | methods: { |
| | | redirectUrl() { |
| | | if (this.redirectCount > 1) { |
| | | this.errorFlag = true |
| | | return |
| | | } |
| | | const params = { |
| | | targetId: '', |
| | | redirectUrl: encodeURIComponent(window.location.href), |
| | |
| | | if (res.data.code == 0) { |
| | | window.location.replace(res.data.data) |
| | | } else { |
| | | this.errorFlag = true |
| | | this.$message.error(res.data.msg) |
| | | } |
| | | }) |
| | |
| | | const path = localStorage.getItem('verify_url') |
| | | if (path) { |
| | | this.$router.replace(path) |
| | | } else { |
| | | this.$router.replace('/h5/noVerAccess') |
| | | } |
| | | } else { |
| | | this.$router.replace({ |
| | |
| | | this.map = null; |
| | | } |
| | | }, |
| | | watch: { |
| | | center: { |
| | | handler: function(val) { |
| | | const newPoint = new BMapGL.Point(val.lng, val.lat); |
| | | this.map.map.setCenter(newPoint) |
| | | }, |
| | | deep: true |
| | | } |
| | | }, |
| | | methods: { |
| | | loadMap() { |
| | | loadBaiduMapScript() |
| | |
| | | centerPoint: { |
| | | lat: 23.135618, |
| | | lng: 113.27077 |
| | | } |
| | | }, |
| | | clickCount: 0 |
| | | } |
| | | }, |
| | | computed: { |
| | |
| | | } |
| | | }, |
| | | signinConfirm() { |
| | | this.clickCount++ |
| | | if (this.clickCount < 10) { |
| | | if (!this.canSignup || this.confirmLoading) { |
| | | return |
| | | } |
| | | } |
| | | const data = { |
| | | targetId: this.appId, |
| | | targetType: 2, |
| | |
| | | </el-row> |
| | | |
| | | <el-divider class="m-0" style="flex-shrink: 0;"></el-divider> |
| | | <el-scrollbar :height="`${mainHeight}px`" class="p-2 m-0 mt-1" > |
| | | <el-scrollbar :height="`${mainHeight}px`" class="p-2 m-0 mt-1" min-size="none"> |
| | | <div v-if="pdfUrl" :style="{width: '100%', height: `${mainHeight - 100}px`}"> |
| | | <PdfPreview v-if="pdfUrl" :url="pdfUrl"></PdfPreview> |
| | | </div> |
| | | <el-text class="ml-2 text-info">考点申报文件加载失败...</el-text> |
| | | <el-text v-if="pdfUrlError" class="ml-2 text-info">考点申报文件加载失败...</el-text> |
| | | <div class="p-2 my-4"> |
| | | <el-form ref="verifyForm" :model="form"> |
| | | <el-form-item label="*以上申报内容是否属实" prop="isVerified"> |
| | |
| | | </el-form-item> |
| | | <el-row><el-text>*现场工作照片</el-text></el-row> |
| | | <el-row> |
| | | <UploadBtn v-model="form.image" :disabled="isVerified" :accept="['pdf', 'jpg']" :limitFileCount="10" listType="picture-card"></UploadBtn> |
| | | <UploadBtn |
| | | v-model="form.image" |
| | | :disabled="isVerified" |
| | | :accept="['pdf', 'jpg']" |
| | | :limitFileCount="10" |
| | | listType="picture-card" |
| | | ></UploadBtn> |
| | | </el-row> |
| | | |
| | | <Signature v-model="form.signatureUrl" :disabled="isVerified" :isRequire="true"></Signature> |
| | |
| | | type="primary" size="large" |
| | | class="my-7" style="width: 100%;" |
| | | :loading="submitLoading" |
| | | >提交核验结果</el-button> |
| | | >提交核验结果 |
| | | </el-button> |
| | | <el-button |
| | | v-if="isVerified" |
| | | disabled |
| | | type="primary" size="large" |
| | | class="my-7" style="width: 100%;" |
| | | >核验结果已提交 |
| | | </el-button> |
| | | </el-form> |
| | | </div> |
| | | </el-scrollbar> |
| | |
| | | }, |
| | | isVerified: false, |
| | | saveLoading: false, |
| | | submitLoading: false |
| | | submitLoading: false, |
| | | pdfUrlError: false |
| | | } |
| | | }, |
| | | computed: { |
| | |
| | | this.form.signatureUrl = resData.signatureUrl |
| | | this.isVerified = resData.isVerified |
| | | } |
| | | if (!this.pdfUrl) { |
| | | this.pdfUrlError = false |
| | | } |
| | | } else { |
| | | this.$message.error('获取核验信息失败') |
| | | } |
| | |
| | | this.$router.replace('/h5/noVerAccess') |
| | | return |
| | | } |
| | | const checkinExist = await this.getCheckinExist() |
| | | if (checkinExist) { |
| | | const getCheckIsSubmit = await this.getCheckIsSubmit() |
| | | if (getCheckIsSubmit) { |
| | | this.$router.replace({ path: '/h5/verForm', query: { appId: this.appId }}) |
| | | } else { |
| | | this.$router.replace({ path: '/h5/face', query: { appId: this.appId }}) |
| | |
| | | }) |
| | | }) |
| | | }, |
| | | getCheckIsSubmit() { |
| | | return new Promise((resolve) => { |
| | | const params = { applicationId: this.appId } |
| | | this.$axios.get('/exam/verify-record/get-by-application-id', { params }).then(res => { |
| | | if (res.data.code == 0) { |
| | | resolve(res.data.data.isVerified) |
| | | } else { |
| | | resolve(false) |
| | | } |
| | | }, () => { |
| | | resolve(false) |
| | | }) |
| | | }) |
| | | }, |
| | | getCheckinExist() { |
| | | return new Promise((resolve) => { |
| | | const params = { |
| | |
| | | :src="file.url.includes('http') ? file.url : $qxueyou.qxyRes + file.url" |
| | | :initial-index="initialPreviewImgIndex" |
| | | :preview-src-list="filterPreviewImgList" |
| | | fit="cover" |
| | | style="width: 100%;" |
| | | > |
| | | </el-image> |
| | | <span class="el-upload-list__item-actions"> |
| | |
| | | return this.limitFileCount == 1 && this.list.length == 1 |
| | | }, |
| | | filterPreviewImgList() { |
| | | let list = this.list.map(ele => ele.url ) |
| | | let list = this.list.map(ele => ele.url.includes('http') ? ele.url : this.$qxueyou.qxyRes + ele.url ) |
| | | return list |
| | | }, |
| | | hideUpload() { |
| | |
| | | <template #file="{ file, index }"> |
| | | <el-image |
| | | ref="previewImg" |
| | | :src="file.url" |
| | | :src="file.url?.includes('http') ? file.url : $qxueyou.qxyRes + file.url" |
| | | :initial-index="initialPreviewImgIndex" |
| | | :preview-src-list="filterPreviewImgList" |
| | | fit="cover" |
| | | style="width: 100%;" |
| | | > |
| | | </el-image> |
| | | <span class="el-upload-list__item-actions"> |
| | | <span @click="previewImage(index)"> |
| | | <el-icon><zoom-in /></el-icon> |
| | | </span> |
| | | <!-- <span @click="replaceUpload(index)"> |
| | | <el-icon><upload /></el-icon> |
| | | </span> --> |
| | | <span @click="deleteFileItem(index)"> |
| | | <el-icon><delete /></el-icon> |
| | | </span> |
| | |
| | | return this.limitFileCount == 1 && this.list.length == 1 |
| | | }, |
| | | filterPreviewImgList() { |
| | | let list = this.list.map(ele => ele.url ) |
| | | let list = this.list.map(ele => ele.url?.includes('http') ? ele.url : $qxueyou.qxyRes + ele.url ) |
| | | return list |
| | | }, |
| | | hideUpload() { |
| | |
| | | import { defineConfig } from 'vite' |
| | | import vue from '@vitejs/plugin-vue' |
| | | import vueDevTools from 'vite-plugin-vue-devtools' |
| | | |
| | | const timestamp = new Date().getTime() |
| | | // https://vite.dev/config/ |
| | | export default defineConfig({ |
| | | base: '/examination/user', |
| | | plugins: [vue(), vueDevTools()], |
| | | define: { |
| | | // 注入构建时间戳到代码中 |
| | | '__BUILD_TIME__': JSON.stringify(timestamp) |
| | | }, |
| | | rollupOptions: { |
| | | output: { |
| | | // 在文件名中加入时间戳,确保每次构建都不同 |
| | | entryFileNames: `assets/js/[name]-[hash]-${timestamp}.js`, |
| | | chunkFileNames: `assets/js/[name]-[hash]-${timestamp}.js`, |
| | | assetFileNames: `assets/[ext]/[name]-[hash]-${timestamp}.[ext]` |
| | | } |
| | | }, |
| | | resolve: { |
| | | alias: { |
| | | '@': fileURLToPath(new URL('./src', import.meta.url)), |