init:first commit of plus-ui
This commit is contained in:
585
src/views/project/attendance/index.vue
Normal file
585
src/views/project/attendance/index.vue
Normal 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>
|
180
src/views/project/attendanceRecords/index.vue
Normal file
180
src/views/project/attendanceRecords/index.vue
Normal 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>
|
177
src/views/project/constructionBlacklist/index.vue
Normal file
177
src/views/project/constructionBlacklist/index.vue
Normal 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>
|
@ -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>
|
1175
src/views/project/constructionUser/index.vue
Normal file
1175
src/views/project/constructionUser/index.vue
Normal file
File diff suppressed because it is too large
Load Diff
@ -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>
|
283
src/views/project/contractor/index.vue
Normal file
283
src/views/project/contractor/index.vue
Normal 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>
|
440
src/views/project/leave/index.vue
Normal file
440
src/views/project/leave/index.vue
Normal 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>
|
584
src/views/project/project/index.vue
Normal file
584
src/views/project/project/index.vue
Normal 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>
|
@ -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>
|
318
src/views/project/projectRelevancy/index.vue
Normal file
318
src/views/project/projectRelevancy/index.vue
Normal 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>
|
368
src/views/project/projectTeam/component/UserListDialog.vue
Normal file
368
src/views/project/projectTeam/component/UserListDialog.vue
Normal 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>
|
284
src/views/project/projectTeam/index.vue
Normal file
284
src/views/project/projectTeam/index.vue
Normal 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>
|
395
src/views/project/reissueCard/index.vue
Normal file
395
src/views/project/reissueCard/index.vue
Normal 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>
|
319
src/views/project/workWage/index.vue
Normal file
319
src/views/project/workWage/index.vue
Normal 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>
|
247
src/views/project/workerDailyReport/index.vue
Normal file
247
src/views/project/workerDailyReport/index.vue
Normal 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>
|
Reference in New Issue
Block a user