ZaiZai преди 1 година
родител
ревизия
6a6986e8f6
променени са 5 файла, в които са добавени 248 реда и са изтрити 25 реда
  1. 14 0
      src/api/modules/other.js
  2. 8 0
      src/api/modules/tasks/hc-data.js
  3. 166 0
      src/components/hc-sms-auth/index.vue
  4. 2 0
      src/components/index.js
  5. 58 25
      src/views/tasks/components/hc-data/task-review.vue

+ 14 - 0
src/api/modules/other.js

@@ -62,3 +62,17 @@ export const queryWbsTreeData = (form, msg = true) => HcApi({
     method: 'get',
     params: form,
 }, msg)
+
+//短信验证
+export const sendNotice = (form, msg = true) => HcApi({
+    url: '/api/blade-business/task/send-notice',
+    method: 'post',
+    params: form,
+}, msg)
+
+//短信过期时间
+export const saveSmsTimeout = (form, msg = true) => HcApi({
+    url: '/api/blade-business/task/save-sms-timeout',
+    method: 'get',
+    params: form,
+}, msg)

+ 8 - 0
src/api/modules/tasks/hc-data.js

@@ -178,4 +178,12 @@ export default {
             data: form,
         }, false)
     },
+    //校验电签短信验证码
+    async checkSmsCode(form = {}) {
+        return HcApi({
+            url: '/api/blade-business/task/check-sms-code',
+            method: 'post',
+            data: form,
+        }, false)
+    },
 }

+ 166 - 0
src/components/hc-sms-auth/index.vue

@@ -0,0 +1,166 @@
+<template>
+    <hc-new-dialog v-model="showModal" title="短信认证" widths="26rem" @close="cancelClick">
+        <el-form ref="reportFormRef" :model="reportModel" :rules="reportRules" label-width="auto" size="large">
+            <el-form-item label="手机号码">
+                <el-input v-model="phoneVal" disabled placeholder="手机号码" />
+            </el-form-item>
+            <el-form-item class="hc-input-button-group" label="验证码" prop="code">
+                <el-input v-model="reportModel.code" placeholder="请输入验证码" />
+                <el-button :disabled="isDisabled" size="large" type="primary" @click="getCodeClick">
+                    {{ isDisabled ? `倒计时${currentTime}s` : '获取验证码' }}
+                </el-button>
+            </el-form-item>
+        </el-form>
+        <template #footer>
+            <div class="dialog-footer">
+                <el-button size="large" @click="cancelClick">
+                    <hc-icon name="close" />
+                    <span>取消</span>
+                </el-button>
+                <el-button :loading="isLoading" hc-btn type="primary" @click="confirmClick">
+                    <hc-icon name="check" />
+                    <span>确认</span>
+                </el-button>
+            </div>
+        </template>
+    </hc-new-dialog>
+</template>
+
+<script setup>
+import { ref, watch } from 'vue'
+import { useAppStore } from '~src/store'
+import { saveSmsTimeout, sendNotice } from '~api/other'
+import config from '~src/config/index'
+import { formValidate } from 'js-fast-way'
+//参数
+const props = defineProps({
+    show: {
+        type: Boolean,
+        default: false,
+    },
+    loading: {
+        type: Boolean,
+        default: false,
+    },
+})
+
+//事件
+const emit = defineEmits(['cancel', 'confirm'])
+//变量
+const userStore = useAppStore()
+const userInfo = ref(userStore.getUserInfo)
+const phoneVal = ref(config.smsPhone + '' || userInfo.value.phone + '')
+const showModal = ref(props.show)
+const isLoading = ref(props.loading)
+
+//监听
+watch(() => [
+    props.show,
+    props.loading,
+    userStore.getUserInfo,
+], ([show, loading, user]) => {
+    userInfo.value = user
+    showModal.value = show
+    isLoading.value = loading
+})
+
+//返回的验证码
+const resCode = ref('')
+//表单
+const reportFormRef = ref(null)
+const reportModel = ref({ code: null })
+const reportRules = ref({
+    code: {
+        required: true,
+        validator: (rule, value, callback) => {
+            const code = resCode.value ?? ''
+            if (!code) {
+                callback(new Error('请先获取验证码'))
+            } else if (!value) {
+                callback(new Error('请输入验证码'))
+            } else if (code !== value) {
+                callback(new Error('验证码错误'))
+            } else {
+                callback()
+            }
+        },
+        trigger: 'blur',
+    },
+})
+
+//短信验证码
+const isDisabled = ref(false) //是否开启倒计时
+const totalTime = 60 //总时间,单位秒
+const recordingTime = ref(0) //记录时间变量
+const currentTime = ref(0) //显示时间变量
+
+//获取短信验证码
+const getCodeClick = async () => {
+    const { error, code, msg } = await sendNotice({
+        phone: phoneVal.value,
+    }, false)
+    //处理数据
+    if (!error && code === 200 && msg) {
+        resCode.value = msg
+        //把显示时间设为总时间
+        currentTime.value = totalTime
+        //开始倒计时
+        isDisabled.value = true
+        //执行倒计时
+        checkingTime()
+        window?.$message?.success('发送成功')
+    } else {
+        resCode.value = ''
+        window?.$message?.error(msg || '请求异常')
+    }
+}
+
+//倒计时
+const checkingTime = () => {
+    //判断是否开启
+    if (isDisabled.value) {
+        //判断显示时间是否已到0,判断记录时间是否已到总时间
+        if (currentTime.value > 0 && recordingTime.value <= totalTime) {
+            //记录时间增加 1
+            recordingTime.value++
+            //显示时间,用总时间 - 记录时间
+            currentTime.value = totalTime - recordingTime.value
+            //1秒钟后,再次执行本方法
+            setTimeout(() => {
+                checkingTime()
+            }, 1000)
+        } else {
+            //时间已完成,还原相关变量
+            isDisabled.value = false		//关闭倒计时
+            recordingTime.value = 0	//记录时间为0
+            currentTime.value = totalTime	//显示时间为总时间
+        }
+    } else {
+        //倒计时未开启,初始化默认变量
+        isDisabled.value = false
+        recordingTime.value = 0
+        currentTime.value = totalTime
+    }
+}
+
+//取消
+const cancelClick = () => {
+    emit('cancel')
+}
+
+//确认
+const confirmClick = async () => {
+    const validate = await formValidate(reportFormRef.value)
+    if (validate) {
+        saveSmsTimeoutApi().then()
+        emit('confirm')
+    }
+}
+
+//验证码过期时间
+const saveSmsTimeoutApi = async () => {
+    await saveSmsTimeout({
+        code: resCode.value,
+    })
+}
+</script>

