Forráskód Böngészése

Merge branch 'dev_v1.0.1' into release_v1.0.1

shudonghui 1 éve
szülő
commit
82429e69c9

+ 5 - 0
src/api/work-hours.js

@@ -32,6 +32,11 @@ export const workAttendanceListApi = (data) =>
     url: '/api/admin/tb/ding/submit/page',
     params: data,
   });
+export const detail = (data) =>
+    request({
+        url: '/api/admin/tb/ding/detail',
+        params: data,
+    });
 export const workAttendanceInfoApi = (data) =>
   request({
     url: '/api/admin/tb/ding/submit/sub_total',

+ 12 - 0
src/assets/icons/icon-anomalies.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-异常共计</title>
+    <g id="工时管理" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="22.03-考勤提交-人员详情" transform="translate(-729, -152)">
+            <g id="icon-异常共计" transform="translate(728, 151)">
+                <rect id="error-circle-filled-(Background)" opacity="0" x="0" y="0" width="16" height="16"></rect>
+                <path d="M8,1 C4.13400912,1 1,4.13400483 1,8 C1,11.8659916 4.13400483,15 8,15 C11.8659916,15 15,11.8659954 15,8 C15,4.13400912 11.8659954,1 8,1 Z M8.5,9.5 L7.5,9.5 L7.5,4.00030303 L8.5,4.00030303 L8.5,9.5 Z M8.59428501,11 L8.59428501,12.1999941 L7.3942852,12.1999941 L7.3942852,11 L8.59428501,11 Z" id="error-circle-filled" fill="#F53F3F"></path>
+            </g>
+        </g>
+    </g>
+</svg>

+ 12 - 0
src/assets/icons/icon-effective-attendance.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-有效出勤</title>
+    <g id="工时管理" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="22.03-考勤提交-人员详情" transform="translate(-337, -152)">
+            <g id="icon-有效出勤" transform="translate(336, 151)">
+                <rect id="check-circle-filled-(Background)" opacity="0" x="0" y="0" width="16" height="16"></rect>
+                <path d="M15,8 C15,4.13400674 11.8659935,1 8,1 C4.13400674,1 1,4.13400674 1,8 C1,11.8659935 4.13400674,15 8,15 C11.8659935,15 15,11.8659935 15,8 Z M7,10.7069998 L11.5,6.20749998 L10.7924995,5.5 L7,9.29300022 L5.20650005,7.5 L4.5,8.20650005 L7,10.7069998 Z" id="check-circle-filled" fill="#00B42A"></path>
+            </g>
+        </g>
+    </g>
+</svg>

+ 12 - 0
src/assets/icons/icon-working-hours.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>icon-工时共计</title>
+    <g id="工时管理" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="22.03-考勤提交-人员详情" transform="translate(-533, -152)">
+            <g id="icon-工时共计" transform="translate(532, 151)">
+                <rect id="time-filled-(Background)" opacity="0" x="0" y="0" width="16" height="16"></rect>
+                <path d="M15,8 C15,4.13400674 11.8659935,1 8,1 C4.13400674,1 1,4.13400674 1,8 C1,11.8659935 4.13400674,15 8,15 C11.8659935,15 15,11.8659935 15,8 Z M7.5,8.3889246 L10.6466904,11.5356159 L11.3537979,10.8285084 L8.5,7.97471142 L8.5,5 L7.5,5 L7.5,8.3889246 Z" id="time-filled" fill="#262626"></path>
+            </g>
+        </g>
+    </g>
+</svg>

+ 1 - 0
src/utils/filter.js

@@ -57,6 +57,7 @@ export function timestampFilter(val, fmt = 'mm') {
     dd: 'yyyy/MM/dd',
     mm: 'yyyy/MM/dd HH:mm',
     ss: 'yyyy/MM/dd HH:mm:ss',
+    tt: 'HH:mm',
   };
   return val ? dateFormat(val, formats[fmt] || fmt) : DEFAULT_FIELD;
 }

+ 13 - 4
src/views/sop/sop-monitor/violation-registration/flow-dialog.vue

@@ -78,6 +78,7 @@
           class="sop-step-body"
         >
           <t-row :gutter="[0, 30]">
+            <template v-if="!IS_VIEW_MODE">
             <t-col :span="12">
               <div class="form-group-title"> 新增跟进 </div>
             </t-col>
@@ -100,8 +101,9 @@
                 <my-upload @change="fileChange"></my-upload>
               </t-form-item>
             </t-col>
+            </template>
             <t-col :span="12">
-              <div class="m-b-10px">
+              <div class="m-b-10px" v-if="!IS_VIEW_MODE">
                 历史明细查阅
                 <t-link
                   theme="primary"
@@ -111,7 +113,7 @@
                   <ChevronDownIcon v-else /></t-link
               ></div>
               <t-table
-                v-if="showHistory"
+                v-if="showHistory || IS_VIEW_MODE"
                 size="small"
                 row-key="id"
                 :columns="columns"
@@ -131,7 +133,7 @@
             </t-col>
           </t-row>
         </t-form>
-        <t-space class="sop-step-footer">
+        <t-space v-if="!IS_VIEW_MODE" class="sop-step-footer">
           <t-button theme="primary" @click="save">保存</t-button>
           <t-button theme="default" @click="emit('update:visible', false)"
             >取消</t-button
@@ -161,13 +163,20 @@ const props = defineProps({
       return {};
     },
   },
+  type: {
+    type: String,
+    default: 'new',
+  },
+
 });
 const emit = defineEmits(['update:visible', 'success']);
 
 const formRef = ref(null);
 const tableData = ref([]);
 const showHistory = ref(false);
