文件上传,切换人脸,打卡,状态编辑,下载资料模板
This commit is contained in:
		| @ -62,6 +62,33 @@ | ||||
|           <el-col :span="1.5"> | ||||
|             <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['project:constructionUser:export']">导出 </el-button> | ||||
|           </el-col> | ||||
|           <el-col :span="1.5"> | ||||
|             <el-button type="warning" plain icon="Edit" :disabled="multiple" @click="statusDialog = true">用户状态编辑 </el-button> | ||||
|           </el-col> | ||||
|           <el-col :span="1.5"> | ||||
|             <el-switch | ||||
|               v-model="playCardStatus" | ||||
|               class="ml-2" | ||||
|               inline-prompt | ||||
|               style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949" | ||||
|               :loading="playCardLoding" | ||||
|               @change="handlePlayCardStatus" | ||||
|               inactive-text="一键关闭打卡" | ||||
|               active-text="一键开启打卡" | ||||
|             /> | ||||
|           </el-col> | ||||
|           <el-row @mouseover="informationStatus = true" :gutter="10" @mouseout="informationStatus = false"> | ||||
|             <el-col :span="1.5"> | ||||
|               <el-button type="success" plain @click="statusDialog = true">员工资料 </el-button> | ||||
|             </el-col> | ||||
|             <el-col :span="1.5" v-show="informationStatus"> | ||||
|               <el-button type="primary" plain icon="Edit" @click="downloadTemplate">下载资料模板 </el-button> | ||||
|             </el-col> | ||||
|             <el-col :span="1.5" v-show="informationStatus"> | ||||
|               <el-button type="warning" plain icon="Edit" @click="statusDialog = true">导入员工资料 </el-button> | ||||
|             </el-col> | ||||
|           </el-row> | ||||
|  | ||||
|           <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> | ||||
|         </el-row> | ||||
|       </template> | ||||
| @ -91,7 +118,24 @@ | ||||
|         </el-table-column> | ||||
|         <el-table-column label="打卡状态" align="center" prop="clock"> | ||||
|           <template #default="scope"> | ||||
|             <dict-tag :options="user_clock_type" :value="scope.row.clock" /> | ||||
|             <el-switch | ||||
|               v-model="scope.row.clock" | ||||
|               class="ml-2" | ||||
|               inline-prompt | ||||
|               style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949" | ||||
|               active-text="开启" | ||||
|               inactive-text="禁用" | ||||
|               :loading="playCardLoding" | ||||
|               active-value="0" | ||||
|               inactive-value="1" | ||||
|               @change="handleClockStatus(scope.row)" | ||||
|             /> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="日薪(元)" align="center" min-width="180"> | ||||
|           <template #default="scope"> | ||||
|             <span>{{ scope.row.salary ? scope.row.salary : scope.row.standardSalary }}</span> | ||||
|             <div class="text-blue text-sm cursor-pointer" @click="openSalaryDialog(scope.row)">{{ scope.row.salary ? '取消变更' : '变更' }}</div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="入场时间" align="center" prop="entryDate" min-width="180" /> | ||||
| @ -115,12 +159,17 @@ | ||||
|               <el-button link type="danger" icon="Avatar" @click="handleJoinBlacklist(scope.row)" v-hasPermi="['project:constructionBlacklist:add']"> | ||||
|                 黑名单 | ||||
|               </el-button> | ||||
|               <el-button link type="primary" icon="Switch" @click="handleChange(scope.row)" v-hasPermi="['project:constructionBlacklist:add']"> | ||||
|                 人员迁移 | ||||
|               </el-button> | ||||
|               <el-button link type="primary" icon="Switch" @click="handleToggle(scope.row)"> 切换人脸 </el-button> | ||||
|               <el-button link type="primary" icon="Switch" @click="handleChange(scope.row)"> 人员迁移 </el-button> | ||||
|               <el-button link type="primary" icon="ChatLineSquare" @click="handleExit(scope.row)"> 入退场记录 </el-button> | ||||
|               <el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['project:constructionUser:remove']"> | ||||
|                 删除 | ||||
|               </el-button> | ||||
|               <el-tooltip content="红点:部分上传,绿点:已上传,无点:未上传" placement="right" effect="dark"> | ||||
|                 <el-badge is-dot type="primary"> | ||||
|                   <el-button link type="primary" icon="FolderAdd" @click="handleUpload(scope.row)">文件上传 </el-button> | ||||
|                 </el-badge> | ||||
|               </el-tooltip> | ||||
|             </el-space> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
| @ -286,6 +335,69 @@ | ||||
|         </div> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|     <el-dialog title="上传文件" v-model="fileStatus" width="770px"> | ||||
|       <div class="image_upload" v-for="(item, index) in uploadPath" :key="item.value"> | ||||
|         <div class="title">{{ item.label }}</div> | ||||
|         <div class="file_upload_all" v-if="item.value != 7"> | ||||
|           <file-upload v-model="item.path" isConstruction :isShowTip="false" :limit="10" :file-type="['pdf']" :file-size="50" /> | ||||
|         </div> | ||||
|       </div> | ||||
|       <template #footer> | ||||
|         <div class="dialog-footer"> | ||||
|           <el-button :loading="buttonLoading" type="primary" @click="updateProjectFile">确认</el-button> | ||||
|           <el-button @click="fileStatus = false"> 取消 </el-button> | ||||
|         </div> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|     <el-dialog :title="skipName + '-切换人脸'" v-model="showFaceDrawer" width="770px"> | ||||
|       <div class="flex items-center justify-center"> | ||||
|         <image-upload v-model="form.facePic" :limit="1" :is-show-tip="false" /> | ||||
|       </div> | ||||
|       <template #footer> | ||||
|         <span | ||||
|           ><el-button type="primary" @click="submitForm">保存</el-button> | ||||
|           <el-button @click="showFaceDrawer = false">取消</el-button> | ||||
|         </span> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|     <el-dialog title="修改在职状态" v-model="statusDialog" width="30%"> | ||||
|       <el-form-item label="在职状态"> | ||||
|         <el-select v-model="vocationalStatus" placeholder="请选择状态"> | ||||
|           <el-option v-for="item in user_status_type" :key="item.value" :label="item.label" :value="item.value" /> | ||||
|         </el-select> | ||||
|       </el-form-item> | ||||
|       <template #footer> | ||||
|         <span | ||||
|           ><el-button type="primary" @click="handleEdit">保存</el-button> | ||||
|           <el-button @click="statusDialog = false">取消</el-button> | ||||
|         </span> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|     <el-dialog title="温馨提示" v-model="salaryStatus" width="30%"> | ||||
|       <span>请输入薪资(元/月)</span> | ||||
|       <el-input class="mt-xl" v-model="changeSalary" placeholder="" size="normal" clearable @change=""></el-input> | ||||
|       <template #footer> | ||||
|         <span> | ||||
|           <el-button type="primary" @click="handleSalary">确认</el-button> | ||||
|           <el-button @click="salaryStatus = false">取消</el-button> | ||||
|         </span> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|     <el-dialog title="入场退场记录" v-model="exitStatus" width="600px"> | ||||
|       <div v-for="(item, index) in exitList"> | ||||
|         <el-timeline> | ||||
|           <el-timeline-item v-for="(itm, idx) in 2" :key="idx" :timestamp="item.entryDate" :color="green"> | ||||
|             {{ item.entryDate }} | ||||
|           </el-timeline-item> | ||||
|         </el-timeline> | ||||
|       </div> | ||||
|  | ||||
|       <template #footer> | ||||
|         <span> | ||||
|           <el-button @click="exitStatus = false">关闭</el-button> | ||||
|         </span> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| @ -297,7 +409,13 @@ import { | ||||
|   listConstructionUser, | ||||
|   updateConstructionUser, | ||||
|   getProjectContractorList, | ||||
|   transferConstructionUser | ||||
|   transferConstructionUser, | ||||
|   updateConstructionUserStatus, | ||||
|   updateConstructionUserPlayCardStatus, | ||||
|   updateConstructionUserPlayCardOneStatus, | ||||
|   updateConstructionUserSalary, | ||||
|   getConstructionUserExit, | ||||
|   dowloadConstructionUserTemplate | ||||
| } from '@/api/project/constructionUser'; | ||||
| import { | ||||
|   ConstructionUserForm, | ||||
| @ -314,10 +432,19 @@ import { ContractorVO } from '@/api/project/contractor/types'; | ||||
| import { ProjectTeamVO } from '@/api/project/projectTeam/types'; | ||||
| import ConstructionUserDetail from '@/views/project/constructionUser/component/ConstructionUserDetail.vue'; | ||||
| import { addConstructionBlacklist } from '@/api/project/constructionBlacklist'; | ||||
| import { listConstructionUserFile, setConstructionUserFile } from '@/api/project/constructionUserFile'; | ||||
| import { | ||||
|   ConstructionUserFileVO, | ||||
|   ConstructionUserExitVO, | ||||
|   ConstructionUserFileForm, | ||||
|   ConstructionUserFileQuery | ||||
| } from '@/api/project/constructionUserFile/types'; | ||||
| import { ElLoadingService } from 'element-plus'; | ||||
|  | ||||
| const { proxy } = getCurrentInstance() as ComponentInternalInstance; | ||||
| const { type_of_work, user_sex_type, user_clock_type } = toRefs<any>(proxy?.useDict('type_of_work', 'user_sex_type', 'user_clock_type')); | ||||
|  | ||||
| const { type_of_work, user_sex_type, user_clock_type, user_file_type, user_status_type } = toRefs<any>( | ||||
|   proxy?.useDict('type_of_work', 'user_sex_type', 'user_clock_type', 'user_file_type', 'user_status_type') | ||||
| ); | ||||
| // 获取用户 store | ||||
| const userStore = useUserStoreHook(); | ||||
| // 从 store 中获取项目列表和当前选中的项目 | ||||
| @ -331,6 +458,18 @@ const single = ref(true); | ||||
| const multiple = ref(true); | ||||
| const total = ref(0); | ||||
| const skip = ref(false); | ||||
| const fileStatus = ref(false); | ||||
| const showFaceDrawer = ref(false); | ||||
| const statusDialog = ref(false); | ||||
| const playCardStatus = ref(false); | ||||
| const playCardLoding = ref(false); | ||||
| const salaryStatus = ref(false); | ||||
| const exitStatus = ref(false); | ||||
| const informationStatus = ref(false); | ||||
| const exitList = ref<ConstructionUserExitVO[]>([]); | ||||
| const changeSalary = ref<string>(''); | ||||
| const vocationalStatus = ref<number>(null); | ||||
| const fileList = ref<ConstructionUserFileVO[]>([]); | ||||
| const queryFormRef = ref<ElFormInstance>(); | ||||
| const constructionUserFormRef = ref<ElFormInstance>(); | ||||
| const skipName = ref(''); | ||||
| @ -421,6 +560,27 @@ const data = reactive<PageData<ConstructionUserForm, ConstructionUserQuery>>({ | ||||
|   } | ||||
| }); | ||||
|  | ||||
| /** 返回遍历文件对象 */ | ||||
| const uploadPath = computed(() => { | ||||
|   const list = JSON.parse(JSON.stringify(user_file_type.value)); | ||||
|   for (const item of fileList.value) { | ||||
|     const targetType = item.fileType; | ||||
|     for (let i = 0; i < list.length; i++) { | ||||
|       if (list[i].value == targetType) { | ||||
|         list[i] = { ...list[i], ...item }; // 合并对象 | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   for (let i = 0; i < list.length; i++) { | ||||
|     if (!list[i].hasOwnProperty('fileType')) { | ||||
|       list[i].fileType = list[i].value; | ||||
|     } | ||||
|   } | ||||
|   console.log(list); | ||||
|   return list; | ||||
| }); | ||||
|  | ||||
| const { queryParams, form, rules } = toRefs(data); | ||||
|  | ||||
| /** 查询施工人员列表 */ | ||||
| @ -433,13 +593,13 @@ const getList = async () => { | ||||
| }; | ||||
|  | ||||
| const selectProject = (e: any) => { | ||||
|   //选中项目筛选出项目下的分包单位 | ||||
|   //选中项目筛选出项目下的分包单位并清空分包单位value | ||||
|   contractorList.value = skipOptions.value.filter((item) => item.id == e)[0].contractorList; | ||||
|   skipObject.contractorId = ''; | ||||
| }; | ||||
|  | ||||
| const setUnits = async () => { | ||||
|   //人员迁移 | ||||
|   console.log('🚀 ~ setUnits ~ skipObject:', skipObject); | ||||
|   let res = await transferConstructionUser(skipObject); | ||||
|   if (res.code == 200) { | ||||
|     ElMessage.success(res.msg); | ||||
| @ -483,6 +643,28 @@ const getProjectTeamList = async () => { | ||||
|   loading.value = false; | ||||
| }; | ||||
|  | ||||
| /** 上传安全协议书按钮操作 */ | ||||
|  | ||||
| const updateProjectFile = async () => { | ||||
|   buttonLoading.value = true; | ||||
|   let fileList = uploadPath.value.map((item) => { | ||||
|     return { | ||||
|       fileId: item.path, | ||||
|       fileType: item.fileType | ||||
|     }; | ||||
|   }); | ||||
|   const data = { | ||||
|     userId: currentUserId.value, | ||||
|     fileList | ||||
|   }; | ||||
|   console.log('🚀 ~ updateProjectFile ~ data:', data); | ||||
|   await setConstructionUserFile(data); | ||||
|   proxy?.$modal.msgSuccess('上传成功'); | ||||
|   buttonLoading.value = false; | ||||
|   fileStatus.value = false; | ||||
|   await getList(); | ||||
| }; | ||||
|  | ||||
| const getTeamName = (teamId: string | number) => { | ||||
|   const team = projectTeamOpt.value.find((item: any) => item.value === teamId); | ||||
|   return team ? team.label : teamId; | ||||
| @ -544,6 +726,17 @@ const handleShowDrawer = (row?: ConstructionUserVO) => { | ||||
|   showDetailDrawer.value = true; | ||||
| }; | ||||
|  | ||||
| //下载模板 | ||||
| const downloadTemplate = async () => { | ||||
|   const loadingInstance = ElLoadingService({ | ||||
|     lock: true, | ||||
|     text: 'Loading', | ||||
|     background: 'rgba(0, 0, 0, 0.7)' | ||||
|   }); | ||||
|   await dowloadConstructionUserTemplate({ projectId: currentProject.value.id }); | ||||
|   loadingInstance.close(); | ||||
| }; | ||||
|  | ||||
| /** 人员迁移 */ | ||||
| const handleChange = async (row: ConstructionUserVO) => { | ||||
|   const _id = row?.id || ids.value[0]; | ||||
| @ -554,6 +747,33 @@ const handleChange = async (row: ConstructionUserVO) => { | ||||
|   skip.value = true; | ||||
| }; | ||||
|  | ||||
| //切换人脸 | ||||
| const handleToggle = async (row: ConstructionUserVO) => { | ||||
|   reset(); | ||||
|   skipName.value = row?.userName; | ||||
|   const _id = row?.id || ids.value[0]; | ||||
|   const res = await getConstructionUser(_id); | ||||
|   Object.assign(form.value, res.data); | ||||
|   showFaceDrawer.value = true; | ||||
| }; | ||||
|  | ||||
| const handleExit = async (row: ConstructionUserVO) => { | ||||
|   const _id = row?.id || ids.value[0]; | ||||
|   currentUserId.value = _id; | ||||
|   const res = await getConstructionUserExit({ userId: _id }); | ||||
|   exitList.value = res.data; | ||||
|   exitStatus.value = true; | ||||
| }; | ||||
|  | ||||
| //上传按钮 | ||||
| const handleUpload = async (row: ConstructionUserVO) => { | ||||
|   const _id = row?.id || ids.value[0]; | ||||
|   currentUserId.value = _id; | ||||
|   const res = await listConstructionUserFile({ userId: _id }); | ||||
|   fileList.value = res.data; | ||||
|   fileStatus.value = true; | ||||
| }; | ||||
|  | ||||
| /** 提交按钮 */ | ||||
| const submitForm = () => { | ||||
|   constructionUserFormRef.value?.validate(async (valid: boolean) => { | ||||
| @ -566,6 +786,7 @@ const submitForm = () => { | ||||
|       } | ||||
|       proxy?.$modal.msgSuccess('操作成功'); | ||||
|       dialog.visible = false; | ||||
|       showFaceDrawer.value = false; | ||||
|       await getList(); | ||||
|     } | ||||
|   }); | ||||
| @ -601,6 +822,69 @@ const handleExport = () => { | ||||
|     `constructionUser_${new Date().getTime()}.xlsx` | ||||
|   ); | ||||
| }; | ||||
| /** 用户状态编辑操作 */ | ||||
| const handleEdit = async () => { | ||||
|   if (!vocationalStatus.value) { | ||||
|     proxy?.$modal.msgError('请选择状态'); | ||||
|     return; | ||||
|   } | ||||
|   const data = { | ||||
|     idList: ids.value, | ||||
|     status: vocationalStatus.value | ||||
|   }; | ||||
|   await updateConstructionUserStatus(data); | ||||
|   proxy?.$modal.msgSuccess('修改成功'); | ||||
|   getList(); | ||||
|   ids.value = []; | ||||
|   statusDialog.value = false; | ||||
| }; | ||||
|  | ||||
| //打开修改日薪 | ||||
| const openSalaryDialog = (row: ConstructionUserVO) => { | ||||
|   const _id = row?.id || ids.value[0]; | ||||
|   currentUserId.value = _id; | ||||
|   if (row.salary) { | ||||
|     setSalary(); | ||||
|     return; | ||||
|   } | ||||
|   console.log(row); | ||||
|   salaryStatus.value = true; | ||||
| }; | ||||
|  | ||||
| //变更日薪 | ||||
| const handleSalary = async () => { | ||||
|   if (!changeSalary.value) { | ||||
|     proxy?.$modal.msgError('请输入薪资'); | ||||
|     return; | ||||
|   } | ||||
|   setSalary(); | ||||
| }; | ||||
| const setSalary = async () => { | ||||
|   await updateConstructionUserSalary({ id: currentUserId.value, salary: changeSalary.value }); | ||||
|   proxy?.$modal.msgSuccess('修改成功'); | ||||
|   getList(); | ||||
|   changeSalary.value = ''; | ||||
|   salaryStatus.value = false; | ||||
| }; | ||||
|  | ||||
| // 批量切换在职状态 | ||||
| const handlePlayCardStatus = async (e) => { | ||||
|   playCardLoding.value = true; | ||||
|   const clock = e ? 1 : 0; | ||||
|   await updateConstructionUserPlayCardStatus({ projectId: currentProject.value.id, clock }); | ||||
|   proxy?.$modal.msgSuccess('修改成功'); | ||||
|   getList(); | ||||
|   playCardLoding.value = false; | ||||
| }; | ||||
|  | ||||
| // 切换在职状态 | ||||
| const handleClockStatus = async (row: ConstructionUserVO) => { | ||||
|   playCardLoding.value = true; | ||||
|   await updateConstructionUserPlayCardOneStatus({ id: row.id, clock: row.clock }); | ||||
|   proxy?.$modal.msgSuccess('修改成功'); | ||||
|   getList(); | ||||
|   playCardLoding.value = false; | ||||
| }; | ||||
|  | ||||
| onMounted(() => { | ||||
|   getList(); | ||||
| @ -608,7 +892,7 @@ onMounted(() => { | ||||
|   getProjectTeamList(); | ||||
| }); | ||||
| </script> | ||||
| <style scoped> | ||||
| <style scoped lang="scss"> | ||||
| .block_box { | ||||
|   border: 1px solid #9eccfa; | ||||
|   border-radius: 6px; | ||||
| @ -622,4 +906,22 @@ onMounted(() => { | ||||
|   font-size: 14px; | ||||
|   margin-bottom: 10px; | ||||
| } | ||||
| .image_upload { | ||||
|   border-bottom: 1px solid #e3e3d7; | ||||
|   padding-bottom: 4px; | ||||
| } | ||||
| .title { | ||||
|   font-size: 18px; | ||||
|   font-weight: 700; | ||||
|   display: block; | ||||
|   margin: 10px 0; | ||||
|   width: 100%; | ||||
|   font-family: cursive; | ||||
| } | ||||
| .information { | ||||
|   display: none; | ||||
| } | ||||
| .informationStatus:hover .information { | ||||
|   display: block; | ||||
| } | ||||
| </style> | ||||
|  | ||||
		Reference in New Issue
	
	Block a user