yearning
23 小时以前 1d37c375fd114212ee1419c3bbdadc81d76666a4
优化
18个文件已修改
268 ■■■■■ 已修改文件
index.html 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/App.vue 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/h5/router.js 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/UA.js 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/axios.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/tool.js 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/wxjssdk.js 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/h5/faceAuth/components/auditDialog.vue 80 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/h5/faceAuth/index.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/h5/index.vue 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/h5/login/bind.vue 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/h5/login/redirect.vue 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/h5/map/BaiduMap.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/h5/map/index.vue 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/h5/noTask/index.vue 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vite.config.js 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
index.html
@@ -4,7 +4,7 @@
    <meta charset="UTF-8">
    <link rel="icon" href="/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>广东省技能人才评价考务管理系统</title>
    <title>广东技能人才评价考务管理服务</title>
  </head>
  <body>
    <div id="app"></div>
src/App.vue
@@ -5,23 +5,17 @@
</template>
<script>
import { isWeixin } from '@/utils/UA.js'
import { getWxSignature } from '@/utils/wxjssdk.js'
export default {
  data() {
    return {}
  },
  watch: {
    '$route.path': function(){
      let count = localStorage.getItem('refreshCount') || 0
      count = Number(count) + 1
      localStorage.setItem('refreshCount', count++)
      if (isWeixin) {
        getWxSignature(this.$route)
      }
    },
  },
  created() {}
    '$route': function() {
      getWxSignature()
    }
  }
}
</script>
src/main.js
@@ -27,10 +27,16 @@
// ?qxydebug2=true 触发
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.get('qxydebug2') === 'true') {
  localStorage.setItem('debug2', 'true')
}
if (localStorage.getItem('debug2') == 'true') {
  import('vconsole').then((module) => {
    new module.default();
  });
}
//  import('vconsole').then((module) => {
//     new module.default();
//   });
app.config.globalProperties.$rules = ruleGenerator
app.config.globalProperties.$property = property
src/router/h5/router.js
@@ -26,11 +26,6 @@
        component: () => import('@/views/h5/addrVerify/form.vue'),
      },
      {
        path: 'noTask',
        name: '暂无任务',
        component: () => import('@/views/h5/noTask/index.vue'),
      },
      {
        path: 'map',
        name: '签到',
        component: () => import('@/views/h5/map/index.vue'),
@@ -48,6 +43,11 @@
    ],
  },
  {
    path: '/h5/noTask',
    name: '暂无任务',
    component: () => import('@/views/h5/noTask/index.vue'),
  },
  {
    path: '/h5/login',
    name: '身份验证登录',
    component: () => import('@/views/h5/login/index.vue'),
src/router/index.js
@@ -7,14 +7,12 @@
  routes: [ ...errorPage, ...h5],
})
router.beforeEach((to, from, next) => {
router.beforeEach(async (to, from, next) => {
  if (!to.matched.length) {
    if (to.path === '/') {
      next({ path: '/error/404', query: { errorUrl: to.path } })
    }
  } else {
    next()
    next({ path: '/error/404', query: { errorUrl: to.fullPath } })
    return
  }
  next()
})
export default router
src/utils/UA.js
@@ -38,7 +38,22 @@
    }, 1000)
  }
}
export default {
  isWeixin,
  isWeixinWork,
  isMobile,
  isTBSX5,
  isiOS,
  isiOSApp,
  isAndroid,
  isAndroidApp,
  isApp,
  isOldVerApp,
  iosInputBlur,
  wxWorkIosScrollToTop,
  isHarmony,
  isHarmonyApp
}
export {
  isWeixin,
  isWeixinWork,
@@ -54,4 +69,4 @@
  wxWorkIosScrollToTop,
  isHarmony,
  isHarmonyApp
}
}
src/utils/axios.js
@@ -109,6 +109,7 @@
    }
    if (response.data && resultCode == '401') {
      let filterUrlList = ['/system/wx/js/signature']
      console.log(filterUrlList.includes(response.config.url))
      if (filterUrlList.includes(response.config.url)){ return }
      if (!originalRequest._retry && tokenUtils.getRefreshToken) {
src/utils/tool.js
@@ -72,7 +72,7 @@
export const getOccupationName = (id) => {
  const { occupationItems } = useOptionItemsStore()
  const obj = occupationItems.find(ele => ele.id == id)
  return obj?.occupationJob || ''
}
@@ -108,7 +108,7 @@
  const { occupationItems } = useOptionItemsStore()
  const occupation = occupationItems.find(ele => ele.code == occupationCode)
  if (!occupation) return ''
  const job = occupation.jobs?.find(ele => ele.jobCode == jobCode)
  if (!job) return ''
@@ -131,7 +131,7 @@
  link.href = url.includes('http') ? url : $qxueyou.qxyRes + url ;
  link.download = filename || '文件';
  link.style.display = 'none';
  // 添加到文档并触发点击
  document.body.appendChild(link);
  link.click();
@@ -140,7 +140,7 @@
export const uploadByBase64 = async function(base64, fileName, fileType = 'png') {
  if (!base64) return null
  let blob = getBlobByBase64(base64, fileType)
  if (!blob) return null
@@ -177,7 +177,7 @@
      }
    }
    xhr.onerror = (evt) => { // 上传失败回调
      store.commit("snack/error", "上传失败!")
      // store.commit("snack/error", "上传失败!")
      console.log(JSON.stringify(evt.target))
      resolve(false)
    }
@@ -209,10 +209,10 @@
export const getFileUrlType = (url = '') => {
  if (!url) return false;
  const suffix = url.split('.').pop().toLowerCase()
  const suffix = url.split('.').pop().toLowerCase()
  const imageExtensions = [
    'jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp',
    'jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp',
    'svg', 'tiff', 'tif', 'ico', 'jfif', 'pjpeg', 'pjp',
    'apng', 'avif', 'heic', 'heif'
  ];
src/utils/wxjssdk.js
@@ -1,7 +1,7 @@
import wx from 'weixin-js-sdk'
import axios from './axios'
import $qxueyou from '@/config/qxueyou.js'
import { isWeixin, isMobile } from '@/utils/UA.js'
import { isWeixin, isMobile, isiOS } from '@/utils/UA.js'
let newFeature = false
let oldShare = ['onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareQZone']
@@ -14,13 +14,14 @@
/**
 * 微信获取签名
 * @param {*} toRoute 目标路由
 */
function getWxSignature(toRoute) {
function getWxSignature() {
  if (!weixinFlag) { return false }
  let signUrl = getSignUrl()
  axios.get('/system/wx/js/signature', {
    params: { url: location.href }
    params: { url: window.location.href }
  }).then(res => {
    if (!res || !res.data) {
      return false
@@ -49,6 +50,20 @@
  })
}
function getSignUrl() {
  const currentUrl = window.location.href.split('#')[0]
  if (isiOS) {
    const cachedEntryUrl = sessionStorage.getItem('qxyKwWxVerifyEntryUrl')
    if (!cachedEntryUrl) {
      sessionStorage.setItem('qxyKwWxVerifyEntryUrl', currentUrl)
      return currentUrl
    }
    return cachedEntryUrl
  }
  return currentUrl
}
function chooseImage(){
  return new Promise((resolve) => {
    wx.chooseImage({
src/views/h5/faceAuth/components/auditDialog.vue
@@ -26,12 +26,20 @@
      <el-row justify="center" class="mt-5" v-if="status=='auditing'">
        <el-text>正在审核中,请耐心等待...</el-text>
      </el-row>
      <el-button
        v-if="status=='unStart'"
        @click="submitAudit"
        :loading="status=='auditing'"
      <el-button v-if="mode=='local'"
        @click="handlerSuccess"
        type="primary"
        size="large" class="mt-5"
        size="large" class="mt-5"
        style="width: 100%;"
      >
        上传现场照片
      </el-button>
      <el-button
        v-else-if="status=='unStart'"
        @click="submitAudit"
        :loading="status=='auditing'"
        type="primary"
        size="large" class="mt-5"
        style="width: 100%;"
      >
        提交审核
@@ -39,21 +47,39 @@
      <el-button
        v-else-if="status=='success'"
        @click="handlerSuccess"
        type="primary"
        size="large" class="mt-5"
        type="primary"
        size="large" class="mt-5"
        style="width: 100%;"
      >
        完成验证
      </el-button>
      <el-button
        v-else-if="status=='fail'"
        @click="dialogFlag=false"
        type="primary"
        size="large" class="mt-5"
        style="width: 100%;"
      >
        确定
      </el-button>
      <template v-else-if="status=='fail'">
        <el-button
          @click="dialogFlag=false"
          type="primary"
          size="large" class="mt-5"
          style="width: 100%;"
        >
          确定
        </el-button>
        <template v-if="verifyErrorCount >= 2" >
          <el-row justify="center">
            <el-text
              tag="ins" class="text-red mt-6"
              @click="uploadLocalImg()"
            >
              核验异常,工作人员上传现场照片
            </el-text>
          </el-row>
          <el-row justify="center" style="width: 100%;">
            <el-text
              class="text-xs text-info px-1"
            >
              请拍摄【本人手持身份证且背景体现现场元素的照片】
            </el-text>
          </el-row>
        </template>
      </template>
    </div>
  </el-dialog>
</template>
@@ -67,7 +93,8 @@
    return {
      dialogFlag: false,
      status: '',
      url: ''
      url: '',
      verifyErrorCount: 0
    }
  },
  props: {
@@ -78,13 +105,17 @@
    base64: {
      type: String,
      default: ''
    },
    mode: {
      type: String,
      default: ''
    }
  },
  computed: {
  },
  created() {
  },
  watch: {
    modelValue(val) {
@@ -109,6 +140,9 @@
      this.$axios.get('/system/auth/staff/checkin/face-match', { params }).then(res => {
        if (res.data.code == 0) {
          this.status = res.data.data ? 'success' : 'fail'
          if (!res.data.data) {
            this.verifyErrorCount += 1
          }
        } else {
          this.status = 'fail'
          this.$message.error(res.data.msg || "人脸比对失败")
@@ -120,7 +154,11 @@
    handlerSuccess() {
      this.dialogFlag = false
      this.$emit('handlerSuccess', this.url)
    }
    },
    uploadLocalImg() {
      this.dialogFlag = false
      this.$emit('uploadLocalImg')
    },
  }
}
</script>
@@ -153,4 +191,4 @@
  100% { top: 100%; } /* 移动到底部 */
}
</style>
</style>
src/views/h5/faceAuth/index.vue
@@ -39,7 +39,9 @@
    <auditDialog
      v-model="auditDialogFlag"
      :base64="base64"
      :mode="mode"
      @handlerSuccess="auditSuccess"
      @uploadLocalImg="uploadLocalImg"
    >
    </auditDialog>
  </div>
@@ -71,7 +73,8 @@
      ],
      openCameraFlag: false,
      base64: '',
      auditDialogFlag: false
      auditDialogFlag: false,
      mode: 'verify', // verify人脸核验照片 / local现场照片
    }
  },
  computed: {
@@ -117,6 +120,10 @@
    auditSuccess(evt) {
      this.$router.replace({ path: '/h5/map', query: { appId: this.appId, url: evt } })
    },
    uploadLocalImg() {
      this.mode = 'local'
      this.startCapture()
    }
  }
}
</script>
src/views/h5/index.vue
@@ -5,8 +5,7 @@
</template>
<script>
import { useSessionStore } from '@/stores/session.js'
import { storeToRefs } from 'pinia';
import { tokenUtils } from '@/utils/axios.js'
import { storeToRefs } from 'pinia'
export default {
  setup() {
    const { setUserInfo } = useSessionStore()
@@ -17,11 +16,11 @@
    return {}
  },
  computed: {
  },
  created() {
    const path = this.$route.path
    const regionCode = this.$route.query.regionCode
    const path = this.$route.path
    const regionCode = this.$route.query.regionCode //未使用
    const fullPath = this.$route.fullPath
    let personType = null
    if (path == '/h5/addrVer') { //0==工作人员 2==考点核验员
@@ -32,10 +31,6 @@
    localStorage.setItem('_personType', personType)
    localStorage.setItem('_regionCode', regionCode)
    localStorage.setItem('_enterUrl', fullPath)
    // const lastPersonType = localStorage.getItem('_personType')
    // if (lastPersonType && lastPersonType !== personType) {
    //   tokenUtils.clearTokens()
    // }
    this.getUserInfo()
  },
  methods: {
@@ -43,9 +38,17 @@
      this.$axios.get('/system/auth/staff/profile').then(res => {
        if (res.data.code == 0) {
          this.setUserInfo(res.data.data || {})
        } else if (res.data.code != 401) {
          const tip = res.data.msg || '获取账号信息异常'
          this.$message.error(tip)
          this.$router.replace({ path: '/h5/noTask', query: { tip } })
        }
      }).catch(() => {
        const tip = '获取账号信息异常'
        this.$router.replace({ path: '/h5/noTask', query: { tip }})
        this.$message.error(tip)
      })
    },
  }
}
</script>
</script>
src/views/h5/login/bind.vue
@@ -5,18 +5,18 @@
        <el-input v-model="form.mobile" placeholder="请输入绑定手机号" style="width: 100%" size="large" />
      </el-form-item>
      <el-form-item prop="code" :rules="[$rules.required('请输入验证码'), $rules.code()]">
        <el-input
          v-model="form.code"
          placeholder="请输入验证码"
          style="width: 100%" size="large"
        <el-input
           v-model="form.code"
           placeholder="请输入验证码"
           style="width: 100%" size="large"
        >
          <template #append>
            <el-row style="width: 70px;justify-content: center;">
              <el-button
                v-if="countdown == 180"
              <el-button
                 v-if="countdown == 180"
                style="color: var(--el-color-primary);"
                class="cursor-p"
                :loading="sendCodeLoading"
                class="cursor-p"
                 :loading="sendCodeLoading"
                @click="sendCode()"
              >
                获取验证码
@@ -138,4 +138,4 @@
.login {
  padding: 40px 20px 20px;
}
</style>
</style>
src/views/h5/login/redirect.vue
@@ -53,7 +53,7 @@
      this.redirectUrl()
      this.redirectCount = localStorage.getItem('weChatRedirectCount') || 0
      this.redirectCount = Number(this.redirectCount) + 1
      localStorage.setItem('weChatRedirectCount', redirectCount)
      localStorage.setItem('weChatRedirectCount', this.redirectCount)
    }
  },
  methods: {
@@ -103,9 +103,7 @@
            })
          }
        } else {
          setTimeout(() => {
            this.$router.replace({ path: '/h5/noTask', query: { tip: res.data.msg }})
          }, 1000)
          this.$router.replace({ path: '/h5/noTask', query: { tip: res.data.msg }})
        }
      })
    }