-
+const IS_VIEW_MODE = computed(() => {
+  return props.type === 'view';
+});
 const title = computed(() => {
   return `违规信息(违规流水号:${props.curRow.code})`;
 });

+ 14 - 2
src/views/sop/sop-monitor/violation-registration/index.vue

@@ -47,6 +47,12 @@
         }"
         v-loading="tableLoading"
       >
+        <template #code="{ col, row }">
+          <more-content
+              :content="row[col.colKey]"
+              @action="handleDetail(row)"
+          ></more-content>
+        </template>
         <template #type="{ col, row }">
           {{ violationTypeFilter(row[col.colKey]) }}
         </template>
@@ -101,6 +107,7 @@
       v-if="perm.LINK_Follow"
       v-model:visible="showViolationFlowDialog"
       :curRow="curRow"
+      :type="viewType"
       @confirm="fetchData"
     ></violation-flow-dialog>
   </div>
@@ -122,7 +129,12 @@ const { perm } = usePermission();
 
 const showViolationFlowDialog = ref(false);
 const curRow = ref({});
-
+const viewType = ref('');
+const handleDetail = (row) => {
+  viewType.value = 'view';
+  curRow.value = row;
+  showViolationFlowDialog.value = true;
+};
 const handleFollow = (row) => {
   curRow.value = row;
   showViolationFlowDialog.value = true;
@@ -171,7 +183,7 @@ const columns = [
     title: '违规类型',
     width: 130,
   },
-  { colKey: 'content', title: '违规情况' },
+  { colKey: 'content', title: '违规情况',ellipsis: true, width: 200 },
   {
     colKey: 'status',
     title: '跟进状态',

+ 186 - 0
src/views/work-hours/work-hours-manage/work-attendance/detail-dialog.vue

@@ -0,0 +1,186 @@
+<template>
+  <my-drawer
+      class="sop-dialog"
+      :visible="visible"
+      header="打卡明细"
+      size="80%"
+      attach="body"
+      :closeOnOverlayClick="false"
+      :close-btn="true"
+      :footer="false"
+      @close="emit('update:visible', false)"
+  >
+    <div class="">
+      <t-collapse class="sop-step-mid" defaultExpandAll>
+        <t-collapse-panel disabled>
+          <t-form colon label-width="72px">
+            <t-row :gutter="[0, 4]">
+              <t-col :span="3">
+                <t-form-item label="项目单号">{{ row.crmNo }}</t-form-item>
+              </t-col>
+              <t-col :span="3">
+                <t-form-item label="姓名">{{ row.archivesInfo }}</t-form-item>
+              </t-col>
+              <t-col :span="3">
+                <t-form-item label="项目角色">{{
+                    roleTypeFilter(row.roleType)
+                  }}
+                </t-form-item>
+              </t-col>
+              <t-col :span="3">
+                <t-form-item label="所属供应商" label-width="100px">{{ row.supplierName }}
+                </t-form-item>
+              </t-col>
+              <t-col :span="3">
+                <t-form-item label="sop流水号">{{
+                    row.sopNo
+                  }}
+                </t-form-item>
+              </t-col>
+              <t-col :span="3">
+                <t-form-item label="客户名称">{{
+                    row.customName
+                  }}
+                </t-form-item>
+              </t-col>
+              <t-col :span="3">
+                <t-form-item label="有效出勤">{{
+                    row.actualDays
+                  }}
+                </t-form-item>
+              </t-col>
+              <t-col :span="3">
+                <t-form-item label="考试开始时间" label-width="100px">{{
+                    timestampFilter(row.approachTime)
+                  }}
+                </t-form-item>
+              </t-col>
+              <t-col :span="3">
+                <t-form-item label="考试结束时间" label-width="100px">{{
+                    timestampFilter(row.departureTime)
+                  }}
+                </t-form-item>
+              </t-col>
+              <!--              <t-col :span="3">-->
+              <!--                <t-form-item label="实施产品">{{-->
+              <!--                    row.productName-->
+              <!--                  }}-->
+              <!--                </t-form-item>-->
+              <!--              </t-col>-->
+              <t-col :span="3">
+                <t-form-item label="服务单元">{{
+                    row.serviceUnitName
+                  }}
+                </t-form-item>
+              </t-col>
+            </t-row>
+          </t-form>
+        </t-collapse-panel>
+      </t-collapse>
+      <div style="margin-bottom: 20px">
+        <t-button variant="outline">
+          <template #icon>
+            <svg-icon name="effective-attendance" color="#00B42A"/>
+          </template
+          >
+          有效出勤&nbsp;&nbsp;&nbsp;&nbsp;{{ row.actualDays }}天
+        </t-button>&nbsp;&nbsp;
+        <t-button variant="outline">
+          <template #icon>
+            <svg-icon name="working-hours" color="#262626"/>
+          </template
+          >
+          共计工时&nbsp;&nbsp;&nbsp;&nbsp;{{ row.workHours }}天
+        </t-button>&nbsp;&nbsp;
+        <t-button variant="outline">
+          <template #icon>
+            <svg-icon name="anomalies" color="#F53F3F"/>
+          </template
+          >
+          异常共计&nbsp;&nbsp;&nbsp;&nbsp;{{ row.exceptionCount }}天
+        </t-button>
+      </div>
+      <t-table
+          size="small"
+          row-key="id"
+          :columns="columns"
+          :data="tableData"
+          bordered
+          :pagination="{
+          defaultCurrent: 1,
+          defaultPageSize: 20,
+
+          total: pagination.total,
+          current: pagination.pageNumber,
+        }"
+      >
+        <template #signIn="{ col, row }">
+          {{ row.signInTime ? timestampFilter(row[col.colKey], 'tt') + row.signInAddress : '异常' }}
+        </template>
+        <template #signOut="{ col, row }">
+          {{ row.signOutTime ? timestampFilter(row[col.colKey], 'tt') + row.signOutAddress : '异常' }}
+        </template>
+        <template #workHours="{ col, row }">
+          {{ row.signOutTime && row.signInTime ? ((row.signOutTime - row.signInTime) / 1000 / 60 / 60).toFixed(2) : '' }}
+        </template>
+      </t-table>
+      <t-space class="sop-step-footer" style="flex-direction: row">
+        <t-button theme="primary" @click="emit('update:visible', false)"
+        >返回
+        </t-button
+        >
+      </t-space>
+    </div>
+
+  </my-drawer>
+</template>
+
+<script setup name="DetailDialog">
+import {timestampFilter, roleTypeFilter, customerTypeFilter, attendanceSubmitStatusFilter} from '@/utils/filter';
+import {computed, reactive, watch} from 'vue';
+import useFetchTable from "@/hooks/useFetchTable";
+import {detail} from "@/api/work-hours";
+import {randomCode} from "@/utils/tool";
+
+const emit = defineEmits(['update:visible', 'confirm']);
+const props = defineProps({
+  visible: Boolean,
+  row: {
+    type: Object,
+    default() {
+      return {};
+    },
+  },
+});
+const columns = [
+  {colKey: 'signDate', title: '日期', width: 100},
+  {colKey: 'signInTime', title: '签到', cell: 'signIn',width: 160},
+  {colKey: 'signOutTime', title: '签退', width: 160, cell: 'signOut'},
+  {colKey: 'workHours', title: '工时(小时)', width: 100, cell: 'workHours'},
+];
+
+const params = computed(() => {
+  return {
+    sopNo: props.row.sopNo,
+    archivesId: props.row.archivesId,
+  };
+});
+
+const {pagination, tableData, fetchData} = useFetchTable(
+    detail,
+    {
+      params,
+    }, false
+);
+
+
+watch(
+    () => props.visible,
+    (val) => {
+      if (val)
+
+        fetchData()
+
+    }
+);
+</script>

+ 24 - 0
src/views/work-hours/work-hours-manage/work-attendance/index.vue

@@ -62,6 +62,18 @@
         :selected-row-keys="selectedRowKeys"
         @select-change="selectChange"
       >
+        <template #sopNo="{ col, row }">
+          <more-content
+              :content="row[col.colKey]"
+              @action="openDetailDialog(row)"
+          ></more-content>
+        </template>
+        <template #archivesInfo="{ col, row }">
+          <more-content
+              :content="row[col.colKey]"
+              @action="openDetailDialog(row)"
+          ></more-content>
+        </template>
         <template #role="{ col, row }">
           {{ roleTypeFilter(row[col.colKey]) }}
         </template>
@@ -114,6 +126,10 @@
         </template>
       </t-table>
     </div>
+    <detail-dialog
+        v-model:visible="showDetailDialog"
+        :row="curRow"
+    ></detail-dialog>
   </div>
 </template>
 
@@ -138,6 +154,10 @@ import {
 import { randomCode } from '@/utils/tool';
 import usePermission from '@/hooks/usePermission';
 const { perm } = usePermission();
+import DetailDialog from './detail-dialog.vue';
+
+const showDetailDialog = ref(false);
+const curRow = ref({});
 
 const selectedRowKeys = ref([]);
 const selectedRowDatas = ref([]);
@@ -145,6 +165,10 @@ const selectChange = (value, { selectedRowData }) => {
   selectedRowKeys.value = value;
   selectedRowDatas.value = selectedRowData.map((item) => getSelectedData(item));
 };
+const openDetailDialog = (row) => {
+  curRow.value = row;
+  showDetailDialog.value = true;
+};
 
 function getSelectedData(data) {
   return {