+ 2 - 0
src/components/index.js

@@ -8,6 +8,7 @@ import HcTitle from './hc-title/hc-title.vue'
 import HcTasksUser from './hc-tasks-user/index.vue'
 import HcViewReport from './view-report/view-report.vue'
 import HcGradientCard from './gradient-card/index.vue'
+import HcSmsAuth from './hc-sms-auth/index.vue'
 import HcPdfs from './hc-pdfs/pdfs.vue'
 
 //注册全局组件
@@ -22,5 +23,6 @@ export const setupComponents = (App) => {
     App.component('HcTitle', HcTitle)
     App.component('HcTasksUser', HcTasksUser)
     App.component('HcViewReport', HcViewReport)
+    App.component('HcSmsAuth', HcSmsAuth)
     App.component('HcPdfs', HcPdfs)
 }

+ 58 - 25
src/views/tasks/components/hc-data/task-review.vue

@@ -39,7 +39,7 @@
                                             <br>
 
                                             <el-tooltip placement="right" effect="light" :visible="item.taskDetailvisible">
-                                                <template #content> 
+                                                <template #content>
                                                     <el-timeline class="hc-time-line">
                                                         <template v-for="(item1, index1) in item.userList" :key="index1">
                                                             <el-timeline-item :class="item1.status === '2' ? 'success' : 'primary'" size="large">
@@ -57,7 +57,7 @@
                                             </el-tooltip>
                                         </div>
                                     </div>
-                                    
+
                                     <div class="reply-time">{{ item.date }}</div>
                                     <div class="reply-content" v-html="item.flowValue" />
                                 </el-timeline-item>
@@ -105,16 +105,19 @@
     <HcTaskNotes v-model="isNotesShow" :table="tableNoteInfo" :info="rowInfo" :is-edit="tabsKey === 1" @finish="taskNotesFinish" />
     <!-- 驳回 -->
     <HcRepealForm v-model="isRepealShow" :info="rowInfo" @finish="taskRepealFinish" />
