Browse Source

Merge branch 'master' of http://git.qmth.com.cn/sop/mobile

刘洋 1 year ago
parent
commit
b06d524729

+ 1 - 0
src/api/common.js

@@ -1,3 +1,4 @@
 import { http } from '@/service/request.js'
 export const getServiceUnit = () => http.post('/api/admin/common/query_service_unit')
 export const getAttachmentList = (ids) => http.post('/api/admin/common/file/preview', ids)
+export const getFlowVersion = (params) => http.post('/api/admin/flow/version/list', {}, { params, custom: { loading: true } })

+ 3 - 0
src/api/ding.js

@@ -13,3 +13,6 @@ export const locAddr = (data) => http.get('https://apis.map.qq.com/ws/geocoder/v
 //考勤打卡-查询所有sop
 export const dingFindAllSop = (data) => http.post('/api/admin/tb/ding/ding_find_all_sop', data, {custom: {loading: true}})
 
+export const dingExceptionSave = (data) => http.post('/api/admin/ding/exception/apply/save', data, {custom: {loading: true}})
+
+

+ 45 - 0
src/components/low-code/DATETIME.vue

@@ -0,0 +1,45 @@
+<template>
+  <view>
+    <u-input :value="valueStr" type="select" :border="true" :placeholder="config.placeholder||'请选择补卡时间'" :disabled="!config.writable" @click="show = true" />
+    <u-picker v-model="show" mode="time" @confirm="change" :params="config.params||params"></u-picker>
+  </view>
+</template>
+
+<script>
+  import { dateFormat } from '@/utils/utils'
+  export default {
+    name: 'DATETIME',
+    props: ['config'],
+    computed: {
+      valueStr() {
+        if(this.value)
+        return dateFormat(this.value, 'yyyy-MM-dd hh:mm')
+      }
+    },
+    data() {
+      return {
+        value: '',
+        show: false,
+        params: {
+          year: true,
+          month: true,
+          day: true,
+          hour: true,
+          minute: true,
+          second: false
+        },
+      }
+    },
+    created() {
+      this.value = this.config.value || ''
+    },
+    methods: {
+      change(obj) {
+        this.value = new Date(obj.year,obj.month,obj.day,obj.hour,obj.minute).getTime()
+        this.$emit('change',  this.value )
+      }
+    }
+  }
+</script>
+
+<style></style>

+ 8 - 1
src/pages.json

@@ -98,6 +98,13 @@
         "navigationBarTitleText": "考勤异常处理",
         "enablePullDownRefresh": false
       }
+    },
+    {
+      "path": "pages/ding/ding-supplement",
+      "style": {
+        "navigationBarTitleText": "考勤补卡",
+        "enablePullDownRefresh": false
+      }
     }
   ],
   "subPackages": [
@@ -147,4 +154,4 @@
       }
     ]
   }
-}
+}

+ 5 - 5
src/pages/ding/ding-abnormal.vue

@@ -31,13 +31,13 @@
             <text class="sub-title" v-if="item.signInInfo.status==='RE_SIGN'">签到:补卡</text>
             <text class="sub-title" v-if="item.signInInfo.status==='OTHER'">--</text>
             <text class="sub-title" v-if="item.signInInfo.status==='NO_SIGN'">签到:未签到</text>
-            <u-button type="primary" size="mini" @click="this.$Router.push({ path: '/pages/ding/ding-supplement', query: {dingId: item.dingId, signDate: item.signDate,singnType:'IN'} })" v-if="item.signInInfo.status==='NO_SIGN'">补卡</u-button>
+            <u-button type="primary" size="mini" @click="this.$Router.push({ path: '/pages/ding/ding-supplement', query: {dingId: item.dingId, signDate: item.signDate,type:'IN'} })" v-if="item.signInInfo.status==='NO_SIGN'">补卡</u-button>
           </view>
           <view class="key-value flex items-center justify-between" v-if="item.signOutInfo.status!=='SIGN'">
             <text class="sub-title" v-if="item.signOutInfo.status==='RE_SIGN'">签退:补卡</text>
             <text class="sub-title" v-if="item.signOutInfo.status==='OTHER'">--</text>
             <text class="sub-title" v-if="item.signOutInfo.status==='NO_SIGN'">签退:未签退</text>
-            <u-button type="primary" size="mini" @click="this.$Router.push({ path: '/pages/ding/ding-supplement', query: {dingId: item.dingId, signDate: item.signDate,singnType:'OUT'} })" v-if="item.signOutInfo.status==='NO_SIGN'">补卡</u-button>
+            <u-button type="primary" size="mini" @click="this.$Router.push({ path: '/pages/ding/ding-supplement', query: {dingId: item.dingId, signDate: item.signDate,type:'OUT'} })" v-if="item.signOutInfo.status==='NO_SIGN'">补卡</u-button>
           </view>
         </view>
         <view class="m-separator" v-if="index!==statistic.dingFormList.length-1"></view>