src/views/h5/map/BaiduMap.vue
@@ -111,6 +111,7 @@
              const newPoint = new BMapGL.Point(that.userPosition.lng, that.userPosition.lat);
              that.map.setCenter(newPoint)
            }
            that.$emit('getPosition', { point: that.userPosition, address: positionAddressText })
        } else {
          that.$emit('getUserPositionStatus', { status: 'fail' })
        }
src/views/h5/map/index.vue
@@ -15,6 +15,7 @@
              @getUserPositionStatus="getUserPositionStatus"
              @getMapStatus="(evt) => mapStatus = evt"
              @getDistance="getDistance"
              @getPosition="getUserPosition"
            />
          </div>
          <div class="center-sign">
@@ -88,7 +89,8 @@
      },
      clickCount: 0,
      personType: 0,
      limitDistanceFlag: false
      limitDistanceFlag: false,
      userPosition: {}
    }
  },
  computed: {
@@ -117,7 +119,7 @@
  },
  created() {
    const type = localStorage.getItem('_personType')
    this.personType = Number(type)
    this.personType = 0
    if (this.personType == 2) {
      this.limitDistanceFlag = true
      this.getVerifyAddress()
@@ -129,6 +131,9 @@
    this.currentTimeText = this.$dayjs().format('HH:mm')
  },
  methods: {
    getUserPosition(evt) {
      this.userPosition = evt
    },
    getVerifyAddress() {
      const params = { applicationId: this.appId }
      this.$axios.get('/exam/verify-record/get-by-application-id', { params }).then(res => {
@@ -169,7 +174,8 @@
        targetId: this.appId,
        targetType: this.personType,
        url: this.url,
        type: this.url ? 0 : 2
        type: this.url ? 0 : 2,
        details: JSON.stringify(this.userPosition)
      }
      this.confirmLoading = true
      this.$axios.post('/exam/staff/checkin', data).then(res => {
src/views/h5/noTask/index.vue
@@ -9,17 +9,18 @@
<script>
export default {
  data() {
    return {
    }
    return {}
  },
  computed: {
    tip() {
      return this.$route.query.tip || '您非相关工作人员,无法签到,请联系工作人员确认。'
    }
  }
  },
  created() {},
  methods: {}
}
</script>
<style lang="scss" scoped>
.content {
  padding: 60px;
@@ -30,4 +31,4 @@
  justify-content: center;
  align-items: center;
}
</style>
</style>
vite.config.js
@@ -7,7 +7,10 @@
// https://vite.dev/config/
export default defineConfig({
  base: '/examination/verify',
  plugins: [vue(), vueDevTools()],
  plugins: [
    vue(),
    vueDevTools()
  ],
  esbuild: {
    drop: ['console', 'debugger']
  },