init:first commit of plus-ui

This commit is contained in:
Teo
2025-05-21 11:24:53 +08:00
commit 95e38df6a5
2219 changed files with 2478311 additions and 0 deletions

View File

@ -0,0 +1,585 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="人员姓名" prop="userName">
<el-input v-model="queryParams.userName" placeholder="请输入人员姓名" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="班组" prop="teamId">
<el-select v-model="queryParams.teamId" placeholder="全部" clearable>
<el-option v-for="dict in ProjectTeam" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="工种" prop="typeOfWork">
<el-select v-model="queryParams.typeOfWork" placeholder="全部" clearable>
<el-option v-for="dict in type_of_work" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="打卡日期" prop="clockDate">
<el-date-picker
clearable
v-model="queryParams.clockDate"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择打卡日期"
@change="selectDate"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-row :gutter="20">
<el-col :span="24" :offset="0">
<el-card shadow="hover">
<!-- <template #header>
<PieChart style="width: 1em; height: 1em; vertical-align: middle" />
<span style="vertical-align: middle">命令统计</span>
</template> -->
<div class="el-table el-table--enable-row-hover el-table--medium">
<div ref="commandstats" style="height: 200px" />
</div>
</el-card>
</el-col>
</el-row>
<el-card shadow="never">
<!-- <template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['project:attendance:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['project:attendance:edit']"
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['project:attendance:remove']"
>删除</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['project:attendance:export']">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template> -->
<el-table v-loading="loading" :data="attendanceList">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="主键id" align="center" prop="id" v-if="false" />
<el-table-column label="人员姓名" align="center" prop="userName" />
<el-table-column label="班组" align="center" prop="teamName" />
<el-table-column label="工种" align="center" prop="typeOfWork">
<template #default="scope">
<dict-tag :options="type_of_work" :value="scope.row.typeOfWork" />
</template>
</el-table-column>
<el-table-column label="出勤(天)" align="center" prop="attendanceDays" />
<el-table-column label="迟到(次)" align="center" prop="lateDays" />
<el-table-column label="早退(次)" align="center" prop="leaveEarlyDays" />
<el-table-column label="缺卡(次)" align="center" prop="unClockDays" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" icon="View" @click="handleDetails(scope.row)" v-hasPermi="['project:attendance:edit']">详情</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 添加或修改考勤对话框 -->
<!-- <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="attendanceFormRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="人员id" prop="userId">
<el-input v-model="form.userId" placeholder="请输入人员id" />
</el-form-item>
<el-form-item label="人脸照" prop="facePic">
<image-upload v-model="form.facePic" />
</el-form-item>
<el-form-item label="项目id" prop="projectId">
<el-input v-model="form.projectId" placeholder="请输入项目id" />
</el-form-item>
<el-form-item label="上班打卡时间" prop="onClockTime">
<el-date-picker clearable v-model="form.onClockTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择上班打卡时间">
</el-date-picker>
</el-form-item>
<el-form-item label="下班打卡时间" prop="offClockTime">
<el-date-picker clearable v-model="form.offClockTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择下班打卡时间">
</el-date-picker>
</el-form-item>
<el-form-item label="打卡日期" prop="clockDate">
<el-date-picker clearable v-model="form.clockDate" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择打卡日期">
</el-date-picker>
</el-form-item>
<el-form-item label="1正常,2迟到,3早退,4缺勤,5补卡" prop="clockStatus">
<el-radio-group v-model="form.clockStatus">
<el-radio v-for="dict in clock_status_type" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="代打人员id" prop="pinchUserId">
<el-input v-model="form.pinchUserId" placeholder="请输入代打人员id" />
</el-form-item>
<el-form-item label="多次打卡时间记录" prop="clockRecord">
<el-input v-model="form.clockRecord" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="上下班" prop="commuter">
<el-input v-model="form.commuter" placeholder="请输入上下班" />
</el-form-item>
<el-form-item label="日薪" prop="dailyWage">
<el-input v-model="form.dailyWage" placeholder="请输入日薪" />
</el-form-item>
<el-form-item label="经度" prop="lng">
<el-input v-model="form.lng" placeholder="请输入经度" />
</el-form-item>
<el-form-item label="纬度" prop="lat">
<el-input v-model="form.lat" placeholder="请输入纬度" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog> -->
<!-- 考勤详情对话框 -->
<el-dialog v-model="dialog.details" width="1300px">
<el-calendar ref="calendar" v-model="calendarDay" class="h170 pos-relative">
<template #header="{ date }">
<span>
<el-date-picker v-model="monthValue" type="month" placeholder="请选择月份" @change="handleMonth" />
</span>
<span class="label">{{ date }} {{ dialog.title }}出勤</span>
<div class="status-detail flex items-center justify-between">
<div class="dot1">全天考勤正常</div>
<div class="dot2">当天存在异常迟到早退缺卡</div>
<div class="dot3">当天提交过补卡申请</div>
</div>
</template>
<template #date-cell="{ data }">
<div class="flex-c" @click="handleViewPlayCard(data)">
<p class="time">{{ day(data) }}</p>
<img v-if="!isplayCard(data)" src="@/assets/icons/svg/empty-CZvxqguX.png" /><span v-if="!isplayCard(data)">暂无打卡记录</span>
<div v-if="isplayCard(data)" class="flex-r"><div class="circle" :class="'status' + attendanceStatus(data)"></div></div>
<div v-if="isplayCard(data)" class="flex justify-center flex-col w100% items-center">
<el-button type="primary" plain size="small" class="w70% my-2" v-if="workTime(data)">{{ workTime(data) }} 上班打卡</el-button>
<el-button type="danger" plain size="small" class="w50% my-2" v-else>上班缺卡</el-button>
<span></span>
<el-button type="warning" plain size="small" class="w70%" v-if="workFromTime(data)">{{ workFromTime(data) }} 下班打卡</el-button>
<el-button type="danger" plain size="small" class="w50%" v-else>下班缺卡</el-button>
</div>
</div>
</template>
</el-calendar>
</el-dialog>
</div>
</template>
<script setup name="Attendance" lang="ts">
import {
listAttendance,
getAttendance,
delAttendance,
addAttendance,
updateAttendance,
listAttendanceTwoWeek,
listAttendanceMonth
} from '@/api/project/attendance';
import { option } from '@/api/project/attendance/echarts';
import * as echarts from 'echarts';
import { AttendanceVO, AttendanceQuery, AttendanceForm, AttendanceTwoWeekVO, AttendanceMonthVO } from '@/api/project/attendance/types';
import { listProjectTeam } from '@/api/project/projectTeam';
import { ProjectTeamVO } from '@/api/project/projectTeam/types';
import { useUserStoreHook } from '@/store/modules/user';
import { parseTime } from '@/utils/ruoyi';
const commandstats = ref();
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { clock_status_type, type_of_work } = toRefs<any>(proxy?.useDict('clock_status_type', 'type_of_work'));
import type { CalendarDateType, CalendarInstance } from 'element-plus';
// 获取用户 store
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目
const currentProject = computed(() => userStore.selectedProject);
const ProjectTeam = computed(() => userStore.ProjectTeamList);
const attendanceList = ref<AttendanceVO[]>([]);
const attendanceTwoWeekList = ref<AttendanceTwoWeekVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const calendarDay = ref<Date | null>(null);
const monthValue = ref<Date | null>(null);
const calendarList = ref<AttendanceMonthVO[]>();
const queryFormRef = ref<ElFormInstance>();
const attendanceFormRef = ref<ElFormInstance>();
const commandstatsIntance = ref<any>(null);
const dialog = reactive<DialogOption>({
visible: false,
details: false,
title: ''
});
const echartsOption = ref<any>({});
const initFormData: AttendanceForm = {
id: undefined,
userId: undefined,
facePic: undefined,
onClockTime: undefined,
offClockTime: undefined,
clockDate: undefined,
clockStatus: undefined,
pinchUserId: undefined,
clockRecord: undefined,
commuter: undefined,
dailyWage: undefined,
projectId: currentProject.value.id,
lng: undefined,
lat: undefined,
remark: undefined,
typeOfWork: undefined,
teamId: undefined
};
const data = reactive<PageData<AttendanceForm, AttendanceQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
userName: undefined,
clockDate: undefined,
clockStatus: undefined,
commuter: undefined,
projectId: currentProject.value.id,
typeOfWork: undefined,
teamId: undefined,
params: {}
},
rules: {
id: [{ required: true, message: '主键id不能为空', trigger: 'blur' }],
userId: [{ required: true, message: '人员id不能为空', trigger: 'blur' }],
facePic: [{ required: true, message: '人脸照不能为空', trigger: 'blur' }],
projectId: [{ required: true, message: '项目id不能为空', trigger: 'blur' }],
clockDate: [{ required: true, message: '打卡日期不能为空', trigger: 'blur' }],
clockStatus: [{ required: true, message: '1正常,2迟到,3早退,4缺勤,5补卡不能为空', trigger: 'change' }]
}
});
const day = computed(() => (date) => {
return date.day.split('-').slice(1).join('-');
});
//是否打卡
const isplayCard = computed(() => (date) => {
return calendarList.value.some((item) => item.clockDate == date.day);
});
//打卡时间下标
const playCardIdx = computed(() => (date) => {
return calendarList.value.findIndex((item) => item.clockDate == date.day);
});
//上班时间
const workTime = computed(() => (date) => {
return calendarList.value[playCardIdx.value(date)].attendanceList[0].clockTime?.slice(10);
});
//下班时间
const workFromTime = computed(() => (date) => {
return calendarList.value[playCardIdx.value(date)].attendanceList[1]?.clockTime?.slice(10);
});
//考勤状态
const attendanceStatus = computed(() => (date) => {
return calendarList.value[playCardIdx.value(date)].status;
});
const { queryParams, form, rules } = toRefs(data);
const calendar = ref<CalendarInstance>();
const handleMonth = async (e: any) => {
calendarDay.value = e;
handleCalendarMonth(e);
};
const selectDate = (e: any) => {
handleQuery();
};
const handleCalendarMonth = async (e?) => {
let clockMonth;
if (e) {
clockMonth = parseTime(e, '{y}-{m}');
}
const res = await listAttendanceMonth({ userId: dialog.id, clockMonth });
calendarList.value = res.data;
};
/** 查看打卡记录详情 */
const handleViewPlayCard = async (data: any) => {
if (data.type == 'next-month' || data.type == 'prev-month') {
monthValue.value = data.date;
handleCalendarMonth(monthValue.value);
}
};
/** 查询考勤列表 */
const getList = async () => {
loading.value = true;
const res = await listAttendance(queryParams.value);
attendanceList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 查询近两周考勤列表 */
const getListTwoWeek = async () => {
loading.value = true;
const res = await listAttendanceTwoWeek(queryParams.value);
attendanceTwoWeekList.value = res.data;
echartsOption.value = { ...option(attendanceTwoWeekList.value) };
commandstatsIntance.value.setOption(echartsOption.value);
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
attendanceFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
getListTwoWeek();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
//处理获取到的月份
const incrementMonth = (dateStr: string, monthsToAdd: number) => {
const [yearPart, monthPart] = dateStr.replace(/\s/g, '').split('年');
const year = parseInt(yearPart, 10);
const month = parseInt(monthPart.replace('月', ''), 10);
// 创建一个新的 Date 对象,设置为输入日期的第一天
const date = new Date(year, month - 1, 1);
// 增加一个月
date.setMonth(date.getMonth() + monthsToAdd);
// 提取增加一个月后的年份和月份
const newYear = date.getFullYear();
const newMonth = String(date.getMonth() + 1).padStart(2, '0');
// 返回格式化后的日期字符串
return `${newYear}-${newMonth}`;
};
/** 详情按钮操作 */
const handleDetails = async (row?: AttendanceVO) => {
const res = await listAttendanceMonth({ userId: row?.id });
calendarList.value = res.data;
dialog.details = true;
dialog.id = row?.id;
dialog.title = row?.userName || '';
};
/** 提交按钮 */
const submitForm = () => {
attendanceFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateAttendance(form.value).finally(() => (buttonLoading.value = false));
} else {
await addAttendance(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/** 删除按钮操作 */
// const handleDelete = async (row?: AttendanceVO) => {
// const _ids = row?.id || ids.value;
// await proxy?.$modal.confirm('是否确认删除考勤编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
// await delAttendance(_ids);
// proxy?.$modal.msgSuccess('删除成功');
// await getList();
// };
/** 导出按钮操作 */
// const handleExport = () => {
// proxy?.download(
// 'project/attendance/export',
// {
// ...queryParams.value
// },
// `attendance_${new Date().getTime()}.xlsx`
// );
// };
//初始化图表
const init = () => {
commandstatsIntance.value = echarts.init(commandstats.value, 'macarons');
commandstatsIntance.value.on('click', function (params) {
queryParams.value.clockDate = params.name;
handleQuery();
});
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
getListTwoWeek();
init();
});
</script>
<style lang="scss" scoped>
.label {
font-size: 24px;
position: absolute;
left: 50%;
top: 0;
transform: translate(-50%);
color: #000;
font-weight: 500;
}
.status-detail {
margin: 0 15px;
position: relative;
font-size: 12px;
> div {
margin: 0 15px;
position: relative;
font-size: 12px;
&::before {
position: absolute;
content: '';
display: inline-block;
left: -15px;
top: 30%;
width: 8px;
height: 8px;
border-radius: 50%;
}
}
.dot1 {
&::before {
background-color: #1d6fe9;
}
}
.dot2 {
&::before {
background-color: #f55f4e;
}
}
.dot3 {
&::before {
background-color: #ff8d1a;
}
}
}
.flex-c {
height: 110px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: relative;
.time {
position: absolute;
z-index: 10;
right: 0;
top: 0;
}
img {
width: 50%;
height: 50%;
}
> span {
font-size: 12px;
color: #ccc;
padding-top: 5px;
}
}
.el-calendar-table__row {
height: 100px;
}
.flex-r {
width: 100%;
display: flex;
flex-direction: row;
justify-content: center;
padding-top: 5px;
height: 10px;
.circle {
width: 7px;
height: 7px;
border-radius: 50%;
margin: 0 2px;
position: absolute;
z-index: 10;
right: 12px;
top: 35px;
}
.status2 {
background: #f55f4e;
}
.status1 {
background: #1d6fe9;
}
.status3 {
background: #ff8d1a;
}
}
::v-deep(.el-calendar) {
.el-calendar__body {
height: 600px;
overflow: auto;
}
td {
height: 110px;
.el-calendar-day {
height: 100%;
}
}
}
</style>

View File

@ -0,0 +1,180 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="人员姓名" prop="userName">
<el-input v-model="queryParams.userName" placeholder="请输入人员姓名" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="班组" prop="teamId">
<el-select v-model="queryParams.teamId" placeholder="全部" clearable>
<el-option v-for="dict in ProjectTeam" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="打卡日期" prop="clockDate">
<el-date-picker clearable v-model="queryParams.clockDate" type="date" value-format="YYYY-MM-DD" placeholder="请选择打卡日期" />
</el-form-item>
<el-form-item label="考勤状态" prop="clockStatus">
<el-select v-model="queryParams.clockStatus" placeholder="全部" clearable>
<el-option v-for="dict in clock_status_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<el-table v-loading="loading" :data="attendanceList">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" type="index" width="60" align="center" />
<el-table-column label="人员姓名" align="center" prop="userName" />
<!-- <el-table-column label="上班打卡时间" align="center" prop="onClockTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.onClockTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="下班打卡时间" align="center" prop="offClockTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.offClockTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column> -->
<el-table-column label="上下班" align="center" prop="commuter">
<template #default="scope">
<dict-tag :options="commuter_type" :value="scope.row.commuter" />
</template>
</el-table-column>
<el-table-column label="打卡日期" align="center" prop="clockDate">
<template #default="scope">
<span>{{ parseTime(scope.row.clockDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="打卡时间" align="center" prop="clockTime">
<template #default="scope">
<span>{{
parseTime(scope.row.clockTime, '{y}-{m}-{d} {h}:{i}:{s}') ? parseTime(scope.row.clockTime, '{y}-{m}-{d} {h}:{i}:{s}') : '缺卡'
}}</span>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
</div>
</template>
<script setup name="Attendance" lang="ts">
import { listAttendance, getAttendance, delAttendance, addAttendance, updateAttendance } from '@/api/project/attendanceRecords';
import { AttendanceVO, AttendanceQuery, AttendanceForm } from '@/api/project/attendanceRecords/types';
import { listProjectTeam } from '@/api/project/projectTeam';
import { ProjectTeamVO } from '@/api/project/projectTeam/types';
import { useUserStoreHook } from '@/store/modules/user';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { clock_status_type, commuter_type } = toRefs<any>(proxy?.useDict('clock_status_type', 'commuter_type'));
const attendanceList = ref<AttendanceVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const attendanceFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
// 获取用户 store
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目
const currentProject = computed(() => userStore.selectedProject);
const ProjectTeam = computed(() => userStore.ProjectTeamList);
const initFormData: AttendanceForm = {
id: undefined,
userId: undefined,
facePic: undefined,
projectId: currentProject.value?.id,
onClockTime: undefined,
offClockTime: undefined,
clockDate: undefined,
clockStatus: undefined,
pinchUserId: undefined,
clockRecord: undefined,
commuter: undefined,
dailyWage: undefined,
lng: undefined,
lat: undefined,
remark: undefined
};
const data = reactive<PageData<AttendanceForm, AttendanceQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
userName: undefined,
projectId: currentProject.value?.id,
clockDate: undefined,
clockStatus: undefined,
commuter: undefined,
params: {},
teamId: undefined
},
rules: {
id: [{ required: true, message: '主键id不能为空', trigger: 'blur' }],
userId: [{ required: true, message: '人员id不能为空', trigger: 'blur' }],
facePic: [{ required: true, message: '人脸照不能为空', trigger: 'blur' }],
projectId: [{ required: true, message: '项目id不能为空', trigger: 'blur' }],
clockDate: [{ required: true, message: '打卡日期不能为空', trigger: 'blur' }],
clockStatus: [{ required: true, message: '1正常,2迟到,3早退,4缺勤,5补卡不能为空', trigger: 'change' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询考勤列表 */
const getList = async () => {
loading.value = true;
const res = await listAttendance(queryParams.value);
attendanceList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
});
</script>

View File

@ -0,0 +1,177 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="名字" prop="userName">
<el-input v-model="queryParams.userName" placeholder="请输入名字" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="身份证号码" prop="sfzNumber" label-width="120">
<el-input v-model="queryParams.sfzNumber" placeholder="请输入身份证号码" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete()"
v-hasPermi="['project:constructionBlacklist:remove']"
>删除
</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" :data="constructionBlacklistList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" type="index" width="60" align="center" />
<el-table-column label="名字" align="center" prop="userName" />
<el-table-column label="身份证号码" align="center" prop="sfzNumber" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['project:constructionBlacklist:remove']">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
</div>
</template>
<script setup name="ConstructionBlacklist" lang="ts">
import { delConstructionBlacklist, listConstructionBlacklist } from '@/api/project/constructionBlacklist';
import { ConstructionBlacklistForm, ConstructionBlacklistQuery, ConstructionBlacklistVO } from '@/api/project/constructionBlacklist/types';
import { useUserStoreHook } from '@/store/modules/user';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
// 获取用户 store
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目
const currentProject = computed(() => userStore.selectedProject);
const constructionBlacklistList = ref<ConstructionBlacklistVO[]>([]);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const constructionBlacklistFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const initFormData: ConstructionBlacklistForm = {
projectId: currentProject.value.id,
userId: undefined,
remark: undefined
};
const data = reactive<PageData<ConstructionBlacklistForm, ConstructionBlacklistQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
id: undefined,
projectId: currentProject.value.id,
userId: undefined,
userName: undefined,
sfzNumber: undefined,
params: {}
},
rules: {
projectId: [{ required: true, message: '项目id不能为空', trigger: 'blur' }],
userId: [{ required: true, message: '用户id不能为空', trigger: 'blur' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询黑名单列表 */
const getList = async () => {
loading.value = true;
const res = await listConstructionBlacklist(queryParams.value);
constructionBlacklistList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
constructionBlacklistFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: ConstructionBlacklistVO[]) => {
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
/** 删除按钮操作 */
const handleDelete = async (row?: ConstructionBlacklistVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除黑名单编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delConstructionBlacklist(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
});
</script>

View File

@ -0,0 +1,188 @@
<template>
<div>
<div class="block_box">
<span>用户信息</span>
<el-form label-width="130px">
<el-row :gutter="20" justify="space-around">
<el-col :span="12">
<el-form-item label="人脸照">
<el-image :src="userDetail?.facePicUrl" style="width: 150px; height: 150px" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="姓名">
{{ userDetail?.userName }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系电话">
{{ userDetail?.phone }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="性别">
<dict-tag :options="user_sex_type" :value="userDetail?.sex" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="年龄">
{{ dayjs().diff(dayjs(userDetail?.sfzBirth), 'year') }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="民族">
{{ userDetail?.nation }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="籍贯">
{{ userDetail?.nativePlace }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="身份证号码">
{{ userDetail?.sfzNumber }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="身份证号码">
{{ userDetail?.sfzNumber }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="身份证有效开始期">
{{ dayjs(userDetail?.sfzStart).format('YYYY 年 MM 月 DD 日') }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="身份证有效结束期">
{{ dayjs(userDetail?.sfzEnd).format('YYYY 年 MM 月 DD 日') }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="身份证地址">
{{ userDetail?.sfzSite }}
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<div class="block_box">
<span>银行卡</span>
<el-form label-width="130px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="银行卡号">
{{ userDetail?.yhkNumber }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="银行开户行">
{{ userDetail?.yhkOpeningBank }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="持卡人">
{{ userDetail?.yhkCardholder }}
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<div class="block_box">
<span>单位信息</span>
<el-form label-width="130px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="施工单位">
{{ userDetail?.contractorVo?.name }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工种">
<dict-tag :options="type_of_work" :value="userDetail?.typeOfWork" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<div class="block_box">
<span>其他信息</span>
<el-form label-width="130px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="班组">
{{ userDetail?.teamVo?.teamName }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="打卡状态">
<dict-tag :options="user_clock_type" :value="userDetail?.clock" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="入场时间">
{{ userDetail?.entryDate ? dayjs(userDetail?.entryDate).format('YYYY 年 MM 月 DD 日 HH:mm:ss') : '' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="离场时间">
{{ userDetail?.leaveDate ? dayjs(userDetail?.leaveDate).format('YYYY 年 MM 月 DD 日 HH:mm:ss') : '' }}
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</div>
</template>
<script setup lang="ts">
import { getConstructionUser } from '@/api/project/constructionUser';
import { ConstructionUserVO } from '@/api/project/constructionUser/types';
import dayjs from 'dayjs';
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'));
interface Props {
userId?: string | number;
}
const props = defineProps<Props>();
const loading = ref<boolean>(false);
const userDetail = ref<ConstructionUserVO>();
const getUserDetail = async () => {
loading.value = true;
const res = await getConstructionUser(props.userId);
if (res.data && res.code === 200) {
userDetail.value = res.data;
}
loading.value = false;
};
onMounted(() => {
getUserDetail();
});
watch(
() => props.userId,
(newId, oldId) => {
if (newId !== oldId) {
getUserDetail();
}
}
);
</script>
<style lang="scss" scoped>
.block_box {
border: 1px solid #9eccfa;
border-radius: 6px;
padding: 10px 20px 20px 10px;
margin: 15px;
> span {
color: #409eff;
font-weight: 700;
font-size: 14px;
}
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,93 @@
<template>
<el-button type="primary" @click="handleUpdateFile">保存文件</el-button>
<el-row :gutter="20">
<el-col :span="8">
<el-menu :default-active="activeMenu" @select="handleMenuClick">
<el-menu-item :key="item.value" v-for="item in contractor_file_type" :index="item.value">
<el-space>
<p>{{ item.label }}</p>
<el-tag type="success" v-if="ossIdMap[item.value]">已上传</el-tag>
<el-tag type="warning" v-else>未上传</el-tag>
</el-space>
</el-menu-item>
</el-menu>
</el-col>
<el-col :span="16">
<file-upload
v-model="ossIdMap[activeMenu]"
:limit="20"
:file-size="50"
:file-type="['pdf']"
isDarg
@update:model-value="
(args) => {
handleOssUpdate(args);
}
"
/>
</el-col>
</el-row>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { getContractor, updateContractor } from '@/api/project/contractor';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { contractor_file_type } = toRefs<any>(proxy?.useDict('contractor_file_type'));
interface Props {
contractorId?: string | number;
}
const props = defineProps<Props>();
const loading = ref<boolean>(false);
// 当前选中的菜单项
const activeMenu = ref('0'); // 默认选中第一个
const ossIdMap = ref<Record<string, string>>({});
// 处理菜单点击事件
const handleMenuClick = (index: string) => {
activeMenu.value = index;
};
// 获取公司详情
const getComponentVO = async () => {
loading.value = true;
const res = await getContractor(props.contractorId);
ossIdMap.value = res.data.fileMap ?? { '0': '' };
loading.value = false;
};
const handleOssUpdate = (ossId: string) => {
// 判断 ossId 是否为空
if (ossId === '' || ossId === null || ossId === undefined) {
delete ossIdMap.value[activeMenu.value]; // 删除 key
} else {
ossIdMap.value[activeMenu.value] = ossId; // 直接赋值
}
console.log(ossIdMap.value);
};
const handleUpdateFile = async () => {
loading.value = true;
await updateContractor({
id: props.contractorId,
fileMap: ossIdMap.value
});
proxy?.$modal.msgSuccess('保存成功');
loading.value = false;
};
watch(
() => props.contractorId,
(newId, oldId) => {
if (newId !== oldId) {
getComponentVO();
}
}
);
onMounted(() => {
getComponentVO();
});
</script>

View File

@ -0,0 +1,283 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="公司名称" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入公司名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['project:contractor:add']"> 新增 </el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['project:contractor:edit']"
>修改
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['project:contractor:remove']"
>删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['project:contractor:export']">导出 </el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" :data="contractorList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" type="index" width="60" align="center" />
<el-table-column label="公司名称" align="center" prop="name" />
<el-table-column label="负责人" align="center" prop="principal" />
<el-table-column label="负责人联系电话" align="center" prop="principalPhone" />
<el-table-column label="管理人" align="center" prop="custodian" />
<el-table-column label="管理人联系电话" align="center" prop="custodianPhone" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-space wrap>
<el-button link type="primary" icon="View" @click="handleContractorFile(scope.row)">文件</el-button>
<el-button link type="success" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['project:contractor:edit']">修改 </el-button>
<el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['project:contractor:remove']">
删除
</el-button>
</el-space>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 添加或修改分包单位对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="contractorFormRef" :model="form" :rules="rules" label-width="120px">
<el-form-item label="公司名称" prop="name">
<el-input v-model="form.name" placeholder="请输入公司名称" />
</el-form-item>
<el-form-item label="负责人" prop="principal">
<el-input v-model="form.principal" placeholder="请输入负责人" />
</el-form-item>
<el-form-item label="负责人联系电话" prop="principalPhone">
<el-input v-model="form.principalPhone" placeholder="请输入负责人联系电话" />
</el-form-item>
<el-form-item label="管理人" prop="custodian">
<el-input v-model="form.custodian" placeholder="请输入管理人" />
</el-form-item>
<el-form-item label="管理人联系电话" prop="custodianPhone">
<el-input v-model="form.custodianPhone" placeholder="请输入管理人联系电话" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
<el-dialog title="上传文件" v-model="visible" width="800px">
<contractor-file-dialog :contractor-id="currentContractorId" />
</el-dialog>
</div>
</template>
<script setup name="Contractor" lang="ts">
import { addContractor, delContractor, getContractor, listContractor, updateContractor } from '@/api/project/contractor';
import { ContractorForm, ContractorQuery, ContractorVO } from '@/api/project/contractor/types';
import ContractorFileDialog from '@/views/project/contractor/component/ContractorFileDialog.vue';
import { useUserStoreHook } from '@/store/modules/user';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const contractorList = ref<ContractorVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const contractorFormRef = ref<ElFormInstance>();
// 获取用户 store
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目
const currentProject = computed(() => userStore.selectedProject);
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const initFormData: ContractorForm = {
id: undefined,
name: undefined,
principal: undefined,
principalPhone: undefined,
custodian: undefined,
custodianPhone: undefined,
fileMap: undefined,
remark: undefined,
projectId: currentProject.value.id
};
const data = reactive<PageData<ContractorForm, ContractorQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
orderByColumn: 'createTime',
isAsc: 'desc',
name: undefined,
principal: undefined,
principalPhone: undefined,
custodian: undefined,
custodianPhone: undefined,
projectId: currentProject.value.id,
params: {}
},
rules: {
id: [{ required: true, message: '主键id不能为空', trigger: 'blur' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询分包单位列表 */
const getList = async () => {
loading.value = true;
const res = await listContractor(queryParams.value);
contractorList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
contractorFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: ContractorVO[]) => {
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
/** 新增按钮操作 */
const handleAdd = () => {
reset();
dialog.visible = true;
dialog.title = '添加分包单位';
};
/** 修改按钮操作 */
const handleUpdate = async (row?: ContractorVO) => {
reset();
const _id = row?.id || ids.value[0];
const res = await getContractor(_id);
Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = '修改分包单位';
};
/** 提交按钮 */
const submitForm = () => {
contractorFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
form.value.projectId = currentProject.value.id;
buttonLoading.value = true;
if (form.value.id) {
await updateContractor(form.value).finally(() => (buttonLoading.value = false));
} else {
await addContractor(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: ContractorVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除分包单位编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delContractor(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'project/contractor/export',
{
...queryParams.value
},
`contractor_${new Date().getTime()}.xlsx`
);
};
/** 文件操作 **/
const visible = ref();
const currentContractorId = ref<number | string>(0);
const handleContractorFile = (row?: ContractorVO) => {
currentContractorId.value = row.id ?? 0;
console.log(currentContractorId.value);
visible.value = true;
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
console.log('监听项目id', queryParams.value.projectId, form.value.projectId);
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
});
</script>

View File

@ -0,0 +1,440 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="100px">
<el-form-item label="申请人" prop="userName">
<el-input v-model="queryParams.userName" placeholder="请输入申请人" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="所属班组" prop="leaveType">
<el-select v-model="queryParams.teamId" placeholder="全部" clearable>
<el-option v-for="dict in ProjectTeam" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<!-- <el-form-item label="请假类型" prop="leaveType">
<el-select v-model="queryParams.leaveType" placeholder="请选择请假类型" clearable>
<el-option v-for="dict in user_leave_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item> -->
<el-form-item label="班组长意见" prop="gangerOpinion">
<el-select v-model="queryParams.gangerOpinion" placeholder="全部" clearable>
<el-option v-for="dict in user_opinion_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="管理员意见" prop="managerOpinion">
<el-select v-model="queryParams.managerOpinion" placeholder="全部" clearable>
<el-option v-for="dict in user_opinion_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<!-- <template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['project:leave:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['project:leave:edit']"
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['project:leave:remove']"
>删除</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['project:leave:export']">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template> -->
<el-table v-loading="loading" :data="leaveList">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" align="center" type="index" width="50" />
<el-table-column label="申请人" align="center" prop="userName" />
<el-table-column label="申请请假说明" align="center" prop="userExplain" />
<!-- <el-table-column label="请假申请时间" align="center" prop="userTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.userTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column> -->
<el-table-column label="所属班组" align="center" prop="teamName">
<template #default="scope">
<dict-tag :options="user_leave_type" :value="scope.row.teamName" />
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :options="user_review_status_type" :value="scope.row.status" />
</template>
</el-table-column>
<!-- <el-table-column label="班组长意见" align="center" prop="gangerOpinion">
<template #default="scope">
<dict-tag :options="user_opinion_type" :value="scope.row.gangerOpinion" />
</template>
</el-table-column>
<el-table-column label="班组长说明" align="center" prop="gangerExplain" />
<el-table-column label="班组长操作时间" align="center" prop="gangerTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.gangerTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="管理员意见" align="center" prop="managerOpinion">
<template #default="scope">
<dict-tag :options="user_opinion_type" :value="scope.row.managerOpinion" />
</template>
</el-table-column>
<el-table-column label="管理员说明" align="center" prop="managerExplain" />
<el-table-column label="请假申请时间" align="center" prop="userTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.userTime) }}</span>
</template>
</el-table-column> -->
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="success" icon="View" @click="handleDetail(scope.row)">详情</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 审批对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<div class="pl-xl">
<el-form-item label="是否同意">
<el-radio-group v-model="auditForm.managerOpinion">
<el-radio value="2" size="small">同意</el-radio>
<el-radio value="3" size="small">拒绝</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="拒绝说明" v-if="auditForm.managerOpinion == '3'">
<el-input v-model="auditForm.managerExplain" placeholder="请输入拒绝说明" type="textarea" clearable></el-input>
</el-form-item>
</div>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
<!-- 详情对话框 -->
<el-dialog :title="detailObj.userName + '补卡申请详情'" v-model="dialog.details" width="700px" append-to-body>
<div class="block_box">
<span>补卡申请</span>
<el-form label-width="130px">
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="补卡申请时间">
{{ detailObj.userTime }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="班组长说明">
{{ detailObj.gangerExplain ? detailObj.gangerExplain : '暂无' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="班组长操作时间">
{{ detailObj.gangerTime ? detailObj.gangerTime : '暂无' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="管理员说明">
{{ detailObj.managerExplain ? detailObj.managerExplain : '暂无' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="管理员操作时间">
{{ detailObj.managerTime ? detailObj.managerTime : '暂无' }}
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<div class="block_box">
<span>审核进度</span>
<el-steps style="max-width: 700px" :active="auditProgress" align-center finish-status="success">
<el-step :title="teamStatus ? detailObj.gangerName : '班组长'" :status="teamStatus ? teamStatus : ''">
<template #description>
<div v-if="!teamStatus">审核中</div>
<div v-else>
<span>{{ detailObj.gangerOpinion == '2' ? '同意' : '拒绝' }}</span>
</div>
</template>
</el-step>
<el-step
:title="managerStatus ? detailObj.managerName : '管理员'"
:status="managerStatus ? managerStatus : ''"
v-if="detailObj.gangerOpinion != '3'"
>
<template #description>
<div v-if="!managerStatus">审核中</div>
<div v-else>
<span>{{ detailObj.managerOpinion == '2' ? '同意' : '拒绝' }}</span>
</div>
</template>
</el-step>
<el-step title="结果" :status="resultsStatus">
<template #description>
<div>{{ user_review_status_type[parseInt(detailObj.status) - 1].label }}</div>
</template>
</el-step>
</el-steps>
</div>
</el-dialog>
</div>
</template>
<script setup name="Leave" lang="ts">
import { listLeave, getLeave, delLeave, addLeave, updateLeave, AuditReissueCard } from '@/api/project/leave';
import { LeaveVO, LeaveQuery, LeaveForm } from '@/api/project/leave/types';
import { listProjectTeam } from '@/api/project/projectTeam';
import { ProjectTeamVO } from '@/api/project/projectTeam/types';
import { AuditReissueCardForm, ReissueCardVO } from '@/api/project/reissueCard/types';
import { useUserStoreHook } from '@/store/modules/user';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { user_leave_type, user_opinion_type, user_review_status_type } = toRefs<any>(
proxy?.useDict('user_leave_type', 'user_opinion_type', 'user_review_status_type')
);
const detailObj = ref<ReissueCardVO>({
userName: undefined,
id: undefined,
userExplain: undefined,
userTime: undefined,
gangerName: undefined,
gangerOpinion: undefined,
gangerExplain: undefined,
gangerTime: undefined,
managerOpinion: undefined,
managerExplain: undefined,
managerTime: undefined,
remark: undefined,
status: undefined,
managerName: undefined
});
const leaveList = ref<LeaveVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const leaveFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: '',
details: false
});
// 获取用户 store
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目
const currentProject = computed(() => userStore.selectedProject);
const ProjectTeam = computed(() => userStore.ProjectTeamList);
const initFormData: LeaveForm = {
id: undefined,
userId: undefined,
userName: undefined,
userExplain: undefined,
userTime: undefined,
leaveType: undefined,
startTime: undefined,
endTime: undefined,
gangerId: undefined,
gangerName: undefined,
gangerOpinion: undefined,
gangerExplain: undefined,
gangerTime: undefined,
managerOpinion: undefined,
managerExplain: undefined,
managerTime: undefined,
projectId: undefined,
teamId: undefined,
remark: undefined
};
const data = reactive<PageData<LeaveForm, LeaveQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
userName: undefined,
leaveType: undefined,
gangerOpinion: undefined,
managerOpinion: undefined,
projectId: undefined,
teamId: undefined,
params: {}
},
rules: {
id: [{ required: true, message: '主键id不能为空', trigger: 'blur' }],
userId: [{ required: true, message: '申请人id不能为空', trigger: 'blur' }],
userName: [{ required: true, message: '申请人名字不能为空', trigger: 'blur' }],
leaveType: [{ required: true, message: '请假类型不能为空', trigger: 'change' }],
startTime: [{ required: true, message: '请假开始时间不能为空', trigger: 'blur' }],
endTime: [{ required: true, message: '请假结束时间不能为空', trigger: 'blur' }],
gangerOpinion: [{ required: true, message: '班组长意见不能为空', trigger: 'change' }],
managerOpinion: [{ required: true, message: '管理员意见不能为空', trigger: 'change' }],
projectId: [{ required: true, message: '项目id不能为空', trigger: 'blur' }]
}
});
const auditForm = reactive<AuditReissueCardForm>({
id: undefined,
managerOpinion: '2',
managerExplain: undefined
});
const { queryParams, form, rules } = toRefs(data);
//审核进度
const auditProgress = computed(() => {
if (auditStatus.value) return 3;
if (managerStatus.value) return 2;
if (teamStatus.value) return 1;
return 0;
});
//审核状态
const auditStatus = computed(() => {
if (detailObj.value.status == '3' || detailObj.value.status == '4') return true;
return false;
});
//管理员审核状态
const managerStatus = computed(() => {
switch (detailObj.value.managerOpinion) {
case '1':
return false;
case '2':
return 'success';
case '3':
return 'error';
}
});
//班组审核状态
const teamStatus = computed(() => {
switch (detailObj.value.gangerOpinion) {
case '1':
return false;
case '2':
return 'success';
case '3':
return 'error';
}
});
//结果状态
const resultsStatus = computed(() => {
if (detailObj.value.status == '3') return 'success';
if (detailObj.value.status == '4') return 'error';
return '';
});
/** 查询施工人员请假申请列表 */
const getList = async () => {
loading.value = true;
const res = await listLeave(queryParams.value);
leaveList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 提交按钮 */
const submitForm = async () => {
await AuditReissueCard(auditForm);
proxy?.$modal.msgSuccess('审批成功');
dialog.visible = false;
await getList();
};
const handleDetail = (row: ReissueCardVO) => {
detailObj.value = row;
console.log('🚀 ~ handleDetail ~ row:', row);
dialog.details = true;
};
/** 审批按钮操作 */
const handleUpdate = async (row?: LeaveVO) => {
reset();
const _id = row?.id || ids.value[0];
auditForm.id = _id;
dialog.visible = true;
dialog.title = '修改施工人员补卡申请';
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'project/leave/export',
{
...queryParams.value
},
`leave_${new Date().getTime()}.xlsx`
);
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
});
</script>
<style lang="scss" scoped>
.block_box {
border: 1px solid #9eccfa;
border-radius: 6px;
padding: 10px 20px 20px 10px;
margin: 15px;
> span {
color: #409eff;
font-weight: 700;
font-size: 14px;
}
}
</style>

View File

@ -0,0 +1,584 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="项目名称" prop="projectName">
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="项目简称" prop="shortName">
<el-input v-model="queryParams.shortName" placeholder="请输入项目简称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['project:project:add']">新增 </el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['project:project:edit']"
>修改
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['project:project:remove']"
>删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['project:project:export']">导出 </el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" :data="projectList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" type="index" width="60" align="center" />
<el-table-column label="项目名称" align="center" prop="projectName" />
<el-table-column label="项目简称" align="center" prop="shortName" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :options="sys_normal_disable" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="项目类型" align="center" prop="projectType" width="120">
<template #default="scope">
<dict-tag :options="project_type" :value="scope.row.projectType" />
</template>
</el-table-column>
<el-table-column label="项目类别" align="center" prop="projectCategory">
<template #default="scope">
<dict-tag :options="project_category_type" :value="scope.row.projectCategory" />
</template>
</el-table-column>
<el-table-column label="负责人" align="center" prop="principal" />
<el-table-column label="负责人电话" align="center" prop="principalPhone" width="120" />
<el-table-column label="实际容量(M)" align="center" prop="actual" width="100" />
<el-table-column label="计划容量(M)" align="center" prop="plan" width="100" />
<el-table-column label="开工时间" align="center" prop="onStreamTime" width="120" />
<el-table-column label="打卡范围" align="center" prop="punchRange" />
<el-table-column label="设计总量" align="center" prop="designTotal" />
<el-table-column label="是否上传DXF" align="center" prop="designId" width="140">
<template #default="scope">
<el-link
:type="scope.row.designId ? 'primary' : 'default'"
:disabled="!scope.row.designId"
@click="handleOpenLayer(scope.row)"
v-loading.fullscreen.lock="fullscreenLoading"
>{{ scope.row.designId ? '已上传' : '未上传' }}</el-link
>
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180" />
<el-table-column fixed="right" label="操作" align="center" class-name="small-padding fixed-width" width="400">
<template #default="scope">
<el-space>
<el-button link type="primary" icon="FolderOpened" @click="handleShowUpload(scope.row)">导入安全协议书 </el-button>
<file-upload
:limit="1"
:fileSize="200"
:fileType="['dxf']"
v-model:model-value="dxfFile"
uploadUrl="/project/projectFile/upload/dxf"
:data="{ projectId: scope.row.id }"
>
<el-button link type="primary" icon="upload">上传DXF </el-button>
</file-upload>
<el-button link type="success" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['project:project:edit']">修改 </el-button>
<el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['project:project:remove']">删除 </el-button>
</el-space>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 添加或修改项目对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="770px" append-to-body>
<el-form ref="projectFormRef" :model="form" :rules="rules" label-width="100px">
<div class="block-box">
<div class="">基础信息</div>
<el-row :gutter="20">
<el-col :span="12" :offset="0">
<el-form-item label="项目名称" prop="projectName">
<el-input v-model="form.projectName" placeholder="请输入项目名称" />
</el-form-item>
</el-col>
<el-col :span="12" :offset="0">
<el-form-item label="项目简称" prop="shortName">
<el-input v-model="form.shortName" placeholder="请输入项目简称" />
</el-form-item>
</el-col>
<el-col :span="12" :offset="0">
<el-form-item label="负责人" prop="principal">
<el-input v-model="form.principal" placeholder="请输入负责人" />
</el-form-item>
</el-col>
<el-col :span="12" :offset="0">
<el-form-item label="负责人电话" prop="principalPhone">
<el-input v-model="form.principalPhone" placeholder="请输入负责人电话" type="number" />
</el-form-item>
</el-col>
<el-col :span="12" :offset="0">
<el-form-item label="项目类型" prop="projectType" label-width="100px">
<el-select v-model="form.projectType" placeholder="请选择项目类型" clearable>
<el-option v-for="dict in project_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" :offset="0">
<el-form-item label="项目类别" prop="projectCategory" label-width="100px">
<el-select v-model="form.projectCategory" placeholder="请选择项目类别" clearable>
<el-option v-for="dict in project_category_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" :offset="0">
<el-form-item label="开工时间" prop="onStreamTime">
<el-date-picker clearable v-model="form.onStreamTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择开工时间" />
</el-form-item>
</el-col>
<el-col :span="12" :push="3">
<el-button type="primary" size="default" @click="amapStatus = true">获取经纬度</el-button>
</el-col>
<el-col :span="12" :offset="0">
<el-form-item label="经度" prop="lng">
<el-input v-model="form.lng" disabled placeholder="请输入经度" />
</el-form-item>
</el-col>
<el-col :span="12" :offset="0">
<el-form-item label="纬度" prop="lat">
<el-input v-model="form.lat" disabled placeholder="请输入纬度" />
</el-form-item>
</el-col>
<el-col :span="24" :offset="0">
<el-form-item label="项目地址" prop="projectSite">
<el-input v-model="form.projectSite" disabled placeholder="请输入项目地址" />
</el-form-item>
</el-col>
<el-col :span="12" :offset="0">
<el-form-item label="计划容量(M)" prop="plan">
<el-input v-model="form.plan" placeholder="请输入计划容量" />
</el-form-item>
</el-col>
<el-col :span="12" :offset="0">
<el-form-item label="实际容量(M)" prop="actual">
<el-input v-model="form.actual" placeholder="请输入实际容量" />
</el-form-item>
</el-col>
<el-col :span="12" :offset="0">
<el-form-item label="设计总量(M)" prop="designTotal">
<el-input v-model="form.designTotal" placeholder="请输入设计总量" />
</el-form-item>
</el-col>
<el-col :span="24" :offset="0">
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入内容" />
</el-form-item>
</el-col>
<el-col :span="12" :offset="0">
<el-form-item label="项目排序" prop="remark">
<el-input-number v-model="form.sort" :min="0" :max="10000" />
</el-form-item>
</el-col>
</el-row>
</div>
<div class="block-box">
<div class="">打卡设置</div>
<el-row :gutter="20">
<el-col :span="12" :offset="0">
<el-form-item label="打卡开始时间" prop="playCardStart" label-width="110px">
<!-- <el-time-picker value-format="HH:mm" v-model="form.playCardStart" placeholder="请输入打卡开始时间" /> -->
<el-time-select
v-model="form.playCardStart"
style="width: 100%"
class="mr-4"
placeholder="请输入打卡开始时间"
value-format="HH:mm"
start="00:00"
step="00:15"
end="23:59"
/>
</el-form-item>
</el-col>
<el-col :span="12" :offset="0">
<el-form-item label="打卡结束时间" prop="playCardEnd" label-width="110px">
<!-- <el-time-picker value-format="HH:mm" v-model="form.playCardEnd" placeholder="请输入打卡结束时间" /> -->
<el-time-select
v-model="form.playCardEnd"
style="width: 100%"
:min-time="form.playCardStart"
class="mr-4"
placeholder="请输入打卡结束时间"
value-format="HH:mm"
start="00:00"
step="00:15"
end="23:59"
/>
</el-form-item>
</el-col>
<el-col :span="24" :offset="0">
<el-form-item label="安全协议书" prop="securityAgreement">
<file-upload v-model="form.securityAgreement" :limit="1" :file-type="['pdf']" :file-size="50" />
</el-form-item>
</el-col>
</el-row>
</div>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
<el-dialog v-model="uploadVisible" title="上传安全协议书" width="400">
<file-upload v-model="fileUploadParam.securityAgreement" :limit="1" :file-type="['pdf']" :file-size="50" />
<template #footer>
<div class="dialog-footer">
<el-button v-loading="buttonLoading" type="primary" @click="updateProjectFile"> 提交</el-button>
<el-button @click="uploadVisible = false">取消</el-button>
</div>
</template>
</el-dialog>
<!-- //选取项目地址弹窗 -->
<el-dialog v-model="amapStatus" :title="form.projectName + '-获取经纬度'" width="80%">
<amap height="620px" @setLocation="setPoi"></amap>
</el-dialog>
<!-- 选取方阵地址 -->
<el-dialog title="设置方阵" v-model="polygonStatus" width="1400px" :close-on-click-modal="false">
<open-layers-map
:project-id="projectId"
:design-id="designId"
@handleCheckChange="setCheckedNodes"
@close="polygonStatus = false"
></open-layers-map>
</el-dialog>
</div>
</template>
<script setup name="Project" lang="ts">
import {
addProject,
addProjectFacilities,
addProjectPilePoint,
addProjectSquare,
delProject,
getProject,
listProject,
updateProject
} from '@/api/project/project';
import { ProjectForm, ProjectQuery, ProjectVO, locationType } from '@/api/project/project/types';
import amap from '@/components/amap/index.vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { sys_normal_disable, project_category_type, project_type } = toRefs<any>(
proxy?.useDict('sys_normal_disable', 'project_category_type', 'project_type')
);
const projectList = ref<ProjectVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const amapStatus = ref(false);
const queryFormRef = ref<ElFormInstance>();
const projectFormRef = ref<ElFormInstance>();
const polygonStatus = ref(false);
const dxfFile = ref(null);
const projectId = ref<string>('');
const designId = ref<string>('');
//被选中的节点
const nodes = ref<any>([]);
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const jsonData = ref(null);
const fullscreenLoading = ref(false);
const initFormData: ProjectForm = {
id: undefined,
projectName: undefined,
shortName: undefined,
pId: undefined,
status: undefined,
picUrl: undefined,
remark: undefined,
projectType: undefined,
projectCategory: undefined,
deletedAt: undefined,
projectSite: undefined,
principal: undefined,
principalPhone: undefined,
actual: undefined,
lng: undefined,
lat: undefined,
plan: undefined,
onStreamTime: undefined,
playCardStart: undefined,
playCardEnd: undefined,
designTotal: undefined,
securityAgreement: undefined,
sort: 0,
showHidden: undefined,
isDelete: undefined
};
const data = reactive<PageData<ProjectForm, ProjectQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
projectName: undefined,
shortName: undefined,
pId: undefined,
status: undefined,
picUrl: undefined,
projectType: undefined,
projectCategory: undefined,
deletedAt: undefined,
projectSite: undefined,
principal: undefined,
principalPhone: undefined,
actual: undefined,
lng: undefined,
lat: undefined,
plan: undefined,
onStreamTime: undefined,
playCardStart: undefined,
playCardEnd: undefined,
designTotal: undefined,
securityAgreement: undefined,
sort: undefined,
showHidden: undefined,
isDelete: undefined,
params: {}
},
rules: {
playCardStart: [{ required: true, message: '打卡开始时间不能为空', trigger: 'blur' }],
playCardEnd: [{ required: true, message: '打卡结束时间不能为空', trigger: 'blur' }],
projectName: [{ required: true, message: '项目名称不能为空', trigger: 'blur' }],
shortName: [{ required: true, message: '项目简称不能为空', trigger: 'blur' }],
principalPhone: [{ required: true, message: '负责人电话不能为空', trigger: 'blur' }],
principal: [{ required: true, message: '负责人不能为空', trigger: 'blur' }],
projectType: [{ required: true, message: '项目类型不能为空', trigger: 'blur' }],
projectCategory: [{ required: true, message: '项目类别不能为空', trigger: 'blur' }],
projectSite: [{ required: true, message: '项目地址不能为空', trigger: 'blur' }],
actual: [{ required: true, message: '实际容量不能为空', trigger: 'blur' }],
lng: [{ required: true, message: '经度不能为空', trigger: 'blur' }],
lat: [{ required: true, message: '纬度不能为空', trigger: 'blur' }],
plan: [{ required: true, message: '计划容量不能为空', trigger: 'blur' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询项目列表 */
const getList = async () => {
loading.value = true;
const res = await listProject(queryParams.value);
projectList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
projectFormRef.value?.resetFields();
};
// 设置位置信息
const setPoi = (location: locationType) => {
if (location) {
console.log('🚀 ~ setPoi ~ poi:', location);
form.value.lng = location.lng;
form.value.lat = location.lat;
form.value.projectSite = location.projectSite;
}
amapStatus.value = false;
};
//设置需要上传的节点
const setCheckedNodes = (nodeList: any) => {
nodes.value = nodeList;
};
//上传节点
// const addFacilities = async () => {
// if (!layerType.value) {
// return proxy?.$modal.msgError('请选择图层类型');
// }
// if (!nodes.value.length) {
// return proxy?.$modal.msgError('请选择需要上传的图层');
// }
// const data = {
// projectId: projectId.value,
// nameGeoJson: null,
// locationGeoJson: null,
// pointGeoJson: null
// };
// loading.value = true;
// if (layerType.value == 1) {
// if (nodes.value[0].option == '名称') {
// data.nameGeoJson = jsonData.value[nodes.value[0].location.index];
// data.locationGeoJson = jsonData.value[nodes.value[1].location.index];
// } else {
// data.nameGeoJson = jsonData.value[nodes.value[1].location.index];
// data.locationGeoJson = jsonData.value[nodes.value[0].location.index];
// }
// await addProjectFacilities(data);
// await proxy?.$modal.msgSuccess('添加成功');
// } else if (layerType.value == 2) {
// data.pointGeoJson = jsonData.value[nodes.value[0].location.index];
// await addProjectPilePoint(data);
// await proxy?.$modal.msgSuccess('添加成功');
// } else if (layerType.value == 3) {
// if (nodes.value[0].option == '名称') {
// data.nameGeoJson = jsonData.value[nodes.value[0].location.index];
// data.locationGeoJson = jsonData.value[nodes.value[1].location.index];
// } else {
// data.nameGeoJson = jsonData.value[nodes.value[1].location.index];
// data.locationGeoJson = jsonData.value[nodes.value[0].location.index];
// }
// await addProjectSquare(data);
// await proxy?.$modal.msgSuccess('添加成功');
// }
// loading.value = false;
// };
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: ProjectVO[]) => {
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
/** 新增按钮操作 */
const handleAdd = () => {
reset();
dialog.visible = true;
dialog.title = '添加项目';
};
/** 修改按钮操作 */
const handleUpdate = async (row?: ProjectVO) => {
reset();
const _id = row?.id || ids.value[0];
const res = await getProject(_id);
Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = '修改-' + form.value.projectName;
};
/** 上传安全协议书按钮操作 */
const uploadVisible = ref<boolean>(false);
const fileUploadParam = ref<{ id: string | number; securityAgreement: string }>({
id: undefined,
securityAgreement: undefined
});
const handleShowUpload = (row?: ProjectVO) => {
fileUploadParam.value.securityAgreement = row.securityAgreement;
fileUploadParam.value.id = row.id;
uploadVisible.value = true;
};
const handleOpenLayer = async (row: ProjectVO) => {
polygonStatus.value = true;
projectId.value = row.id;
designId.value = row.designId;
};
const updateProjectFile = async () => {
buttonLoading.value = true;
await updateProject(fileUploadParam.value);
proxy?.$modal.msgSuccess('上传成功');
buttonLoading.value = false;
uploadVisible.value = false;
await getList();
};
/** 提交按钮 */
const submitForm = () => {
projectFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateProject(form.value).finally(() => (buttonLoading.value = false));
} else {
await addProject(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: ProjectVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除项目编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delProject(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'project/project/export',
{
...queryParams.value
},
`project_${new Date().getTime()}.xlsx`
);
};
onMounted(() => {
getList();
});
</script>
<style scoped>
.block-box {
border: 1px solid #9eccfa;
border-radius: 6px;
padding: 10px 20px 0 10px;
margin-bottom: 20px;
}
.block-box > div {
color: #409eff;
font-weight: 700;
font-size: 14px;
margin-bottom: 10px;
}
</style>

View File

@ -0,0 +1,86 @@
<template>
<div>
<div>
<el-transfer v-model="selectedProjects" :data="allProjects" filterable :titles="['项目列表', '已关联项目']" @change="handleTransferChange" />
</div>
<div style="text-align: right; margin-top: 20px">
<el-button type="primary" @click="$emit('close')">关闭</el-button>
</div>
</div>
</template>
<script lang="ts" setup>
import { defineProps, onMounted, ref, watch } from 'vue';
import { listProject } from '@/api/project/project';
import { addNewProjectRelevancy, listUserProjects, removeNewProjectRelevancy } from '@/api/project/projectRelevancy';
import { ProjectRelevancyVO } from '@/api/project/projectRelevancy/types';
// **从父组件接收 `userId`**
const props = defineProps<{ userId: number | string }>();
// **所有项目列表**
const allProjects = ref<{ key: number | string; label: string }[]>([]);
// **已关联的项目 ID 列表**
const selectedProjects = ref<(number | string)[]>([]);
// **获取所有项目列表**
const getProjectList = async () => {
try {
const res = await listProject();
allProjects.value = res.rows.map((project) => ({
key: project.id,
label: project.projectName
}));
} catch (error) {
console.error('获取项目列表失败:', error);
}
};
const getUserProjects = async () => {
if (!props.userId) return;
try {
const res = await listUserProjects({ userId: props.userId });
selectedProjects.value = Array.isArray(res.rows) ? res.rows.map((item: ProjectRelevancyVO) => item.projectId) : [];
} catch (error) {
console.error('获取用户关联的项目失败:', error);
selectedProjects.value = []; // 请求失败时清空列表
}
};
// **监听 `userId` 变化,重新加载关联数据**
watch(
() => props.userId,
async (newUserId) => {
if (newUserId) {
await getUserProjects();
}
},
{ immediate: true }
);
// **处理穿梭框变更**
const handleTransferChange = async (_: number[], direction: 'left' | 'right', movedKeys: number[]) => {
try {
if (direction === 'right') {
// **添加关联**
await addNewProjectRelevancy({
userId: props.userId,
projectIdList: movedKeys
});
} else {
// **移除关联**
await removeNewProjectRelevancy({
userId: props.userId,
projectIdList: movedKeys
});
}
} catch (error) {
console.error('更新项目关联失败:', error);
}
};
// **初始化数据**
onMounted(async () => {
await getProjectList();
});
</script>

View File

@ -0,0 +1,318 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="用户ID" prop="userId">
<el-input v-model="queryParams.userId" placeholder="请输入用户ID" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="项目ID" prop="projectId">
<el-input v-model="queryParams.projectId" placeholder="请输入项目ID" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['project:projectRelevancy:add']">新增 </el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['project:projectRelevancy:edit']"
>修改
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['project:projectRelevancy:remove']"
>删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['project:projectRelevancy:export']">导出 </el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" :data="projectRelevancyList" @selection-change="handleSelectionChange">
<el-table-column prop="id" label="关联ID" width="180" />
<el-table-column prop="userId" label="用户ID" width="100" />
<el-table-column prop="projectId" label="项目ID" width="180" />
<el-table-column prop="project.projectName" label="项目名称" width="200" />
<el-table-column prop="project.type" label="项目类型" width="150" />
<el-table-column prop="project.projectSite" label="项目地址" width="200" />
<el-table-column prop="project.principal" label="负责人" width="120" />
<el-table-column prop="project.principalPhone" label="联系电话" width="150" />
<el-table-column prop="project.onStreamTime" label="上线时间" width="150" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['project:projectRelevancy:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button
link
type="primary"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['project:projectRelevancy:remove']"
></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<!-- 添加 ShuttleFrame 弹窗 -->
<el-dialog v-model="shuttleVisible" title="编辑关联项目" width="auto" destroy-on-close>
<shuttle-frame :userId="selectedUserId" @close="shuttleVisible = false" />
</el-dialog>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 添加或修改系统用户与项目关联对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="projectRelevancyFormRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="用户ID" prop="userId">
<el-select v-model="form.userId" placeholder="请选择用户">
<el-option v-for="user in userList" :key="user.userId" :label="user.nickName" :value="user.userId" />
</el-select>
</el-form-item>
<el-form-item label="项目ID" prop="projectId">
<!-- 项目ID下拉选择框 -->
<el-select v-model="form.projectId" placeholder="请选择项目ID" @change="onProjectChange">
<el-option v-for="project in projectList" :key="project.id" :label="project.projectName" :value="project.id" />
</el-select>
</el-form-item>
</el-form>
<div v-if="selectedProject" style="padding: 0px 100px">
<p><strong>项目名称:</strong> {{ selectedProject.projectName }}</p>
<p><strong>项目类型:</strong> {{ selectedProject.type }}</p>
<p><strong>项目地址:</strong> {{ selectedProject.projectSite }}</p>
<p><strong>负责人:</strong> {{ selectedProject.principal }}</p>
<p><strong>联系电话:</strong> {{ selectedProject.principalPhone }}</p>
</div>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="ProjectRelevancy" lang="ts">
import { addProjectRelevancy, delProjectRelevancy, listProjectRelevancy, updateProjectRelevancy } from '@/api/project/projectRelevancy';
import { listProject } from '@/api/project/project';
import { listUser } from '@/api/system/user';
import { ProjectRelevancyForm, ProjectRelevancyQuery, ProjectRelevancyVO } from '@/api/project/projectRelevancy/types';
import ShuttleFrame from './component/ShuttleFrame.vue';
import { UserVO } from '@/api/system/user/types';
import { ProjectVO } from '@/api/project/project/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const projectRelevancyList = ref<ProjectRelevancyVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const projectRelevancyFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const initFormData: ProjectRelevancyForm = {
id: undefined,
userId: undefined,
projectId: undefined,
deletedAt: undefined
};
const data = reactive<PageData<ProjectRelevancyForm, ProjectRelevancyQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
orderByColumn: 'createTime',
isAsc: 'desc',
userId: undefined,
projectId: undefined,
deletedAt: undefined,
params: {}
},
rules: {
id: [{ required: true, message: '主键ID不能为空', trigger: 'blur' }],
userId: [{ required: true, message: '用户ID不能为空', trigger: 'blur' }],
projectId: [{ required: true, message: '项目ID不能为空', trigger: 'blur' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询系统用户与项目关联列表 */
const getList = async () => {
loading.value = true;
const res = await listProjectRelevancy(queryParams.value);
projectRelevancyList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
projectRelevancyFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: ProjectRelevancyVO[]) => {
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
/** 新增按钮操作 */
const handleAdd = () => {
reset();
dialog.visible = true;
dialog.title = '添加系统用户与项目关联';
};
const shuttleVisible = ref(false);
const selectedUserId = ref<string | number>();
const handleUpdate = (row?: ProjectRelevancyVO) => {
const currentRow = row || projectRelevancyList.value.find((item) => item.id === ids.value[0]);
if (currentRow) {
selectedUserId.value = currentRow.userId;
shuttleVisible.value = true;
}
};
/** 提交按钮 */
const submitForm = () => {
projectRelevancyFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateProjectRelevancy(form.value).finally(() => (buttonLoading.value = false));
} else {
await addProjectRelevancy(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: ProjectRelevancyVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除系统用户与项目关联编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delProjectRelevancy(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'project/projectRelevancy/export',
{
...queryParams.value
},
`projectRelevancy_${new Date().getTime()}.xlsx`
);
};
const projectList = ref<any[]>([]);
const projectItem = new Map();
const selectedProject = ref<any | null>(null);
// 获取项目列表的方法
const getProjectList = async () => {
try {
const res = await listProject();
const projectListData = res.rows;
projectList.value = projectListData;
// 将项目详情存入 Map
projectListData.forEach((project: ProjectVO) => {
projectItem.set(project.id, {
projectName: project.projectName,
type: project.type,
projectSite: project.projectSite,
principal: project.principal,
principalPhone: project.principalPhone
});
});
} catch (error) {
console.error('获取项目列表失败:', error);
}
};
// 当选择项目时触发
const onProjectChange = (projectId: string) => {
selectedProject.value = projectItem.get(projectId) || null;
};
//获取新增用户列表方法
const userList = ref<{ userId: string | number; nickName: string }[]>([]);
const getUserList = async () => {
try {
const response = await listUser({
pageNum: 1,
pageSize: 100
});
userList.value = response.rows.map((user: UserVO) => ({
userId: user.userId,
nickName: user.nickName
}));
} catch (error) {
console.error('获取用户列表失败:', error);
}
};
onMounted(() => {
getList();
getProjectList();
getUserList();
});
</script>
<style></style>

View File

@ -0,0 +1,368 @@
<template>
<div>
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="施工人员" prop="memberName">
<el-input v-model="queryParams.memberName" placeholder="请输入施工人员" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="岗位" prop="postId">
<el-select v-model="queryParams.postId" clearable placeholder="请选择岗位">
<el-option v-for="item in user_post_type" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- <el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button size="small" type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['project:projectTeamMember:add']"> 新增 </el-button>
</el-col>
<el-col :span="1.5">
<el-button
size="small"
type="success"
plain
icon="Edit"
:disabled="single"
@click="handleUpdate()"
v-hasPermi="['project:projectTeamMember:edit']"
>
修改
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
size="small"
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete()"
v-hasPermi="['project:projectTeamMember:remove']"
>
删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button size="small" type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['project:projectTeamMember:export']">
导出
</el-button>
</el-col>
</el-row> -->
<el-table size="small" v-loading="loading" :data="projectTeamMemberList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" type="index" width="60" align="center" />
<el-table-column label="施工人员" align="center" prop="memberName" />
<el-table-column label="岗位" align="center" prop="postId">
<template #default="scope">
<dict-tag :options="user_post_type" :value="scope.row.postId" />
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-space wrap>
<el-button link type="success" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['project:projectTeamMember:edit']">
修改
</el-button>
<el-button link type="danger" icon="Position" @click="handleExit(scope.row)" v-hasPermi="['project:projectTeamMember:remove']">
退场
</el-button>
</el-space>
</template>
</el-table-column>
</el-table>
<pagination
size="small"
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改项目班组下的成员对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="projectTeamMemberFormRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="施工人员" prop="memberId" v-if="!form.id">
<el-select v-model="form.memberId" clearable placeholder="请选择人员" filterable>
<el-option v-for="item in userNotInTeamOpt" :key="item.value" :label="item.label" :value="item.value" />
<pagination
size="small"
v-show="userNotInTeamTotal > 0"
:total="userNotInTeamTotal"
v-model:page="userQueryParams.pageNum"
v-model:limit="userQueryParams.pageSize"
@pagination="getUserListNotInTeam"
/>
</el-select>
</el-form-item>
<el-form-item label="岗位" prop="postId">
<el-select v-model="form.postId" clearable placeholder="请选择岗位">
<el-option v-for="item in user_post_type" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
<!-- 上传退场记录 -->
<el-dialog title="员工离场" v-model="memberStatus" width="30%">
<el-form :model="memberForm" ref="memberFormRef" :rules="memberRules" label-width="100px" :inline="false">
<el-form-item label="用户名">
<el-input v-model="memberForm.userName" disabled></el-input>
</el-form-item>
<el-form-item label="退场文件">
<file-upload v-model="memberForm.filePath" :limit="10" :is-show-tip="false" :file-size="50" />
</el-form-item>
<el-form-item label="备注">
<el-input v-model="memberForm.remark" placeholder="请输入备注" type="textarea"></el-input>
</el-form-item>
</el-form>
<template #footer>
<span>
<el-button type="primary" @click="submitMemberForm" :loading="buttonLoading">确定</el-button>
<el-button @click="memberStatus = false">取消</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ProjectTeamVO } from '@/api/project/projectTeam/types';
import { ProjectTeamMemberForm, ProjectTeamMemberQuery, ProjectTeamMemberVO } from '@/api/project/projectTeamMember/types';
import {
addProjectTeamMember,
delProjectTeamMember,
getProjectTeamMember,
listProjectTeamMember,
updateProjectTeamMember
} from '@/api/project/projectTeamMember';
import { computed, reactive, ref } from 'vue';
import { useUserStoreHook } from '@/store/modules/user';
import { listConstructionUser, delConstructionUserMember } from '@/api/project/constructionUser';
import { ConstructionUserQuery, ConstructionUserVO, ConstructionUserMembeForm } from '@/api/project/constructionUser/types';
// 获取用户 store
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目
const currentProject = computed(() => userStore.selectedProject);
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { user_post_type } = toRefs<any>(proxy?.useDict('user_post_type'));
const memberStatus = ref(false);
interface Props {
projectTeamVo: ProjectTeamVO;
}
const memberForm = reactive<ConstructionUserMembeForm>({
id: undefined,
filePath: undefined,
remark: undefined,
userName: undefined
});
const props = defineProps<Props>();
// 是否可见
const visible = ref(false);
const initFormData: ProjectTeamMemberForm = {
projectId: currentProject.value.id
};
const data = reactive<PageData<ProjectTeamMemberForm, ProjectTeamMemberQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
orderByColumn: 'createTime',
isAsc: 'desc',
projectId: currentProject.value.id
},
rules: {
id: [{ required: true, message: '主键id不能为空', trigger: 'blur' }]
},
memberRules: {
filePath: [{ required: true, message: '请上传退场文件', trigger: 'blur' }]
}
});
const buttonLoading = ref(false);
const loading = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const projectTeamMemberFormRef = ref<ElFormInstance>();
const memberFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const { queryParams, form, rules, memberRules } = toRefs(data);
const projectTeamMemberList = ref<ProjectTeamMemberVO[]>([]);
/** 查询项目班组下的成员列表 */
const getList = async () => {
loading.value = true;
const res = await listProjectTeamMember({ ...queryParams.value, teamId: props.projectTeamVo.id });
projectTeamMemberList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
projectTeamMemberFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: ProjectTeamMemberVO[]) => {
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
/** 新增按钮操作 */
const handleAdd = () => {
reset();
dialog.visible = true;
dialog.title = '添加项目班组下的成员';
getUserListNotInTeam();
};
const userNotInTeamOpt = ref();
const userNotInTeamTotal = ref();
const userQueryParams = ref<ConstructionUserQuery>({
pageNum: 1,
pageSize: 10,
orderByColumn: 'createTime',
isAsc: 'desc',
projectId: currentProject.value.id
});
// 获取不在当前班组的成员
const getUserListNotInTeam = async () => {
loading.value = true;
const res = await listConstructionUser({ ...userQueryParams.value, notTeamId: props.projectTeamVo.id });
userNotInTeamOpt.value = res.rows.map((user: ConstructionUserVO) => ({
value: user.id,
label: user.userName
}));
userNotInTeamTotal.value = res.total;
loading.value = false;
};
/** 修改按钮操作 */
const handleUpdate = async (row?: ProjectTeamMemberVO) => {
reset();
const _id = row?.id || ids.value[0];
const res = await getProjectTeamMember(_id);
Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = '修改项目班组下的成员';
};
/** 提交按钮 */
const submitForm = () => {
projectTeamMemberFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateProjectTeamMember(form.value).finally(() => (buttonLoading.value = false));
} else {
await addProjectTeamMember({
...form.value,
teamId: props.projectTeamVo.id
}).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/** 确定退场按钮 */
const submitMemberForm = async () => {
memberFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
await delConstructionUserMember(memberForm).finally(() => (buttonLoading.value = false));
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
memberForm.filePath = undefined;
memberForm.remark = undefined;
}
});
memberStatus.value = false;
};
/** 退场按钮操作 */
const handleExit = async (row?: ProjectTeamMemberVO) => {
const _ids = row?.id || ids.value;
memberForm.userName = row?.memberName;
console.log('🚀 ~ handleDelete ~ row:', row);
memberForm.id = row?.id;
memberStatus.value = true;
};
/** 删除按钮操作 */
const handleDelete = async (row?: ProjectTeamMemberVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除项目班组下的成员编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delProjectTeamMember(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'project/projectTeamMember/export',
{
...queryParams.value
},
`projectTeamMember_${new Date().getTime()}.xlsx`
);
};
watch(
() => props.projectTeamVo,
(newId, oldId) => {
if (newId !== oldId) {
getList();
}
}
);
onMounted(() => {
getList();
});
</script>

View File

@ -0,0 +1,284 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="班组名称" prop="teamName">
<el-input v-model="queryParams.teamName" placeholder="请输入班组名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['project:projectTeam:add']"> 新增 </el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['project:projectTeam:edit']">
修改
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['project:projectTeam:remove']">
删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['project:projectTeam:export']">导出 </el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" :data="projectTeamList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" type="index" width="60" align="center" />
<el-table-column label="班组名称" align="center" prop="teamName" />
<el-table-column label="班组人数" align="center" prop="peopleNumber">
<template #default="scope">
<el-link type="primary" :underline="false" @click="handleUserList(scope.row)"> {{ scope.row.peopleNumber }}</el-link>
</template>
</el-table-column>
<el-table-column label="打卡范围" align="center" prop="isClockIn">
<template #default="scope">
<dict-tag :options="team_clock_type" :value="scope.row.isClockIn" />
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-space wrap>
<el-button link type="primary" icon="User" @click="handleUserList(scope.row)">班组成员</el-button>
<el-button link type="success" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['project:projectTeam:edit']"> 修改 </el-button>
<el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['project:projectTeam:remove']">
删除
</el-button>
</el-space>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 添加或修改项目班组对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="projectTeamFormRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="班组名称" prop="teamName">
<el-input v-model="form.teamName" placeholder="请输入班组名称" />
</el-form-item>
<el-form-item label="打卡范围" prop="isClockIn">
<el-select v-model="form.isClockIn" clearable placeholder="请选择打卡范围">
<el-option v-for="item in team_clock_type" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
<el-dialog :title="currentRow.teamName" v-model="visible" width="1000px">
<user-list-dialog :projectTeamVo="currentRow" />
</el-dialog>
</div>
</template>
<script setup name="ProjectTeam" lang="ts">
import { addProjectTeam, delProjectTeam, getProjectTeam, listProjectTeam, updateProjectTeam } from '@/api/project/projectTeam';
import { ProjectTeamForm, ProjectTeamQuery, ProjectTeamVO } from '@/api/project/projectTeam/types';
import { useUserStoreHook } from '@/store/modules/user';
import UserListDialog from '@/views/project/projectTeam/component/UserListDialog.vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { team_clock_type } = toRefs<any>(proxy?.useDict('team_clock_type'));
// 获取用户 store
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目
const currentProject = computed(() => userStore.selectedProject);
const projectTeamList = ref<ProjectTeamVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const currentRow = ref<ProjectTeamVO>({
id: undefined,
projectId: undefined,
teamName: undefined,
isClockIn: undefined,
remark: undefined,
createTime: undefined
});
const queryFormRef = ref<ElFormInstance>();
const projectTeamFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const initFormData: ProjectTeamForm = {
id: undefined,
projectId: currentProject.value.id,
teamName: undefined,
isClockIn: undefined,
remark: undefined,
peopleNumber: undefined
};
const data = reactive<PageData<ProjectTeamForm, ProjectTeamQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
orderByColumn: 'createTime',
isAsc: 'desc',
projectId: currentProject.value.id,
teamName: undefined,
isClockIn: undefined,
params: {},
peopleNumber: undefined
},
rules: {
id: [{ required: true, message: '主键id不能为空', trigger: 'blur' }],
isClockIn: [{ required: true, message: '范围内打卡不能为空', trigger: 'blur' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询项目班组列表 */
const getList = async () => {
loading.value = true;
const res = await listProjectTeam(queryParams.value);
projectTeamList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
projectTeamFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: ProjectTeamVO[]) => {
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
/** 新增按钮操作 */
const handleAdd = () => {
reset();
dialog.visible = true;
dialog.title = '添加项目班组';
};
/** 修改按钮操作 */
const handleUpdate = async (row?: ProjectTeamVO) => {
reset();
const _id = row?.id || ids.value[0];
const res = await getProjectTeam(_id);
Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = '修改项目班组';
};
const visible = ref<boolean>(false);
/** 班组成员操作 */
const handleUserList = (row?: ProjectTeamVO) => {
currentRow.value = row;
visible.value = true;
};
/** 提交按钮 */
const submitForm = () => {
projectTeamFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
form.value.projectId = currentProject.value.id;
if (form.value.id) {
await updateProjectTeam(form.value).finally(() => (buttonLoading.value = false));
} else {
await addProjectTeam(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: ProjectTeamVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除项目班组编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delProjectTeam(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'project/projectTeam/export',
{
...queryParams.value
},
`projectTeam_${new Date().getTime()}.xlsx`
);
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
});
</script>

View File

@ -0,0 +1,395 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="申请人" prop="userName">
<el-input v-model="queryParams.userName" placeholder="请输入申请人" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="补卡类型" prop="reissueCardType">
<el-select v-model="queryParams.reissueCardType" placeholder="全部" clearable>
<el-option v-for="dict in commuter_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="所属班组" prop="reissueCardType">
<el-select v-model="queryParams.teamId" placeholder="全部" clearable>
<el-option v-for="dict in ProjectTeam" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="班组长意见" prop="gangerOpinion" label-width="100px">
<el-select v-model="queryParams.gangerOpinion" placeholder="全部" clearable>
<el-option v-for="dict in user_opinion_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="管理员意见" prop="managerOpinion" label-width="100px">
<el-select v-model="queryParams.managerOpinion" placeholder="全部" clearable>
<el-option v-for="dict in user_opinion_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<el-table v-loading="loading" :data="reissueCardList">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" align="center" width="55" type="index" />
<el-table-column label="申请人" align="center" prop="userName" />
<el-table-column label="申请补卡说明" align="center" prop="userExplain" />
<el-table-column label="所属班组" align="center" prop="teamName" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :options="user_review_status_type" :value="scope.row.status" />
</template>
</el-table-column>
<!-- <el-table-column label="班组长意见" align="center" prop="gangerOpinion">
<template #default="scope">
<dict-tag :options="user_opinion_type" :value="scope.row.gangerOpinion" />
</template>
</el-table-column>
<el-table-column label="班组长说明" align="center" prop="gangerExplain" />
<el-table-column label="班组长操作时间" align="center" prop="gangerTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.gangerTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="管理员意见" align="center" prop="managerOpinion">
<template #default="scope">
<dict-tag :options="user_opinion_type" :value="scope.row.managerOpinion" />
</template>
</el-table-column>
<el-table-column label="管理员说明" align="center" prop="managerExplain" />
<el-table-column label="补卡申请时间" align="center" prop="userTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.userTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="管理员操作时间" align="center" prop="managerTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.managerTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column> -->
<!-- <el-table-column label="备注" align="center" prop="remark" /> -->
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="success" icon="View" @click="handleDetail(scope.row)">详情</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<el-dialog title="修改施工人员补卡申请" v-model="dialog.visible" width="400px">
<div class="pl-xl">
<el-form-item label="是否同意">
<el-radio-group v-model="auditForm.managerOpinion">
<el-radio value="2" size="small">同意</el-radio>
<el-radio value="3" size="small">拒绝</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="拒绝说明" v-if="auditForm.managerOpinion == '3'">
<el-input v-model="auditForm.managerExplain" placeholder="请输入拒绝说明" type="textarea" clearable></el-input>
</el-form-item>
</div>
<template #footer>
<span>
<el-button type="primary" @click="submitAudit">确定</el-button>
<el-button @click="dialog.visible = false">取消</el-button>
</span>
</template>
</el-dialog>
<el-dialog :title="detailObj.userName + '补卡申请详情'" v-model="dialog.details" width="700px" append-to-body>
<div class="block_box">
<span>补卡申请</span>
<el-form label-width="130px">
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="补卡申请时间">
{{ detailObj.userTime }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="班组长说明">
{{ detailObj.gangerExplain ? detailObj.gangerExplain : '暂无' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="班组长操作时间">
{{ detailObj.gangerTime ? detailObj.gangerTime : '暂无' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="管理员说明">
{{ detailObj.managerExplain ? detailObj.managerExplain : '暂无' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="管理员操作时间">
{{ detailObj.managerTime ? detailObj.managerTime : '暂无' }}
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<div class="block_box">
<span>审核进度</span>
<el-steps style="max-width: 700px" :active="auditProgress" align-center finish-status="success">
<el-step :title="teamStatus ? detailObj.gangerName : '班组长'" :status="teamStatus ? teamStatus : ''">
<template #description>
<div v-if="!teamStatus">审核中</div>
<div v-else>
<span>{{ detailObj.gangerOpinion == '2' ? '同意' : '拒绝' }}</span>
<p>{{ detailObj.gangerExplain }}</p>
</div>
</template>
</el-step>
<el-step :title="managerStatus ? detailObj.managerName : '管理员'" :status="managerStatus ? managerStatus : ''">
<template #description>
<div v-if="!managerStatus">审核中</div>
<div v-else>
<span>{{ detailObj.managerOpinion == '2' ? '同意' : '拒绝' }}</span>
<p>{{ detailObj.managerExplain }}</p>
</div>
</template>
</el-step>
<el-step title="结果" :status="resultsStatus">
<template #description>
<div>{{ user_review_status_type[parseInt(detailObj.status) - 1].label }}</div>
</template>
</el-step>
</el-steps>
</div>
</el-dialog>
</div>
</template>
<script setup name="ReissueCard" lang="ts">
import { listProjectTeam } from '@/api/project/projectTeam';
import { ProjectTeamVO } from '@/api/project/projectTeam/types';
import { listReissueCard, getReissueCard, delReissueCard, addReissueCard, updateReissueCard, AuditReissueCard } from '@/api/project/reissueCard';
import { ReissueCardVO, ReissueCardQuery, ReissueCardForm, AuditReissueCardForm } from '@/api/project/reissueCard/types';
import { useUserStoreHook } from '@/store/modules/user';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { commuter_type, user_opinion_type, user_review_status_type } = toRefs<any>(
proxy?.useDict('commuter_type', 'user_opinion_type', 'user_review_status_type')
);
const detailObj = ref<ReissueCardVO>({
userName: undefined,
id: undefined,
userExplain: undefined,
userTime: undefined,
gangerName: undefined,
gangerOpinion: undefined,
gangerExplain: undefined,
gangerTime: undefined,
managerOpinion: undefined,
managerExplain: undefined,
managerTime: undefined,
remark: undefined,
status: undefined,
managerName: undefined
});
const reissueCardList = ref<ReissueCardVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const reissueCardFormRef = ref<ElFormInstance>();
const auditForm = reactive<AuditReissueCardForm>({
id: undefined,
managerOpinion: '2',
managerExplain: undefined
});
const dialog = reactive<DialogOption>({
visible: false,
title: '',
details: false
});
// 获取用户 store
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目
const currentProject = computed(() => userStore.selectedProject);
const ProjectTeam = computed(() => userStore.ProjectTeamList);
const initFormData: ReissueCardForm = {
id: undefined,
userId: undefined,
userExplain: undefined,
gangerId: undefined,
gangerOpinion: undefined,
gangerExplain: undefined,
managerOpinion: undefined,
managerExplain: undefined,
projectId: currentProject.value?.id,
attendanceId: undefined,
remark: undefined
};
const data = reactive<PageData<ReissueCardForm, ReissueCardQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
userName: undefined,
gangerOpinion: undefined,
managerOpinion: undefined,
projectId: currentProject.value?.id,
teamId: undefined,
reissueCardType: undefined,
params: {}
},
rules: {
id: [{ required: true, message: '主键id不能为空', trigger: 'blur' }],
userId: [{ required: true, message: '申请人id不能为空', trigger: 'blur' }],
gangerId: [{ required: true, message: '班组长不能为空', trigger: 'blur' }],
gangerOpinion: [{ required: true, message: '班组长意见不能为空', trigger: 'blur' }],
managerOpinion: [{ required: true, message: '管理员意见不能为空', trigger: 'blur' }],
projectId: [{ required: true, message: '项目id不能为空', trigger: 'blur' }],
attendanceId: [{ required: true, message: '考勤表主键id不能为空', trigger: 'blur' }]
}
});
const { queryParams, form, rules } = toRefs(data);
//审核进度
const auditProgress = computed(() => {
if (auditStatus.value) return 3;
if (managerStatus.value) return 2;
if (teamStatus.value) return 1;
return 0;
});
//审核状态
const auditStatus = computed(() => {
if (detailObj.value.status == '3' || detailObj.value.status == '4') return true;
return false;
});
//管理员审核状态
const managerStatus = computed(() => {
switch (detailObj.value.managerOpinion) {
case '1':
return false;
case '2':
return 'success';
case '3':
return 'error';
}
});
//班组审核状态
const teamStatus = computed(() => {
switch (detailObj.value.gangerOpinion) {
case '1':
return false;
case '2':
return 'success';
case '3':
return 'error';
}
});
//结果状态
const resultsStatus = computed(() => {
if (detailObj.value.status == '3') return 'success';
if (detailObj.value.status == '4') return 'error';
return '';
});
/** 查询施工人员补卡申请列表 */
async function getList() {
loading.value = true;
const res = await listReissueCard(queryParams.value);
reissueCardList.value = res.rows;
total.value = res.total;
loading.value = false;
}
/** 表单重置 */
const reset = () => {
auditForm.managerExplain = '';
auditForm.managerOpinion = '2';
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 新增按钮操作 */
const handleAdd = () => {
reset();
dialog.visible = true;
dialog.title = '添加施工人员补卡申请';
};
/** 审批按钮操作 */
const handleUpdate = async (row?: ReissueCardVO) => {
reset();
const _id = row?.id || ids.value[0];
auditForm.id = _id;
dialog.visible = true;
dialog.title = '修改施工人员补卡申请';
};
const handleDetail = (row: ReissueCardVO) => {
detailObj.value = row;
dialog.details = true;
};
/** 审批操作 */
const submitAudit = async () => {
await AuditReissueCard(auditForm);
proxy?.$modal.msgSuccess('审批成功');
dialog.visible = false;
auditForm.managerExplain = '';
auditForm.managerOpinion = '2';
await getList();
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
});
</script>
<style lang="scss" scoped>
.block_box {
border: 1px solid #9eccfa;
border-radius: 6px;
padding: 10px 20px 20px 10px;
margin: 15px;
> span {
color: #409eff;
font-weight: 700;
font-size: 14px;
}
}
</style>

View File

@ -0,0 +1,319 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="工种" prop="workType">
<el-select v-model="queryParams.workType" placeholder="全部" clearable>
<el-option v-for="dict in type_of_work" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="工资计算方式" prop="wageCalculationType" label-width="100px">
<el-select v-model="queryParams.wageCalculationType" placeholder="全部" clearable>
<el-option v-for="dict in wageCalculationTypeList" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<!-- <el-form-item label="工资计量单位" prop="wageMeasureUnit" label-width="100px">
<el-select v-model="queryParams.wageMeasureUnit" placeholder="请选择工资计量单位" clearable>
<el-option v-for="dict in wage_measure_unit_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item> -->
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['project:workWage:add']">新增 </el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['project:workWage:edit']"
>修改
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['project:workWage:remove']"
>删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['project:workWage:export']">导出 </el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" :data="workWageList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" align="center" type="index" width="60px" />
<!-- <el-table-column label="主键id" align="center" prop="id" v-if="true" /> -->
<!-- <el-table-column label="项目id" align="center" prop="projectId" /> -->
<el-table-column label="工种" align="center" prop="workType">
<template #default="scope">
<dict-tag :options="type_of_work" :value="scope.row.workType" />
</template>
</el-table-column>
<el-table-column label="是否是特种兵" align="center" prop="isSpecialType">
<template #default="scope">
{{ scope.row.isSpecialType == 1 ? '是' : '否' }}
</template>
</el-table-column>
<el-table-column label="工资计算方式" align="center" prop="wageCalculationType">
<template #default="scope">
{{ scope.row.wageCalculationType == 1 ? '计时' : '计件' }}
</template>
</el-table-column>
<el-table-column label="工资标准" align="center" prop="wage" />
<el-table-column label="工资计量单位" align="center" prop="wageMeasureUnit">
<template #default="scope">
<dict-tag :options="wage_measure_unit_type" :value="scope.row.wageMeasureUnit" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['project:workWage:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['project:workWage:remove']"></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 添加或修改工种薪水对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="workWageFormRef" :model="form" :rules="rules" label-width="100px">
<!-- <el-form-item label="项目id" prop="projectId">
<el-input v-model="form.projectId" placeholder="请输入项目id" />
</el-form-item> -->
<el-form-item label="工种" prop="workType">
<el-select v-model="form.workType" placeholder="请选择工种" :disabled="!form.id ? false : true">
<el-option v-for="dict in type_of_work" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="是否是特种兵 " prop="isSpecialType">
<el-select v-model="form.isSpecialType" placeholder="请选择是否是特种兵">
<el-option v-for="dict in isSpecialTypeList" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="工资计算方式" prop="wageCalculationType">
<el-select v-model="form.wageCalculationType" placeholder="请选择工资计算方式" :disabled="!form.id ? false : true">
<el-option v-for="dict in wageCalculationTypeList" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="工资标准" prop="wage">
<el-input v-model="form.wage" placeholder="请输入工资标准" />
</el-form-item>
<!-- <el-form-item label="工资计量单位" prop="wageMeasureUnit">
<el-select v-model="form.wageMeasureUnit" placeholder="请选择工资计量单位">
<el-option v-for="dict in wage_measure_unit_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
</el-form-item> -->
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="WorkWage" lang="ts">
import { listWorkWage, getWorkWage, delWorkWage, addWorkWage, updateWorkWage } from '@/api/project/workWage';
import { WorkWageVO, WorkWageQuery, WorkWageForm, SpecialType } from '@/api/project/workWage/types';
import { useUserStoreHook } from '@/store/modules/user';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { type_of_work, wage_measure_unit_type } = toRefs<any>(proxy?.useDict('type_of_work', 'wage_measure_unit_type'));
console.log(type_of_work);
// 获取用户 store
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目
const currentProject = computed(() => userStore.selectedProject);
const workWageList = ref<WorkWageVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const workWageFormRef = ref<ElFormInstance>();
const isSpecialTypeList = ref<Array<SpecialType>>([
{ label: '是', value: '1' },
{ label: '否', value: '2' }
]);
const wageCalculationTypeList = ref<Array<SpecialType>>([
{ label: '计时', value: '1' },
{ label: '计件', value: '2' }
]);
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const initFormData: WorkWageForm = {
id: undefined,
projectId: currentProject.value.id,
workType: undefined,
isSpecialType: undefined,
wageCalculationType: undefined,
wage: undefined,
wageMeasureUnit: undefined,
remark: undefined
};
const data = reactive<PageData<WorkWageForm, WorkWageQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
projectId: currentProject.value.id,
workType: undefined,
isSpecialType: undefined,
wageCalculationType: undefined,
wage: undefined,
wageMeasureUnit: undefined,
params: {}
},
rules: {
id: [{ required: true, message: '主键id不能为空', trigger: 'blur' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询工种薪水列表 */
const getList = async () => {
loading.value = true;
const res = await listWorkWage(queryParams.value);
workWageList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
workWageFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: WorkWageVO[]) => {
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
/** 新增按钮操作 */
const handleAdd = () => {
reset();
dialog.visible = true;
dialog.title = '添加工种薪水';
};
/** 修改按钮操作 */
const handleUpdate = async (row?: WorkWageVO) => {
reset();
const _id = row?.id || ids.value[0];
const res = await getWorkWage(_id);
Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = '修改工种薪水';
};
/** 提交按钮 */
const submitForm = () => {
workWageFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
form.value.projectId = currentProject.value.id;
if (form.value.id) {
await updateWorkWage(form.value).finally(() => (buttonLoading.value = false));
} else {
await addWorkWage(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: WorkWageVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除工种薪水编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delWorkWage(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'project/workWage/export',
{
...queryParams.value
},
`workWage_${new Date().getTime()}.xlsx`
);
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
});
</script>

View File

@ -0,0 +1,247 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="申请人" prop="userName">
<el-input v-model="queryParams.userName" placeholder="请输入申请人" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="日报类型" prop="isResubmit">
<el-select v-model="queryParams.isResubmit" placeholder="全部" @change="handleQuery">
<el-option v-for="dict in reSubmitType" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="所属班组" prop="leaveType">
<el-select v-model="queryParams.teamId" placeholder="全部" clearable>
<el-option v-for="dict in ProjectTeam" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<el-table v-loading="loading" :data="workerDailyReportList">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="主键id" align="center" prop="id" v-if="false" />
<el-table-column label="申请人名字" align="center" prop="userName" />
<el-table-column label="今日完成工作" align="center" prop="todayCompletedWork" />
<el-table-column label="未完成工作" align="center" prop="unfinishedWork" />
<el-table-column label="明日工作" align="center" prop="tomorrowWork" v-if="queryParams.isResubmit == '1'" />
<el-table-column label="需协调与帮助" align="center" prop="coordinationHelp" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="success" icon="View" @click="handleDetail(scope.row)">详情</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<el-dialog title="日报打卡详情" v-model="dialog.visible" width="700">
<div class="block_box">
<span>基本信息</span>
<el-form label-width="130px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="所在班组">
{{ form.teamName }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="日报日期">
{{ form.reportDate ? form.reportDate : '暂无' }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="补交理由">
{{ form.resubmitReason ? form.resubmitReason : '暂无' }}
</el-form-item>
</el-col>
<!-- <el-col :span="12">
<el-form-item label="附件">
<span v-if="!form.fileList.length">暂无</span>
<div v-else>
<el-link target="_blank" :href="item" :underline="false" v-for="(item, index) in form.fileList" :key="index">
<img src="../../../../src/assets/icons/svg/PDF.png" alt="" class="w10 mr" />
</el-link>
</div>
</el-form-item>
</el-col> -->
</el-row>
</el-form>
</div>
<div class="block_box">
<span>日报明细</span>
<el-table :data="form.dailyPieceItemVoList" class="mt">
<el-table-column type="index" width="50" />
<el-table-column label="计件类型" align="center" prop="pieceType" />
<el-table-column label="计件数量" align="center" prop="pieceCount" />
<el-table-column label="计件单位" align="center" prop="pieceUnit" />
<el-table-column label="备注" align="center" prop="remark" />
</el-table>
</div>
<div class="block_box" v-if="form.fileList.length">
<span>附件</span>
<div class="mt pl">
<el-link target="_blank" :href="item" :underline="false" v-for="(item, index) in form.fileList" :key="index">
<img v-if="getFileTypeFromUrl(item)" src="../../../../src/assets/icons/svg/PDF.png" alt="" class="w22 mr-xl" />
<img v-else :src="item" class="w22 mr-xl" />
</el-link>
</div>
</div>
</el-dialog>
</div>
</template>
<script setup name="WorkerDailyReport" lang="ts">
import {
listWorkerDailyReport,
getWorkerDailyReport,
delWorkerDailyReport,
addWorkerDailyReport,
updateWorkerDailyReport
} from '@/api/project/workerDailyReport';
import { WorkerDailyReportVO, WorkerDailyReportQuery, WorkerDailyReportForm } from '@/api/project/workerDailyReport/types';
import { SpecialType } from '@/api/project/workWage/types';
import { useUserStoreHook } from '@/store/modules/user';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
// 获取用户 store
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目
const currentProject = computed(() => userStore.selectedProject);
const ProjectTeam = computed(() => userStore.ProjectTeamList);
const workerDailyReportList = ref<WorkerDailyReportVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const workerDailyReportFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const reSubmitType = ref<SpecialType[]>([
{
label: '打卡',
value: '1'
},
{
label: '补卡',
value: '2'
}
]);
const initFormData: WorkerDailyReportForm = {
id: undefined,
projectId: currentProject.value?.id,
teamId: undefined,
userId: undefined,
userName: undefined,
todayCompletedWork: undefined,
unfinishedWork: undefined,
tomorrowWork: undefined,
coordinationHelp: undefined,
fileList: undefined,
isResubmit: undefined
};
const data = reactive<PageData<WorkerDailyReportForm, WorkerDailyReportQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
projectId: currentProject.value?.id,
teamId: undefined,
userId: undefined,
userName: undefined,
params: {},
isResubmit: '1'
}
});
const { queryParams, form } = toRefs(data);
const getFileTypeFromUrl = computed(() => (url) => {
const regex = /\.([a-zA-Z0-9]+)(?:[?#]|$)/;
const match = url.match(regex);
if (match[1]?.toLowerCase() == 'pdf') {
return true;
}
return false;
});
/** 查询施工人员日报列表 */
const getList = async () => {
loading.value = true;
const res = await listWorkerDailyReport(queryParams.value);
workerDailyReportList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 详情按钮操作 */
const handleDetail = async (row?: WorkerDailyReportVO) => {
const _id = row?.id || ids.value[0];
const res = await getWorkerDailyReport(_id);
Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = '修改施工人员日报';
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
});
</script>
<style lang="scss" scoped>
.block_box {
border: 1px solid #9eccfa;
border-radius: 6px;
padding: 10px 20px 20px 10px;
margin: 15px;
> span {
color: #409eff;
font-weight: 700;
font-size: 14px;
}
}
</style>