@@ -57,7 +57,7 @@ import {dingFindAllSop,dingStatistic} from "@/api/ding";
 
 
 export default {
-  name: 'ding-statistics',
+  name: 'ding-abnormal',
   components: {RadiusSelect},
   data() {
     return {
@@ -118,7 +118,7 @@ export default {
 
 <style lang="scss" scoped>
 .ding {
-  height: calc(100% - 80rpx);
+  //height: calc(100% - 80rpx);
   padding: 24rpx;
 }
 
@@ -169,7 +169,7 @@ export default {
 }
 
 .scroll-Y {
-  height: calc(100% - 184rpx);
+  //height: calc(100vh - 184rpx);
   margin-top: 12px;
   border-radius: 6px;
   background: #FFFFFF;

+ 4 - 4
src/pages/ding/ding-statistics.vue

@@ -37,14 +37,14 @@
             <text class="sub-title" v-if="item.signInInfo.status==='RE_SIGN'">签到:补卡</text>
             <text class="sub-title" v-if="item.signInInfo.status==='OTHER'">--</text>
             <text class="sub-title" v-if="item.signInInfo.status==='NO_SIGN'">签到:未签到</text>
-            <u-button type="primary" size="mini" @click="this.$Router.push({ path: '/pages/ding/ding-supplement', query: {dingId: item.dingId, signDate: item.signDate,singnType:'IN'} })" v-if="item.signInInfo.status==='NO_SIGN'">补卡</u-button>
+            <u-button type="primary" size="mini" @click="this.$Router.push({ path: '/pages/ding/ding-supplement', query: {dingId: item.dingId, signDate: item.signDate,type:'IN'} })" v-if="item.signInInfo.status==='NO_SIGN'">补卡</u-button>
           </view>
           <view class="key-value flex items-center justify-between">
             <text class="sub-title" v-if="item.signOutInfo.status==='SIGN'">签退:{{ dateFormat(item.signOutInfo.signTime, 'hh:mm') }} {{item.signOutInfo.signAddress }}</text>
             <text class="sub-title" v-if="item.signOutInfo.status==='RE_SIGN'">签退:补卡</text>
             <text class="sub-title" v-if="item.signOutInfo.status==='OTHER'">--</text>
             <text class="sub-title" v-if="item.signOutInfo.status==='NO_SIGN'">签退:未签退</text>
-            <u-button type="primary" size="mini" @click="this.$Router.push({ path: '/pages/ding/ding-supplement', query: {dingId: item.dingId, signDate: item.signDate,singnType:'OUT'} })" v-if="item.signOutInfo.status==='NO_SIGN'">补卡</u-button>
+            <u-button type="primary" size="mini" @click="this.$Router.push({ path: '/pages/ding/ding-supplement', query: {dingId: item.dingId, signDate: item.signDate,type:'OUT'} })" v-if="item.signOutInfo.status==='NO_SIGN'">补卡</u-button>
           </view>
         </view>
         <view class="m-separator" v-if="index!==statistic.dingFormList.length-1"></view>
@@ -125,7 +125,7 @@ export default {
 
 <style lang="scss" scoped>
 .ding {
-  height: calc(100% - 80rpx);
+  //height: calc(100% - 80rpx);
   padding: 24rpx;
 }
 
@@ -176,7 +176,7 @@ export default {
 }
 
 .scroll-Y {
-  height: calc(100% - 184rpx);
+  //height: calc(100% - 184rpx);
   margin-top: 12px;
   border-radius: 6px;
   background: #FFFFFF;

+ 162 - 0
src/pages/ding/ding-supplement.vue

@@ -0,0 +1,162 @@
+<template>
+  <view class="ding flex flex-col">
+    <scroll-view
+      scroll-y="true"
+      refresher-enabled="false"
+      class="scroll-Y"
+    >
+      <view class="form-box">
+        <view class="f-item">
+          <view class="label">
+            <text class="title">异常日期:{{ tbDingApply.signDate||'' }}</text>
+          </view>
+        </view>
+        <view class="f-item">
+          <view class="label">
+            <text class="text">补卡类型:{{ tbDingApply.type==='IN'?'签到':'签退' }}</text>
+          </view>
+        </view>
+        <view class="f-item">
+          <view class="label">
+            <text class="red">*</text>
+            <text class="text">补卡时间</text>
+          </view>
+          <DATETIME :config="{}" @change="(time)=>{tbDingApply.applyTime=time}"></DATETIME>
+        </view>
+        <view class="f-item">
+          <view class="label">
+            <text class="text">补卡理由({{ (tbDingApply.reason||'').length }}/200)</text>
+          </view>
+          <u-input v-model="tbDingApply.reason" maxlength="200" type="textarea" :border="true" placeholder="请输入理由" height="200"/>
+        </view>
+        <view class="f-item">
+          <view class="label">
+            <text class="red">*</text>
+            <text class="text">证明附加</text>
+            <text class="sub-text flex">为提高审核通过率,请认真提交证明附件或截图。</text>
+            <UPLOADIMAGE :key="null" :config="{ length: 3, value: [] }" @change="(e)=>tbDingApply.attachmentIdList=e.value.map(e=>e.id)"></UPLOADIMAGE>
+          </view>
+        </view>
+      </view>
+    </scroll-view>
+    <view class="bottom-space">
+      <u-button type="primary" @click="submit">提交</u-button>
+    </view>
+    <u-toast ref="uToast"/>
+  </view>
+</template>
+
+<script>
+
+
+import UPLOADIMAGE from "@/components/low-code/UPLOAD_IMAGE.vue";
+import TEXT from "@/components/low-code/TEXT.vue";
+import DATETIME from "@/components/low-code/DATETIME.vue";
+import {dingExceptionSave} from "@/api/ding";
+import {getFlowVersion} from "@/api/common";
+
+export default {
+  name: 'ding-supplement',
+  components: {DATETIME, TEXT, UPLOADIMAGE},
+  data() {
+    return {
+      loadingFlag: 0,
+      show:false,
+      tbDingApply: {
+        signDate:'',
+        dingId: 0,
+        applyTime: 0,
+        reason: '',
+        attachmentIdList: [],
+        flowDeploymentId: 0,
+        type: ''
+      }
+    }
+  },
+  mounted() {
+    this.tbDingApply = this.$Route.query;
+  },
+
+  methods: {
+    async submit() {
+      const v= await getFlowVersion({type:'DING_EXCEPTION_FLOW'});
+      this.tbDingApply.flowDeploymentId=v[0].flowDeploymentId;
+      await dingExceptionSave(this.tbDingApply);
+      this.$refs.uToast.show({
+        title: '提交成功',
+        type: 'success'
+      })
+      this.$Router.back(1)
+    }
+
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.ding {
+  //height: calc(100% - 80rpx);
+
+
+}
+
+.scroll-Y {
+  height: calc(100vh - 184rpx);
+}
+
+.form-box {
+  padding: 12rpx;
+  background: #FFFFFF;
+  border-radius: 6px;
+  margin: 12rpx;
+
+  .f-item {
+    margin-bottom: 30rpx;
+
+    .label {
+      margin-bottom: 4rpx;
+
+      .red {
+        color: red;
+        margin-right: 4rpx;
+      }
+
+      .title {
+        height: 22px;
+        font-size: 14px;
+        font-family: PingFangSC-Medium, PingFang SC;
+        font-weight: 500;
+        color: #262626;
+        line-height: 22px;
+      }
+
+      .text {
+        height: 22px;
+        font-size: 14px;
+        font-family: PingFangSC-Regular, PingFang SC;
+        font-weight: 400;
+        color: #595959;
+        line-height: 22px;
+      }
+
+      .sub-text {
+        height: 20px;
+        font-size: 12px;
+        font-family: PingFangSC-Regular, PingFang SC;
+        font-weight: 400;
+        color: #FF7D00;
+        line-height: 20px;
+      }
+    }
+  }
+}
+
+.bottom-space {
+  height: 88px;
+  background: #FFFFFF;
+  position: absolute;
+  bottom: 0;
+  width: 100%;
+  padding: 24px;
+}
+</style>

+ 8 - 15
src/pages/ding/ding.vue

@@ -171,32 +171,25 @@ export default {
       if (this.dingInfo.faceOpen) {
           this.faceModel=true;
       }else{
-        const _this=this;
-        getAppWxLatLon(async (res) => {
-          const loc = await locAddr(res);
-          _this.dingObj.signAddress = loc.result.address
-          _this.dingObj.axisX = res.longitude;
-          _this.dingObj.axisY = res.latitude;
-          dingSave(_this.dingObj).then((res) => {
-            _this.dingSuccess = true;
-            _this.signInEnable = false;
-            _this.signOutEnable = false;
-          })
-        })
+        this.saveDing();
       }
     },
     dingFace(facePhotoPath){
+      this.dingObj.facePhotoPath = facePhotoPath;
+      this.saveDing();
+    },
+    saveDing(){
       const _this=this;
       getAppWxLatLon(async (res) => {
         const loc = await locAddr(res);
         _this.dingObj.signAddress = loc.result.address
-        _this.dingObj.facePhotoPath = facePhotoPath;
         _this.dingObj.axisX = res.longitude;
         _this.dingObj.axisY = res.latitude;
-        dingSave(_this.dingObj).then((res) => {
+        dingSave(_this.dingObj).then(async (res) => {
           _this.dingSuccess = true;
           _this.signInEnable = false;
           _this.signOutEnable = false;
+          _this.dingInfo = await getDingInfo({sopNo: sopNo});
         })
       })
     }
@@ -206,7 +199,7 @@ export default {
 
 <style lang="scss" scoped>
 .ding {
-  height: calc(100% - 80rpx);
+  //height: calc(100vh - 80rpx);
   padding: 24rpx;
 }
 .msg-item {