+    <!-- 短信认证 -->
+    <HcSmsAuth :loading="SMSAuthLoading" :show="SMSAuthShow" @cancel="SMSAuthCancel" @confirm="SMSAuthConfirm" />
 </template>
 
 <script setup>
 import { nextTick, ref, watch } from 'vue'
-import { arrUnion, getArrValue, getObjValue, getRandom } from 'js-fast-way'
 import { useAppStore } from '~src/store'
 import HcTaskForm from './task-form.vue'
 import HcTaskNotes from './task-notes.vue'
 import HcRepealForm from './repeal-form.vue'
+import { arrUnion, getArrValue, getObjValue, getRandom, isNullES } from 'js-fast-way'
 import mainApi from '~api/tasks/hc-data'
+import dayjs from 'dayjs'
 
 const props = defineProps({
     tabs: {
@@ -146,14 +149,9 @@ const tableRef = ref(null)
 const tabsKey = ref(Number(props.tabs))
 const rowInfo = ref(props.row)
 
-watch(() => [
-    props.tabs,
-    props.row,
-], ([key, row]) => {
+watch(() => [props.tabs, props.row], ([key, row]) => {
     tabsKey.value = Number(key)
     rowInfo.value = row
-    console.log(rowInfo.value.fixedFlowId == null)
-   
 }, {
     immediate: true,
     deep: true,
@@ -162,6 +160,7 @@ watch(() => [
 //监听显示
 watch(isShow, (val) => {
     if (val) {
+        checkSmsCode()
         setTaskInfo()
         setSplitRef()
     }
@@ -219,7 +218,7 @@ const getTableDetail = async () => {
         })
         flowListTask.value = arrUnion(firstarr, taskList)
     }
-  
+
     //默认选中第一行
     let info = {}
     if (tableData.value.length > 0) {
@@ -312,21 +311,11 @@ const taskFormFinish = () => {
 
 //确认审批
 const confirmLoading = ref(false)
-const confirmClick = async () => {
-    confirmLoading.value = true
-    const { error, code, msg } = await mainApi.taskApprove({
-        taskId: rowInfo.value.id,
-        projectId: projectId.value,
-        contractId: contractId.value,
-    })
-    confirmLoading.value = false
-    if (!error && code === 200) {
-        window.$message.success('审批成功')
-        emit('finish')
-        cancelClick()
-    } else {
-        window.$message.error(msg ?? '审批失败')
-    }
+const confirmClick = () => {
+    const ShowAuth = isCheckSmsCodeTime()
+    SMSAuthShow.value = ShowAuth
+    //免短信验证
+    if (!ShowAuth) SMSAuthConfirm()
 }
 
 //驳回审批
@@ -355,6 +344,50 @@ const taskDetailvisible = ref(false)
 const getTaskDetail = ()=>{
     taskDetailvisible.value = true
 }
+
+//短信验证有效期
+const smsCodeTime = ref('')
+const checkSmsCode = async () => {
+    const { data } = await mainApi.checkSmsCode()
+    smsCodeTime.value = data ? data : ''
+}
+
+//验证短信有效期
+const isCheckSmsCodeTime = () => {
+    const smsTime = smsCodeTime.value
+    if (isNullES(smsTime)) {
+        return true
+    } else {
+        const toDayTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss')
+        return dayjs(smsTime).isBefore(toDayTime)
+    }
+}
+
+//短信验证
+const SMSAuthLoading = ref(false)
+const SMSAuthShow = ref(false)
+const SMSAuthConfirm = async () => {
+    confirmLoading.value = true
+    const { error, code, msg } = await mainApi.taskApprove({
+        taskId: rowInfo.value.id,
+        projectId: projectId.value,
+        contractId: contractId.value,
+    })
+    if (!error && code === 200) {
+        window.$message.success('审批成功')
+        await checkSmsCode()
+        confirmLoading.value = false
+        emit('finish')
+        SMSAuthCancel()
+        cancelClick()
+    } else {
+        confirmLoading.value = false
+        window.$message.error(msg ?? '审批失败')
+    }
+}
+const SMSAuthCancel = () => {
+    SMSAuthShow.value = false
+}
 </script>
 
 <style lang="scss" scoped>