first commit

This commit is contained in:
2025-08-19 10:19:29 +08:00
commit 3b61e84a7f
3014 changed files with 2640574 additions and 0 deletions

View File

@ -0,0 +1,586 @@
<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(() => proxy?.$cache.local.getJSON('ProjectTeamList') || []);
const attendanceList = ref<AttendanceVO[]>([]);
const attendanceTwoWeekList = ref<AttendanceTwoWeekVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const calendarDay = ref<Date | null>(null);
const monthValue = ref<Date | null>(null);
const calendarList = ref<AttendanceMonthVO[]>();
const queryFormRef = ref<ElFormInstance>();
const attendanceFormRef = ref<ElFormInstance>();
const commandstatsIntance = ref<any>(null);
const dialog = reactive<DialogOption>({
visible: false,
details: false,
title: ''
});
const echartsOption = ref<any>({});
const initFormData: AttendanceForm = {
id: undefined,
userId: undefined,
facePic: undefined,
onClockTime: undefined,
offClockTime: undefined,
clockDate: undefined,
clockStatus: undefined,
pinchUserId: undefined,
clockRecord: undefined,
commuter: undefined,
dailyWage: undefined,
projectId: currentProject.value?.id,
lng: undefined,
lat: undefined,
remark: undefined,
typeOfWork: undefined,
teamId: undefined
};
const data = reactive<PageData<AttendanceForm, AttendanceQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
userName: undefined,
clockDate: undefined,
clockStatus: undefined,
commuter: undefined,
projectId: currentProject.value?.id,
typeOfWork: undefined,
teamId: undefined,
params: {}
},
rules: {
id: [{ required: true, message: '主键id不能为空', trigger: 'blur' }],
userId: [{ required: true, message: '人员id不能为空', trigger: 'blur' }],
facePic: [{ required: true, message: '人脸照不能为空', trigger: 'blur' }],
projectId: [{ required: true, message: '项目id不能为空', trigger: 'blur' }],
clockDate: [{ required: true, message: '打卡日期不能为空', trigger: 'blur' }],
clockStatus: [{ required: true, message: '1正常,2迟到,3早退,4缺勤,5补卡不能为空', trigger: 'change' }]
}
});
const day = computed(() => (date) => {
return date.day.split('-').slice(1).join('-');
});
//是否打卡
const isplayCard = computed(() => (date) => {
return calendarList.value.some((item) => item.clockDate == date.day);
});
//打卡时间下标
const playCardIdx = computed(() => (date) => {
return calendarList.value.findIndex((item) => item.clockDate == date.day);
});
//上班时间
const workTime = computed(() => (date) => {
return calendarList.value[playCardIdx.value(date)].attendanceList[0].clockTime?.slice(10);
});
//下班时间
const workFromTime = computed(() => (date) => {
return calendarList.value[playCardIdx.value(date)].attendanceList[1]?.clockTime?.slice(10);
});
//考勤状态
const attendanceStatus = computed(() => (date) => {
return calendarList.value[playCardIdx.value(date)].status;
});
const { queryParams, form, rules } = toRefs(data);
const calendar = ref<CalendarInstance>();
const handleMonth = async (e: any) => {
calendarDay.value = e;
handleCalendarMonth(e);
};
const selectDate = (e: any) => {
handleQuery();
};
const handleCalendarMonth = async (e?) => {
let clockMonth;
if (e) {
clockMonth = parseTime(e, '{y}-{m}');
}
const res = await listAttendanceMonth({ userId: dialog.id, clockMonth });
calendarList.value = res.data;
};
/** 查看打卡记录详情 */
const handleViewPlayCard = async (data: any) => {
if (data.type == 'next-month' || data.type == 'prev-month') {
monthValue.value = data.date;
handleCalendarMonth(monthValue.value);
}
};
/** 查询考勤列表 */
const getList = async () => {
loading.value = true;
const res = await listAttendance(queryParams.value);
attendanceList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 查询近两周考勤列表 */
const getListTwoWeek = async () => {
loading.value = true;
const res = await listAttendanceTwoWeek(queryParams.value);
attendanceTwoWeekList.value = res.data;
echartsOption.value = { ...option(attendanceTwoWeekList.value) };
commandstatsIntance.value.setOption(echartsOption.value);
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
attendanceFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
getListTwoWeek();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
//处理获取到的月份
const incrementMonth = (dateStr: string, monthsToAdd: number) => {
const [yearPart, monthPart] = dateStr.replace(/\s/g, '').split('年');
const year = parseInt(yearPart, 10);
const month = parseInt(monthPart.replace('月', ''), 10);
// 创建一个新的 Date 对象,设置为输入日期的第一天
const date = new Date(year, month - 1, 1);
// 增加一个月
date.setMonth(date.getMonth() + monthsToAdd);
// 提取增加一个月后的年份和月份
const newYear = date.getFullYear();
const newMonth = String(date.getMonth() + 1).padStart(2, '0');
// 返回格式化后的日期字符串
return `${newYear}-${newMonth}`;
};
/** 详情按钮操作 */
const handleDetails = async (row?: AttendanceVO) => {
const res = await listAttendanceMonth({ userId: row?.id });
calendarList.value = res.data;
dialog.details = true;
dialog.id = row?.id;
dialog.title = row?.userName || '';
};
/** 提交按钮 */
const submitForm = () => {
attendanceFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateAttendance(form.value).finally(() => (buttonLoading.value = false));
} else {
await addAttendance(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/** 删除按钮操作 */
// const handleDelete = async (row?: AttendanceVO) => {
// const _ids = row?.id || ids.value;
// await proxy?.$modal.confirm('是否确认删除考勤编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
// await delAttendance(_ids);
// proxy?.$modal.msgSuccess('删除成功');
// await getList();
// };
/** 导出按钮操作 */
// const handleExport = () => {
// proxy?.download(
// 'project/attendance/export',
// {
// ...queryParams.value
// },
// `attendance_${new Date().getTime()}.xlsx`
// );
// };
//初始化图表
const init = () => {
commandstatsIntance.value = echarts.init(commandstats.value, 'macarons');
commandstatsIntance.value.on('click', function (params) {
queryParams.value.clockDate = params.name;
handleQuery();
});
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value?.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
getListTwoWeek();
init();
});
</script>
<style lang="scss" scoped>
.label {
font-size: 24px;
position: absolute;
left: 50%;
top: 0;
transform: translate(-50%);
color: #000;
font-weight: 500;
}
.status-detail {
margin: 0 15px;
position: relative;
font-size: 12px;
> div {
margin: 0 15px;
position: relative;
font-size: 12px;
&::before {
position: absolute;
content: '';
display: inline-block;
left: -15px;
top: 30%;
width: 8px;
height: 8px;
border-radius: 50%;
}
}
.dot1 {
&::before {
background-color: #1d6fe9;
}
}
.dot2 {
&::before {
background-color: #f55f4e;
}
}
.dot3 {
&::before {
background-color: #ff8d1a;
}
}
}
.flex-c {
height: 110px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: relative;
.time {
position: absolute;
z-index: 10;
right: 0;
top: 0;
}
img {
width: 50%;
height: 50%;
}
> span {
font-size: 12px;
color: #ccc;
padding-top: 5px;
}
}
.el-calendar-table__row {
height: 100px;
}
.flex-r {
width: 100%;
display: flex;
flex-direction: row;
justify-content: center;
padding-top: 5px;
height: 10px;
.circle {
width: 7px;
height: 7px;
border-radius: 50%;
margin: 0 2px;
position: absolute;
z-index: 10;
right: 12px;
top: 35px;
}
.status2 {
background: #f55f4e;
}
.status1 {
background: #1d6fe9;
}
.status3 {
background: #ff8d1a;
}
}
::v-deep(.el-calendar) {
.el-calendar__body {
height: 600px;
overflow: auto;
}
td {
height: 110px;
.el-calendar-day {
height: 100%;
}
}
}
</style>

View File

@ -0,0 +1,181 @@
<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(() => proxy?.$cache.local.getJSON('ProjectTeamList') || []);
const initFormData: AttendanceForm = {
id: undefined,
userId: undefined,
facePic: undefined,
projectId: currentProject.value?.id,
onClockTime: undefined,
offClockTime: undefined,
clockDate: undefined,
clockStatus: undefined,
pinchUserId: undefined,
clockRecord: undefined,
commuter: undefined,
dailyWage: undefined,
lng: undefined,
lat: undefined,
remark: undefined
};
const data = reactive<PageData<AttendanceForm, AttendanceQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
userName: undefined,
projectId: currentProject.value?.id,
clockDate: undefined,
clockStatus: undefined,
commuter: undefined,
params: {},
teamId: undefined
},
rules: {
id: [{ required: true, message: '主键id不能为空', trigger: 'blur' }],
userId: [{ required: true, message: '人员id不能为空', trigger: 'blur' }],
facePic: [{ required: true, message: '人脸照不能为空', trigger: 'blur' }],
projectId: [{ required: true, message: '项目id不能为空', trigger: 'blur' }],
clockDate: [{ required: true, message: '打卡日期不能为空', trigger: 'blur' }],
clockStatus: [{ required: true, message: '1正常,2迟到,3早退,4缺勤,5补卡不能为空', trigger: 'change' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询考勤列表 */
const getList = async () => {
loading.value = true;
const res = await listAttendance(queryParams.value);
attendanceList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value?.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
});
</script>

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -0,0 +1,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="公司名称" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入公司名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="分包类型" prop="contractorType">
<el-select v-model="queryParams.contractorType" filterable placeholder="请选择类型">
<el-option v-for="(item, i) of dictList" :key="i" :label="item.dictLabel" :value="item.dictValue"> </el-option>
</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="['contractor:contractor:add']"> 新增 </el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['contractor:contractor:edit']"
>修改
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['contractor:contractor:remove']"
>删除
</el-button>
</el-col>
<!-- <el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['contractor: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">
<template #default="scope">
<span>{{ filterType(scope.row.contractorType) }}</span>
</template>
</el-table-column>
<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="['contractor:contractor:edit']"
>修改
</el-button>
<el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['contractor: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 draggable :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="contractorType">
<el-select v-model="form.contractorType" filterable placeholder="请选择类型">
<el-option v-for="(item, i) of dictList" :key="i" :label="item.dictLabel" :value="item.dictValue"> </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>
<el-dialog draggable 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';
import { getDicts, listData } from '@/api/system/dict/data';
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();
const dictList = ref([]); //字典列表
// 从 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,
contractorType: 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,
contractorType: undefined,
projectId: currentProject.value?.id,
params: {}
},
rules: {
id: [{ required: true, message: '主键id不能为空', trigger: 'blur' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询字典数据列表 */
const getDictList = async () => {
const res = await getDicts('contractor_type');
dictList.value = res.data;
};
// 分包类型
const filterType = (val) => {
let label = '';
dictList.value.forEach((item) => {
if (item.dictValue == val) {
label = item.dictLabel;
}
});
return label;
};
/** 查询分包单位列表 */
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(() => {
getDictList();
getList();
});
</script>

View File

@ -0,0 +1,346 @@
<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="never">
<el-descriptions border :column="2">
<el-descriptions-item label="分包方">{{ info.contractorName }}</el-descriptions-item>
<el-descriptions-item label="物料名称">{{ info.materialName }}</el-descriptions-item>
<el-descriptions-item label="物料数量">{{ info.materialNumber }}</el-descriptions-item>
</el-descriptions></el-card
>
<el-card shadow="hover" style="margin-top: 10px">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="使用情况" prop="usedPosition">
<el-input v-model="queryParams.usedPosition" 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('1')">到货</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="primary" plain icon="Minus" @click="handleAdd('2')">使用</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete()"
v-hasPermi="['contractor:contractorMaterialRecord:remove']"
>删除</el-button
>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-tabs v-model="activeName" type="border-card" class="demo-tabs" @tab-click="handleClick">
<el-tab-pane label="到货" name="1">
<el-table v-loading="loading" :data="contractorMaterialRecordList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="分包方" align="center" prop="contractorName" />
<el-table-column label="物料名称" align="center" prop="contractorMaterialName" />
<!-- <el-table-column label="记录类型" align="center" prop="recordType">
<template #default="scope">
<dict-tag :options="contractor_material_record_type" :value="scope.row.recordType" />
</template>
</el-table-column> -->
<el-table-column label="记录时间" align="center" prop="recordTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.recordTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="数量" align="center" prop="recordNumber" />
<el-table-column label="使用情况" align="center" prop="usedPosition" />
<el-table-column label="相关附件" align="center" prop="file" />
<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="['contractor:contractorMaterialRecord:edit']"
></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button
link
type="primary"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['contractor:contractorMaterialRecord: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-tab-pane>
<el-tab-pane label="使用" name="2">
<el-table v-loading="loading" :data="contractorMaterialRecordList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="分包方" align="center" prop="contractorName" />
<el-table-column label="物料名称" align="center" prop="contractorMaterialName" />
<!-- <el-table-column label="记录类型" align="center" prop="recordType">
<template #default="scope">
<dict-tag :options="contractor_material_record_type" :value="scope.row.recordType" />
</template>
</el-table-column> -->
<el-table-column label="记录时间" align="center" prop="recordTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.recordTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="数量" align="center" prop="recordNumber" />
<el-table-column label="使用情况" align="center" prop="usedPosition" />
<el-table-column label="相关附件" align="center" prop="file" />
<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="['contractor:contractorMaterialRecord:edit']"
></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button
link
type="primary"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['contractor:contractorMaterialRecord: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-tab-pane>
</el-tabs>
</el-card>
<!-- 添加或修改分包方物料记录对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="contractorMaterialRecordFormRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="记录时间" prop="recordTime">
<el-date-picker clearable v-model="form.recordTime" type="date" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择记录时间">
</el-date-picker>
</el-form-item>
<el-form-item label="数量" prop="recordNumber">
<el-input v-model="form.recordNumber" type="number" placeholder="请输入数量" />
</el-form-item>
<el-form-item label="使用情况" prop="usedPosition">
<el-input v-model="form.usedPosition" placeholder="请输入使用情况" />
</el-form-item>
<el-form-item label="相关附件" prop="file">
<file-upload v-model="form.file" />
</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="ContractorMaterialRecord" lang="ts">
import {
listContractorMaterialRecord,
getContractorMaterialRecord,
delContractorMaterialRecord,
addContractorMaterialRecord,
updateContractorMaterialRecord
} from '@/api/project/contractorMaterial/contractorMaterialRecord';
import {
ContractorMaterialRecordVO,
ContractorMaterialRecordQuery,
ContractorMaterialRecordForm
} from '@/api/project/contractorMaterial/contractorMaterialRecord/types';
import { getContractorMaterial } from '@/api/project/contractorMaterial';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { contractor_material_record_type } = toRefs<any>(proxy?.useDict('contractor_material_record_type'));
const contractorMaterialRecordList = ref<ContractorMaterialRecordVO[]>([]);
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 contractorMaterialRecordFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const initFormData: ContractorMaterialRecordForm = {
id: undefined,
contractorMaterialId: undefined,
recordType: undefined,
recordTime: undefined,
recordNumber: undefined,
remainingNumber: undefined,
usedPosition: undefined,
file: undefined,
remark: undefined
};
const info = ref({
contractorName: undefined,
materialName: undefined,
materialNumber: undefined
});
const activeName = '1';
const data = reactive<PageData<ContractorMaterialRecordForm, ContractorMaterialRecordQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
projectId: undefined,
contractorId: undefined,
contractorMaterialId: undefined,
recordType: undefined,
usedPosition: undefined,
params: {}
},
rules: {
contractorMaterialId: [{ required: true, message: '物料id不能为空', trigger: 'blur' }],
recordType: [{ required: true, message: '记录类型不能为空', trigger: 'change' }],
recordTime: [{ required: true, message: '记录时间不能为空', trigger: 'blur' }],
recordNumber: [{ required: true, message: '数量不能为空', trigger: 'blur' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询分包方物料记录列表 */
const getList = async () => {
loading.value = true;
const res = await listContractorMaterialRecord(queryParams.value);
contractorMaterialRecordList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
contractorMaterialRecordFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: ContractorMaterialRecordVO[]) => {
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
/** 新增按钮操作 */
const handleAdd = (type) => {
reset();
dialog.visible = true;
form.value.recordType = type;
dialog.title = '物料' + (type == 1 ? '到货' : '使用');
};
/** 修改按钮操作 */
const handleUpdate = async (row?: ContractorMaterialRecordVO) => {
reset();
const _id = row?.id || ids.value[0];
const res = await getContractorMaterialRecord(_id);
Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = '修改物料记录';
};
/** 提交按钮 */
const submitForm = () => {
contractorMaterialRecordFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateContractorMaterialRecord(form.value).finally(() => (buttonLoading.value = false));
} else {
await addContractorMaterialRecord(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
getDetail(data.form.contractorMaterialId);
dialog.visible = false;
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: ContractorMaterialRecordVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除分包方物料记录编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delContractorMaterialRecord(_ids);
proxy?.$modal.msgSuccess('删除成功');
getDetail(data.form.contractorMaterialId);
await getList();
};
const handleClick = (val) => {
queryParams.value.pageNum = 1;
queryParams.value.recordType = val.props.name;
handleQuery();
};
const getDetail = async (_id) => {
const res = await getContractorMaterial(_id);
info.value = res.data;
};
const getAll = (obj) => {
info.value = obj;
initFormData.contractorMaterialId = obj.id;
data.form.contractorMaterialId = obj.id;
data.queryParams.contractorMaterialId = obj.id;
getDetail(obj.id);
getList();
};
defineExpose({
getAll
});
</script>

View File

@ -0,0 +1,330 @@
<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="contractorId">
<el-select v-model="queryParams.contractorId" filterable placeholder="请选择分包方">
<el-option v-for="(item, i) of contractorList" :key="i" :label="item.name" :value="item.id"> </el-option>
</el-select>
</el-form-item>
<el-form-item label="物料名称" prop="materialName">
<el-input v-model="queryParams.materialName" placeholder="请输入物料名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="物料类型" prop="materialType">
<el-select v-model="queryParams.materialType" placeholder="请选择物料类型" clearable>
<el-option v-for="dict in contractor_material_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="物料型号" prop="materialModel">
<el-input v-model="queryParams.materialModel" 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="['contractor:contractorMaterial:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['contractor:contractorMaterial:edit']"
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete()"
v-hasPermi="['contractor:contractorMaterial:remove']"
>删除</el-button
>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" :data="contractorMaterialList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="分包方" align="center" prop="contractorName" />
<el-table-column label="物料名称" align="center" prop="materialName" />
<el-table-column label="物料类型" align="center" prop="materialType">
<template #default="scope">
<dict-tag :options="contractor_material_type" :value="scope.row.materialType" />
</template>
</el-table-column>
<el-table-column label="物料型号" align="center" prop="materialModel" />
<el-table-column label="物料数量" align="center" prop="materialNumber" />
<el-table-column label="物料单位" align="center" prop="materialUnit" />
<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="['contractor:contractorMaterial:edit']"
></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button
link
type="primary"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['contractor:contractorMaterial:remove']"
></el-button>
</el-tooltip>
<el-tooltip content="出入库" placement="top">
<el-button link type="primary" icon="view" @click="handleView(scope.row)"></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 draggable :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="contractorMaterialFormRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="分包方" prop="contractorId">
<el-select v-model="form.contractorId" filterable placeholder="请选择分包方">
<el-option v-for="(item, i) of contractorList" :key="i" :label="item.name" :value="item.id"> </el-option>
</el-select>
</el-form-item>
<el-form-item label="物料名称" prop="materialName">
<el-input v-model="form.materialName" placeholder="请输入物料名称" />
</el-form-item>
<el-form-item label="物料类型" prop="materialType">
<el-select v-model="form.materialType" placeholder="请选择物料类型">
<el-option v-for="dict in contractor_material_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="物料型号" prop="materialModel">
<el-input v-model="form.materialModel" placeholder="请输入物料型号" />
</el-form-item>
<el-form-item label="物料单位" prop="materialUnit">
<el-input v-model="form.materialUnit" placeholder="请输入物料单位" />
</el-form-item>
<!-- <el-form-item label="文件" prop="file">
<file-upload v-model="form.file" />
</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 draggable :title="dialogRecord.title" v-model="dialogRecord.visible" width="1500px" append-to-body>
<div>
<contractorMaterialRecord ref="contractorMaterialRecordRef"></contractorMaterialRecord>
</div>
</el-dialog>
</div>
</template>
<script setup name="ContractorMaterial" lang="ts">
import {
listContractorMaterial,
getContractorMaterial,
delContractorMaterial,
addContractorMaterial,
updateContractorMaterial
} from '@/api/project/contractorMaterial';
import contractorMaterialRecord from '@/views/project/contractorMaterial/component/contractorMaterialRecord.vue';
import { ContractorMaterialVO, ContractorMaterialQuery, ContractorMaterialForm } from '@/api/project/contractorMaterial/types';
import { useUserStoreHook } from '@/store/modules/user';
import { listContractor } from '@/api/project/contractor';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { contractor_material_type } = toRefs<any>(proxy?.useDict('contractor_material_type'));
// 获取用户 store
const userStore = useUserStoreHook();
const currentProject = computed(() => userStore.selectedProject);
const contractorMaterialList = ref<ContractorMaterialVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const contractorMaterialRecordRef = ref(null);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const contractorList = ref([]); //分包列表
const queryFormRef = ref<ElFormInstance>();
const contractorMaterialFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
// 出入库
const dialogRecord = reactive<DialogOption>({
visible: false,
title: ''
});
const initFormData: ContractorMaterialForm = {
id: undefined,
projectId: currentProject.value?.id,
contractorId: undefined,
materialName: undefined,
materialType: undefined,
materialModel: undefined,
materialUnit: undefined,
file: undefined,
remark: undefined
};
const data = reactive<PageData<ContractorMaterialForm, ContractorMaterialQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
projectId: currentProject.value?.id,
contractorId: undefined,
materialName: undefined,
materialType: undefined,
materialModel: undefined,
params: {}
},
rules: {
contractorId: [{ required: true, message: '分包方不能为空', trigger: 'blur' }],
materialName: [{ required: true, message: '物料名称不能为空', trigger: 'blur' }],
materialUnit: [{ required: true, message: '物料单位不能为空', trigger: 'blur' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询分包单位列表 */
const getSubList = async () => {
const res = await listContractor({
pageNum: 1,
pageSize: 10000,
projectId: currentProject.value?.id
});
contractorList.value = res.rows;
handleQuery();
};
/** 查询分包方物料列表 */
const getList = async () => {
loading.value = true;
const res = await listContractorMaterial(queryParams.value);
contractorMaterialList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
contractorMaterialFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
if (contractorList.value.length == 1) queryParams.value.contractorId = contractorList.value[0].id;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: ContractorMaterialVO[]) => {
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?: ContractorMaterialVO) => {
reset();
const _id = row?.id || ids.value[0];
const res = await getContractorMaterial(_id);
Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = '修改分包方物料';
};
/** 提交按钮 */
const submitForm = () => {
contractorMaterialFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateContractorMaterial(form.value).finally(() => (buttonLoading.value = false));
} else {
await addContractorMaterial(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: ContractorMaterialVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除分包方物料编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delContractorMaterial(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value?.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getSubList();
}
);
onUnmounted(() => {
listeningProject();
});
const handleView = async (row: ContractorToolVO) => {
// 打开弹框
dialogRecord.visible = true;
dialogRecord.title = row.materialName + '-物料出入库';
await nextTick();
contractorMaterialRecordRef.value.getAll(row);
};
onMounted(() => {
getSubList();
});
</script>

View File

@ -0,0 +1,374 @@
<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="never">
<el-descriptions border :column="2">
<el-descriptions-item label="分包方">{{ info.contractorName }}</el-descriptions-item>
<el-descriptions-item label="工具名称">{{ info.toolName }}</el-descriptions-item>
<el-descriptions-item label="工具型号">{{ info.toolModel }}</el-descriptions-item>
<el-descriptions-item label="工具数量">{{ info.toolNumber }}</el-descriptions-item>
</el-descriptions></el-card
>
<el-card shadow="never" style="margin-top: 10px">
<el-form ref="queryFormRef" label-width="110px" :model="queryParams" :inline="true">
<el-form-item label="检测编号" prop="checkNum">
<el-input v-model="queryParams.checkNum" placeholder="请输入检测编号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="检测部门" prop="checkDept">
<el-input v-model="queryParams.checkDept" 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('1', '进场时间')" v-hasPermi="['contractor:contractorToolEntry:add']"
>进场</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="primary" plain icon="Minus" @click="handleAdd('2', '出场时间')" v-hasPermi="['contractor:contractorToolEntry:add']"
>出场</el-button
>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete()"
v-hasPermi="['contractor:contractorToolEntry:remove']"
>删除</el-button
>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-tabs v-model="activeName" type="border-card" class="demo-tabs" @tab-click="handleClick">
<el-tab-pane label="进场" name="1">
<el-table v-loading="loading" height="30vh" :data="contractorToolEntryList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="分包方" align="center" prop="contractorName" />
<el-table-column label="工器具数量" align="center" prop="recordNumber" />
<el-table-column label="检测编号" align="center" prop="checkNum" />
<el-table-column label="检测部门" align="center" prop="checkDept" />
<el-table-column label="检测时间" align="center" prop="checkTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.checkTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="合格证" align="center" prop="certificate" />
<el-table-column label="进场时间" align="center" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.recordTime, '{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-tooltip content="修改" placement="top">
<el-button
link
type="primary"
icon="Edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['contractor:contractorToolEntry:edit']"
></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button
link
type="primary"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['contractor:contractorToolEntry: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-tab-pane>
<el-tab-pane label="出场" name="2">
<el-table v-loading="loading" height="50vh" :data="contractorToolEntryList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="分包方" align="center" prop="contractorName" />
<el-table-column label="工器具数量" align="center" prop="recordNumber" />
<el-table-column label="检测编号" align="center" prop="checkNum" />
<el-table-column label="检测部门" align="center" prop="checkDept" />
<el-table-column label="检测时间" align="center" prop="checkTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.checkTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<!-- <el-table-column label="合格证" align="center" prop="certificate" /> -->
<el-table-column label="出场时间" align="center" prop="recordTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.recordTime, '{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-tooltip content="修改" placement="top">
<el-button
link
type="primary"
icon="Edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['contractor:contractorToolEntry:edit']"
></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button
link
type="primary"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['contractor:contractorToolEntry: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-tab-pane>
</el-tabs>
</el-card>
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="contractorToolEntryFormRef" :model="form" :rules="rules" label-width="120px">
<el-form-item label="工器具数量" prop="recordNumber">
<el-input v-model="form.recordNumber" type="number" placeholder="请输入进场工器具数量" />
</el-form-item>
<el-form-item label="检测编号" prop="checkNum">
<el-input v-model="form.checkNum" placeholder="请输入检测编号" />
</el-form-item>
<el-form-item label="检测部门" prop="checkDept">
<el-input v-model="form.checkDept" placeholder="请输入检测部门" />
</el-form-item>
<el-form-item label="检测时间" prop="checkTime">
<el-date-picker clearable v-model="form.checkTime" type="date" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择检测时间">
</el-date-picker>
</el-form-item>
<el-form-item :label="titleLable" prop="entryTime">
<el-date-picker clearable v-model="form.entryTime" type="date" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择进场时间">
</el-date-picker>
</el-form-item>
<el-form-item label="合格证" prop="certificate">
<file-upload v-model="form.certificate" />
</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="ContractorToolEntry" lang="ts">
import {
listContractorToolEntry,
getContractorToolEntry,
delContractorToolEntry,
addContractorToolEntry,
updateContractorToolEntry
} from '@/api/project/contractorTool/contractorToolEntry';
import { ContractorToolEntryVO, ContractorToolEntryQuery, ContractorToolEntryForm } from '@/api/project/contractorTool/contractorToolEntry/types';
import { getContractorTool } from '@/api/project/contractorTool';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
import { useUserStoreHook } from '@/store/modules/user';
// 获取用户 store
const userStore = useUserStoreHook();
const currentProject = computed(() => userStore.selectedProject);
const contractorToolEntryList = ref<ContractorToolEntryVO[]>([]);
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 contractorToolEntryFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const titleLable = ref('进场时间');
const initFormData: ContractorToolEntryForm = {
id: undefined,
contractorToolId: undefined,
toolNumber: undefined,
checkNum: undefined,
checkDept: undefined,
checkTime: undefined,
certificate: undefined,
remark: undefined,
entryTime: undefined,
recordType: undefined,
recordNumber: undefined
};
const info = ref({
contractorName: undefined,
toolNumber: undefined,
toolName: undefined,
toolModel: undefined
});
const data = reactive<PageData<ContractorToolEntryForm, ContractorToolEntryQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
projectId: currentProject.value?.id,
contractorId: undefined,
contractorToolId: undefined,
toolNumber: undefined,
checkNum: undefined,
checkDept: undefined,
recordType: undefined,
params: {}
},
rules: {
contractorToolId: [{ required: true, message: '分包方工器具不能为空', trigger: 'blur' }]
}
});
const activeName = '1';
/** 查询分包方工器具进场列表 */
const getList = async () => {
loading.value = true;
const res = await listContractorToolEntry(queryParams.value);
contractorToolEntryList.value = res.rows;
total.value = res.total;
loading.value = false;
};
const getDetail = async (_id) => {
const res = await getContractorTool(_id);
info.value = res.data;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
contractorToolEntryFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: ContractorToolEntryVO[]) => {
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
/** 新增按钮操作 */
const handleAdd = (type, label) => {
reset();
titleLable.value = label;
dialog.visible = true;
form.value.recordType = type;
dialog.title = '工器具' + (type == 1 ? '进场' : '出场');
};
/** 修改按钮操作 */
const handleUpdate = async (row?: ContractorToolEntryVO) => {
reset();
const _id = row?.id || ids.value[0];
const res = await getContractorToolEntry(_id);
Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = '修改工器具';
};
/** 提交按钮 */
const submitForm = () => {
contractorToolEntryFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateContractorToolEntry(form.value).finally(() => (buttonLoading.value = false));
} else {
await addContractorToolEntry(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
getDetail(data.form.contractorToolId);
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: ContractorToolEntryVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除分包方工器具进场编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delContractorToolEntry(_ids);
proxy?.$modal.msgSuccess('删除成功');
getDetail(data.form.contractorToolId);
await getList();
};
const handleClick = (val) => {
queryParams.value.pageNum = 1;
queryParams.value.recordType = val.props.name;
handleQuery();
};
const getAll = (obj) => {
info.value = obj;
initFormData.contractorToolId = obj.id;
data.form.contractorToolId = obj.id;
data.queryParams.contractorToolId = obj.id;
getDetail(obj.id);
getList();
};
defineExpose({
getAll
});
const { queryParams, form, rules } = toRefs(data);
</script>

View File

@ -0,0 +1,325 @@
<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="contractorId">
<el-select v-model="queryParams.contractorId" filterable placeholder="请选择分包方">
<el-option v-for="(item, i) of contractorList" :key="i" :label="item.name" :value="item.id"> </el-option>
</el-select>
</el-form-item>
<el-form-item label="工具名称" prop="toolName">
<el-input v-model="queryParams.toolName" placeholder="请输入工具名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="工具类型" prop="toolType">
<el-select v-model="queryParams.toolType" placeholder="请选择工具类型" clearable>
<el-option v-for="dict in contractor_tool_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="工具型号" prop="toolModel">
<el-input v-model="queryParams.toolModel" placeholder="请输入工具型号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="工具数量" prop="toolNumber">
<el-input v-model="queryParams.toolNumber" 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="['contractor:contractorTool:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['contractor:contractorTool:edit']"
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete()"
v-hasPermi="['contractor:contractorTool:remove']"
>删除</el-button
>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" :data="contractorToolList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="分包方" align="center" prop="contractorName" />
<el-table-column label="工具名称" align="center" prop="toolName" />
<el-table-column label="工具类型" align="center" prop="toolType">
<template #default="scope">
<dict-tag :options="contractor_tool_type" :value="scope.row.toolType" />
</template>
</el-table-column>
<el-table-column label="工具型号" align="center" prop="toolModel" />
<el-table-column label="工具数量" align="center" prop="toolNumber" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<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="['contractor:contractorTool:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button
link
type="primary"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['contractor:contractorTool:remove']"
></el-button>
</el-tooltip>
<el-tooltip content="出入库" placement="top">
<el-button link type="primary" icon="view" @click="handleView(scope.row)"></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 draggable :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="contractorToolFormRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="分包方" prop="contractorId">
<el-select v-model="form.contractorId" filterable placeholder="请选择分包方">
<el-option v-for="(item, i) of contractorList" :key="i" :label="item.name" :value="item.id"> </el-option>
</el-select>
</el-form-item>
<el-form-item label="工具名称" prop="toolName">
<el-input v-model="form.toolName" placeholder="请输入工具名称" />
</el-form-item>
<el-form-item label="工具类型" prop="toolType">
<el-select v-model="form.toolType" placeholder="请选择工具类型">
<el-option v-for="dict in contractor_tool_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="工具型号" prop="toolModel">
<el-input v-model="form.toolModel" placeholder="请输入工具型号" />
</el-form-item>
<!-- <el-form-item label="文件" prop="file">
<file-upload v-model="form.file"/>
</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 draggable :title="dialogLevan.title" v-model="dialogLevan.visible" width="1500px" append-to-body>
<div>
<LevanAutbound ref="LevanAutboundRef"></LevanAutbound>
</div>
</el-dialog>
</div>
</template>
<script setup name="ContractorTool" lang="ts">
import { listContractorTool, getContractorTool, delContractorTool, addContractorTool, updateContractorTool } from '@/api/project/contractorTool';
import { ContractorToolVO, ContractorToolQuery, ContractorToolForm } from '@/api/project/contractorTool/types';
import { listContractor } from '@/api/project/contractor';
import { useUserStoreHook } from '@/store/modules/user';
import LevanAutbound from '@/views/project/contractorTool/component/LevanAutbound.vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
// 获取用户 store
const userStore = useUserStoreHook();
const currentProject = computed(() => userStore.selectedProject);
const { contractor_tool_type } = toRefs<any>(proxy?.useDict('contractor_tool_type'));
const contractorToolList = ref<ContractorToolVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const LevanAutboundRef = ref(null);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const contractorList = ref([]); //分包列表
const queryFormRef = ref<ElFormInstance>();
const contractorToolFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
// 出入库
const dialogLevan = reactive<DialogOption>({
visible: false,
title: ''
});
const initFormData: ContractorToolForm = {
id: undefined,
projectId: currentProject.value?.id,
contractorId: undefined,
toolName: undefined,
toolType: undefined,
toolModel: undefined,
toolNumber: undefined,
file: undefined,
remark: undefined
};
const data = reactive<PageData<ContractorToolForm, ContractorToolQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
projectId: currentProject.value?.id,
contractorId: undefined,
toolName: undefined,
toolType: undefined,
toolModel: undefined,
toolNumber: undefined,
params: {}
},
rules: {
contractorId: [{ required: true, message: '分包方不能为空', trigger: 'blur' }],
toolName: [{ required: true, message: '工具名称不能为空', trigger: 'blur' }],
toolType: [{ required: true, message: '工具类型不能为空', trigger: 'blur' }],
toolModel: [{ required: true, message: '工具数量不能为空', trigger: 'blur' }],
toolNumber: [{ required: true, message: '分包方不能为空', trigger: 'blur' }]
}
});
const { contractor_tool_record_type } = toRefs<any>(proxy?.useDict('contractor_tool_record_type'));
const { queryParams, form, rules } = toRefs(data);
/** 查询分包单位列表 */
const getSubList = async () => {
const res = await listContractor({
pageNum: 1,
pageSize: 10000,
projectId: currentProject.value?.id
});
contractorList.value = res.rows;
handleQuery();
};
/** 查询分包方工器具列表 */
const getList = async () => {
loading.value = true;
const res = await listContractorTool(queryParams.value);
contractorToolList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
contractorToolFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
if (contractorList.value.length == 1) queryParams.value.contractorId = contractorList.value[0].id;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: ContractorToolVO[]) => {
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?: ContractorToolVO) => {
reset();
const _id = row?.id || ids.value[0];
const res = await getContractorTool(_id);
Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = '修改工器具';
};
/** 提交按钮 */
const submitForm = () => {
contractorToolFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateContractorTool(form.value).finally(() => (buttonLoading.value = false));
} else {
await addContractorTool(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: ContractorToolVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除分包方工器具编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delContractorTool(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value?.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getSubList();
}
);
onUnmounted(() => {
listeningProject();
});
const handleView = async (row: ContractorToolVO) => {
// 打开弹框
dialogLevan.visible = true;
dialogLevan.title = row.toolName + '-工器具出入库';
await nextTick();
LevanAutboundRef.value.getAll(row);
};
onMounted(() => {
getSubList();
});
</script>

View File

@ -0,0 +1,265 @@
<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="110px">
<el-form-item label="道路名称" prop="roadName">
<el-input v-model="queryParams.roadName" placeholder="请输入道路名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="对应地块" prop="landBlockId">
<el-select v-model="queryParams.landBlockId" clearable placeholder="请选择对应地块">
<el-option v-for="item in landBlockList" :key="item.id" :label="item.landName" :value="item.id" />
</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="['land:enterRoad:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['land:enterRoad:remove']"
>删除</el-button
>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" :data="enterRoadList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="道路编号" align="center" prop="roadCode" />
<el-table-column label="道路名称" align="center" prop="roadName" />
<el-table-column label="设计新建道路长度(米)" align="center" prop="designCreateLength" />
<el-table-column label="设计改扩建长度(米)" align="center" prop="designUpdateLength" />
<el-table-column label="需流转总长度(米)" align="center" prop="changeLength" />
<el-table-column label="需要流转总面积(亩)" align="center" prop="changeArea" />
<el-table-column label="对应地块" align="center" prop="landName" />
<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" @click="handleUpdate(scope.row)" v-hasPermi="['land:enterRoad:edit']">编辑</el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" @click="handleDelete(scope.row)" v-hasPermi="['land:enterRoad: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 draggable :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="enterRoadFormRef" :model="form" :rules="rules" label-width="150px">
<el-form-item label="道路名称" prop="roadName">
<el-input v-model="form.roadName" placeholder="请输入道路名称" />
</el-form-item>
<el-form-item label="设计新建道路长度(米)" prop="designCreateLength">
<el-input v-model="form.designCreateLength" type="number" placeholder="请输入设计新建道路长度" />
</el-form-item>
<el-form-item label="设计改扩建长度(米)" prop="designUpdateLength">
<el-input v-model="form.designUpdateLength" type="number" placeholder="请输入设计改扩建长度" />
</el-form-item>
<el-form-item label="需流转总长度(米)" prop="changeLength">
<el-input v-model="form.changeLength" type="number" placeholder="请输入需流转总长度" />
</el-form-item>
<el-form-item label="需要流转总面积(亩)" prop="changeArea">
<el-input v-model="form.changeArea" type="number" placeholder="请输入需要流转总面积" />
</el-form-item>
<el-form-item label="对应地块" prop="landBlockId">
<el-select v-model="form.landBlockId" clearable placeholder="请选择对应地块">
<el-option v-for="item in landBlockList" :key="item.id" :label="item.landName" :value="item.id" />
</el-select>
</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="EnterRoad" lang="ts">
import { listEnterRoad, getEnterRoad, delEnterRoad, addEnterRoad, updateEnterRoad } from '@/api/system/landTransfer/enterRoad';
import { EnterRoadVO, EnterRoadQuery, EnterRoadForm } from '@/api/system/landTransfer/enterRoad/types';
import { listLandBlock } from '@/api/system/landTransfer/landBlock';
import { useUserStoreHook } from '@/store/modules/user';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
// 获取用户 store
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目
const currentProject = computed(() => userStore.selectedProject);
const enterRoadList = ref<EnterRoadVO[]>([]);
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 landBlockList = ref([]);
const queryFormRef = ref<ElFormInstance>();
const enterRoadFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const initFormData: EnterRoadForm = {
id: undefined,
projectId: currentProject.value?.id,
roadCode: undefined,
roadName: undefined,
designCreateLength: undefined,
designUpdateLength: undefined,
changeLength: undefined,
changeArea: undefined,
landBlockId: undefined
};
const data = reactive<PageData<EnterRoadForm, EnterRoadQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
projectId: currentProject.value?.id,
roadCode: undefined,
roadName: undefined,
designCreateLength: undefined,
designUpdateLength: undefined,
changeLength: undefined,
changeArea: undefined,
landBlockId: undefined,
params: {}
},
rules: {
id: [{ required: true, message: '主键ID不能为空', trigger: 'blur' }],
projectId: [{ required: true, message: '项目ID不能为空', trigger: 'blur' }],
roadCode: [{ required: true, message: '道路编号不能为空', trigger: 'blur' }],
roadName: [{ required: true, message: '道路名称不能为空', trigger: 'blur' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询进场道路信息列表 */
const getList = async () => {
loading.value = true;
const res = await listEnterRoad(queryParams.value);
enterRoadList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 查询地块信息列表 */
const getListLand = async () => {
const res = await listLandBlock({
pageNum: 1,
pageSize: 10000,
projectId: currentProject.value?.id
});
landBlockList.value = res.rows;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
enterRoadFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: EnterRoadVO[]) => {
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?: EnterRoadVO) => {
reset();
const _id = row?.id || ids.value[0];
const res = await getEnterRoad(_id);
Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = '修改进场道路信息';
};
/** 提交按钮 */
const submitForm = () => {
enterRoadFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateEnterRoad(form.value).finally(() => (buttonLoading.value = false));
} else {
await addEnterRoad(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: EnterRoadVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除进场道路信息编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delEnterRoad(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value?.id,
(nid, oid) => {
queryParams.value.projectId = nid;
getListLand();
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getListLand();
getList();
});
</script>

View File

@ -0,0 +1,398 @@
<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="110px">
<el-form-item label="地块编号" prop="landCode">
<el-input v-model="queryParams.landCode" placeholder="请输入地块编号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="地块名称" prop="landName">
<el-input v-model="queryParams.landName" placeholder="请输入地块名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="所属村委会" prop="villageCommittee">
<el-input v-model="queryParams.villageCommittee" placeholder="请输入所属村委会" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="设计面积(亩)" prop="designArea">
<el-input v-model="queryParams.designArea" type="number" placeholder="请输入设计面积" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="地块数(块)" prop="blockCount">
<el-input v-model="queryParams.blockCount" type="number" placeholder="请输入地块数" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="农户数(户)" prop="farmerCount">
<el-input v-model="queryParams.farmerCount" type="number" 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="['land:landBlock:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['land:landBlock:remove']"
>删除</el-button
>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table draggable v-loading="loading" :data="landBlockList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="地块编号" align="center" prop="landCode" />
<el-table-column label="地块名称" align="center" prop="landName" />
<el-table-column label="方阵" align="center" prop="unit" />
<el-table-column label="所属村委会" align="center" prop="villageCommittee" />
<el-table-column label="设计面积(亩)" align="center" prop="designArea" />
<el-table-column label="地块数(块)" align="center" prop="blockCount" />
<el-table-column label="农户数(户)" align="center" prop="farmerCount" />
<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" @click="handleUpdate(scope.row)" v-hasPermi="['land:landBlock:edit']">编辑</el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" @click="handleDelete(scope.row)" v-hasPermi="['land:landBlock:remove']">删除</el-button>
</el-tooltip>
<el-tooltip content="关联方阵" placement="top">
<el-button type="primary" link @click="handleView(scope.row)">关联方阵</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 draggable :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="landBlockFormRef" :model="form" :rules="rules" label-width="100px">
<!-- <el-form-item label="地块编号" prop="landCode">
<el-input v-model="form.landCode" placeholder="请输入地块编号" />
</el-form-item> -->
<el-form-item label="地块名称" prop="landName">
<el-input v-model="form.landName" placeholder="请输入地块名称" />
</el-form-item>
<el-form-item label="所属村委会" prop="villageCommittee">
<el-input v-model="form.villageCommittee" placeholder="请输入所属村委会" />
</el-form-item>
<el-form-item label="设计面积(亩)" prop="designArea">
<el-input type="number" v-model="form.designArea" placeholder="请输入设计面积" />
</el-form-item>
<el-form-item label="地块数(块)" prop="blockCount">
<el-input type="number" v-model="form.blockCount" placeholder="请输入地块数" />
</el-form-item>
<el-form-item label="农户数(户)" prop="farmerCount">
<el-input type="number" v-model="form.farmerCount" 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 draggable :title="dialogMatrix.title" v-model="dialogMatrix.visible" width="800px" append-to-body>
<el-button type="primary" plain icon="Plus" @click="addUnitBoItem" style="margin-bottom: 15px">添加</el-button>
<el-form ref="landBlockFormMatrixRef" :model="formM" :rules="rules" label-width="100px">
<el-row v-for="(item, i) of unitBoList" :key="i">
<el-col :span="9">
<el-form-item label="方阵" prop="matrixId">
<el-cascader
:options="fangzhenList"
placeholder="请选择"
filterable
:props="{ value: 'matrixId', label: 'name' }"
v-model="item.unitProjectId"
clearable
/>
</el-form-item>
</el-col>
<el-col :span="7">
<el-form-item label="所属工区" prop="unitProjectArea">
<el-input v-model="item.unitProjectArea" placeholder="请输入所属工区" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="方阵状态" prop="unitProjectStatus">
<el-input v-model="item.unitProjectStatus" placeholder="请输入方阵状态" />
</el-form-item>
</el-col>
<el-col :span="1" style="margin-left: 15px">
<el-button type="danger" icon="Delete" @click="removeUnitBoItem(i)"></el-button>
</el-col>
</el-row>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitFormMatrix"> </el-button>
<el-button @click="cancelMatrix"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="LandBlock" lang="ts">
import { listLandBlock, getLandBlock, delLandBlock, LandUnit, addLandBlock, updateLandBlock, subMatrix } from '@/api/system/landTransfer/landBlock';
import { LandBlockVO, LandBlockQuery, LandBlockForm } from '@/api/system/landTransfer/landBlock/types';
import { useUserStoreHook } from '@/store/modules/user';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
// 获取用户 store
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目
const currentProject = computed(() => userStore.selectedProject);
const landBlockList = ref<LandBlockVO[]>([]);
const fangzhenList = ref([]); //方阵列表数据
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const unitBoList = ref([
{
unitProjectArea: '1',
unitProjectStatus: '1',
unitProjectId: []
}
]);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const landBlockFormRef = ref<ElFormInstance>();
const landBlockFormMatrixRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const dialogMatrix = reactive<DialogOption>({
visible: false,
title: '选择方阵'
});
const initFormData: LandBlockForm = {
id: undefined,
projectId: currentProject.value?.id,
landCode: undefined,
landName: undefined,
villageCommittee: undefined,
designArea: undefined,
blockCount: undefined,
farmerCount: undefined,
remark: undefined
};
const data = reactive({
form: { ...initFormData },
formM: {
landId: undefined
},
queryParams: {
pageNum: 1,
pageSize: 10,
projectId: currentProject.value?.id,
landCode: undefined,
landName: undefined,
villageCommittee: undefined,
designArea: undefined,
blockCount: undefined,
farmerCount: undefined,
params: {}
},
rules: {
id: [{ required: true, message: '主键ID不能为空', trigger: 'blur' }],
projectId: [{ required: true, message: '项目ID不能为空', trigger: 'blur' }],
landCode: [{ required: true, message: '地块编号不能为空', trigger: 'blur' }],
landName: [{ required: true, message: '地块名称不能为空', trigger: 'blur' }]
}
});
const { queryParams, form, rules, formM } = toRefs(data);
/** 查询地块信息列表 */
const getList = async () => {
loading.value = true;
const res = await listLandBlock(queryParams.value);
landBlockList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
landBlockFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: LandBlockVO[]) => {
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?: LandBlockVO) => {
reset();
const _id = row?.id || ids.value[0];
const res = await getLandBlock(_id);
Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = '修改地块信息';
};
/** 提交按钮 */
const submitForm = () => {
landBlockFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateLandBlock(form.value).finally(() => (buttonLoading.value = false));
} else {
await addLandBlock(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: LandBlockVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除地块信息编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delLandBlock(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
// 获取方阵列表
const getfangzhenList = async () => {
loading.value = true;
const res = await subMatrix(currentProject.value?.id);
res.data.forEach((item) => {
item.children.forEach((item2) => {
item2.matrixId = item2.name + '_' + item2.matrixId;
});
});
fangzhenList.value = res.data;
};
const handleView = async (row) => {
// 关联方阵
dialogMatrix.visible = true;
dialogMatrix.title = '关联方阵';
data.formM.landId = row.id;
};
// 动态添加unitBoList项
const addUnitBoItem = () => {
unitBoList.value.push({
unitProjectArea: '',
unitProjectStatus: '',
unitProjectId: []
});
};
// 移除unitBoList项
const removeUnitBoItem = (index: number) => {
if (unitBoList.value.length > 1) {
unitBoList.value.splice(index, 1);
} else {
proxy?.$modal.msgWarning('至少保留一项');
}
};
const submitFormMatrix = () => {
landBlockFormMatrixRef.value?.validate(async (valid: boolean) => {
if (valid) {
var arr = [];
unitBoList.value.forEach((item) => {
let str = item.unitProjectId[1].split('_');
arr.push({
unitProjectArea: item.unitProjectArea,
unitProjectStatus: item.unitProjectStatus,
unitProjectId: str[1],
unitProjectName: str[0]
});
});
var res = await LandUnit({ ...formM.value, unitBoList: arr });
if (res.code == 200) {
proxy?.$modal.msgSuccess('操作成功');
dialogMatrix.visible = false;
await getList();
} else {
proxy?.$modal.msgError(res.msg);
}
}
});
};
/** 取消按钮 */
const cancelMatrix = () => {
resetMatrix();
dialogMatrix.visible = false;
};
/** 表单重置 */
const resetMatrix = () => {
data.formM.landId = '';
unitBoList.value = [
{
unitProjectArea: '1',
unitProjectStatus: '1',
unitProjectId: []
}
];
landBlockFormMatrixRef.value?.resetFields();
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value?.id,
(nid, oid) => {
queryParams.value.projectId = nid;
getfangzhenList();
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
getfangzhenList();
});
</script>

View File

@ -0,0 +1,400 @@
<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="110px">
<el-form-item label="对应地块" prop="landBlockId">
<el-select v-model="queryParams.landBlockId" clearable placeholder="请选择对应地块">
<el-option v-for="item in landBlockList" :key="item.id" :label="item.landName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="流转台账状态" prop="transferStatus">
<el-select v-model="queryParams.transferStatus" placeholder="请选择流转台账状态" clearable>
<el-option label="待流转" :value="0"></el-option>
<el-option label="已流转" :value="1"></el-option> </el-select
></el-form-item>
<el-form-item label="责任人" prop="responsiblePerson">
<el-input v-model="queryParams.responsiblePerson" placeholder="请输入责任人" clearable @keyup.enter="handleQuery" />
</el-form-item>
<!-- <el-form-item label="预计完成时间" prop="expectedFinishDate">
<el-date-picker
clearable
v-model="queryParams.expectedFinishDate"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择预计完成时间"
/>
</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="['land:landTransferLedger:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['land:landTransferLedger:remove']"
>删除</el-button
>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" :data="landTransferLedgerList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="土地类型" align="center" prop="landTypeName" />
<el-table-column label="地块" align="center" prop="landName" />
<el-table-column label="进场道路" align="center" prop="roadName" />
<el-table-column label="设计面积(亩)" align="center" prop="designArea" width="180" />
<el-table-column label="责任人" align="center" prop="responsiblePerson" />
<el-table-column label="预计完成时间" align="center" prop="expectedFinishDate" width="180"> </el-table-column>
<el-table-column label="流转状态" align="center" prop="transferStatusName" />
<el-table-column label="已流转面积(亩)" align="center" prop="transferAea" width="180" />
<el-table-column label="流转比例(%)" align="center" prop="transferRatio" width="180" />
<el-table-column label="土地租金(元)" align="center" prop="landRent" width="180" />
<el-table-column label="青苗赔偿(元)" align="center" prop="seedlingCompensation" width="180" />
<el-table-column label="总金额(元)" align="center" prop="totalAmount" width="150" />
<el-table-column label="状态说明" align="center" prop="statusDescription" />
<el-table-column label="问题总结" align="center" prop="issueSummary" />
<el-table-column label="下一步策略" align="center" prop="nextStrategy" width="180" />
<!-- 固定列 -->
<el-table-column label="操作" align="center" fixed="right" width="200">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['land:landTransferLedger:edit']">编辑</el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" @click="handleDelete(scope.row)" v-hasPermi="['land:landTransferLedger: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 draggable :title="dialog.title" v-model="dialog.visible" width="900px" append-to-body>
<el-form ref="landTransferLedgerFormRef" :model="form" :rules="rules" label-width="120px">
<el-row>
<el-col :span="12">
<el-form-item label="对应地块" prop="landBlockId">
<el-select v-model="form.landBlockId" clearable placeholder="请选择对应地块" @change="handleLandBlockChange">
<el-option v-for="item in landBlockList" :key="item.id" :label="item.landName" :value="item.id" />
</el-select> </el-form-item
></el-col>
<el-col :span="12">
<el-form-item label="进场道路" prop="enterRoadId">
<el-select v-model="form.enterRoadId" clearable placeholder="请选择对应地块">
<el-option v-for="item in enterRoadList" :key="item.id" :label="item.roadName" :value="item.id" />
</el-select> </el-form-item
></el-col>
<el-col :span="12">
<el-form-item label="土地类型" prop="landType">
<el-select v-model="form.landType" placeholder="请选择土地类型" clearable>
<el-option v-for="dict in land_type" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select></el-form-item
></el-col>
<el-col :span="12">
<el-form-item label="流转台账状态" prop="transferStatus">
<el-select v-model="form.transferStatus" :disabled="!form.id" placeholder="请选择流转台账状态" clearable>
<el-option
v-for="dict in land_transfer_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/> </el-select></el-form-item
></el-col>
<el-col :span="12">
<el-form-item label="设计面积(亩)" prop="designArea">
<el-input type="number" v-model="form.designArea" placeholder="请输入设计面积" /> </el-form-item
></el-col>
<el-col :span="12"
><el-form-item label="责任人" prop="responsiblePerson">
<el-input v-model="form.responsiblePerson" placeholder="请输入责任人" /> </el-form-item
></el-col>
<el-col v-if="form.transferStatus != '2'" :span="12"
><el-form-item label="预计完成日期" prop="expectedFinishDate">
<el-date-picker clearable v-model="form.expectedFinishDate" type="date" value-format="YYYY-MM-DD" placeholder="请选择预计完成时间">
</el-date-picker> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '1'" :span="12"
><el-form-item label="已流转面积(亩)" prop="transferAea">
<el-input v-model="form.transferAea" type="number" placeholder="请输入已流转面积" /> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '1'" :span="12"
><el-form-item label="流转比例(%)" prop="transferRatio">
<el-input v-model="form.transferRatio" type="number" placeholder="请输入流转比例" /> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '1'" :span="12">
<el-form-item label="土地租金(元)" prop="landRent">
<el-input type="number" v-model="form.landRent" placeholder="请输入土地租金" /> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '1'" :span="12">
<el-form-item label="青苗赔偿(元)" prop="seedlingCompensation">
<el-input v-model="form.seedlingCompensation" type="number" placeholder="请输入青苗赔偿" /> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '1'" :span="12">
<el-form-item label="总金额(元)" prop="totalAmount">
<el-input type="number" v-model="form.totalAmount" placeholder="请输入总金额" /> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '2'" :span="12"
><el-form-item label="不签合同面积(亩)" prop="noContractArea">
<el-input v-model="form.noContractArea" type="number" placeholder="请输入不签合同面积" /> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '2'" :span="12">
<el-form-item label="不测量面积(亩)" prop="noSurveyArea">
<el-input v-model="form.noSurveyArea" type="number" placeholder="请输入不测量面积" /> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '2'" :span="24"
><el-form-item label="不签合同原因" prop="noContractReason">
<el-input v-model="form.noContractReason" type="textarea" placeholder="请输入内容" /> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '2'" :span="24"
><el-form-item label="不流转原因" prop="nonTransferReason">
<el-input v-model="form.nonTransferReason" type="textarea" placeholder="请输入内容" /> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '1'" :span="24"
><el-form-item label="状态说明" prop="statusDescription">
<el-input v-model="form.statusDescription" type="textarea" placeholder="请输入内容" /> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '1'" :span="24"
><el-form-item label="问题总结" prop="issueSummary">
<el-input v-model="form.issueSummary" type="textarea" placeholder="请输入内容" /> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '1'" :span="24">
<el-form-item label="下一步策略" prop="nextStrategy">
<el-input v-model="form.nextStrategy" type="textarea" placeholder="请输入内容" /> </el-form-item
></el-col>
</el-row>
</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="LandTransferLedger" lang="ts">
import {
listLandTransferLedger,
getLandTransferLedger,
delLandTransferLedger,
addLandTransferLedger,
updateLandTransferLedger
} from '@/api/system/landTransfer/landTransferLedger';
import { listEnterRoad } from '@/api/system/landTransfer/enterRoad';
import { LandTransferLedgerVO, LandTransferLedgerQuery, LandTransferLedgerForm } from '@/api/system/landTransfer/landTransferLedger/types';
import { useUserStoreHook } from '@/store/modules/user';
import { listLandBlock } from '@/api/system/landTransfer/landBlock';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
// 获取用户 store
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目
const currentProject = computed(() => userStore.selectedProject);
const landTransferLedgerList = ref<LandTransferLedgerVO[]>([]);
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 landBlockList = ref([]);
const queryFormRef = ref<ElFormInstance>();
const landTransferLedgerFormRef = ref<ElFormInstance>();
const enterRoadList = ref([]);
const { land_type, land_transfer_status } = toRefs<any>(proxy?.useDict('land_type', 'land_transfer_status'));
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const initFormData = {
id: undefined,
projectId: currentProject.value?.id,
landType: undefined,
landBlockId: undefined,
enterRoadId: undefined,
designArea: undefined,
responsiblePerson: undefined,
expectedFinishDate: undefined,
transferAea: undefined,
transferRatio: undefined,
landRent: undefined,
seedlingCompensation: undefined,
totalAmount: undefined,
transferStatus: undefined,
statusDescription: undefined,
issueSummary: undefined,
nextStrategy: undefined,
noContractArea: undefined,
noContractReason: undefined,
noSurveyArea: undefined,
nonTransferReason: undefined
};
const data = reactive<PageData<LandTransferLedgerForm, LandTransferLedgerQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
projectId: currentProject.value?.id,
landType: undefined,
landBlockId: undefined,
enterRoadId: undefined,
designArea: undefined,
responsiblePerson: undefined,
expectedFinishDate: undefined,
transferAea: undefined,
transferRatio: undefined,
landRent: undefined,
seedlingCompensation: undefined,
totalAmount: undefined,
transferStatus: undefined,
statusDescription: undefined,
issueSummary: undefined,
nextStrategy: undefined,
params: {},
listType: 1
},
rules: {
id: [{ required: true, message: '主键ID不能为空', trigger: 'blur' }],
projectId: [{ required: true, message: '项目ID不能为空', trigger: 'blur' }],
landType: [{ required: true, message: '土地类型不能为空', trigger: 'change' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询项目土地流转台账列表 */
const getList = async () => {
loading.value = true;
const res = await listLandTransferLedger(queryParams.value);
landTransferLedgerList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
dialog.visible = false;
reset();
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
landTransferLedgerFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: LandTransferLedgerVO[]) => {
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
/** 新增按钮操作 */
const handleAdd = () => {
reset();
form.value.transferStatus = '0';
dialog.visible = true;
enterRoadList.value = [];
dialog.title = '添加项目土地流转台账';
};
/** 修改按钮操作 */
const handleUpdate = async (row?: LandTransferLedgerVO) => {
reset();
form.value.landBlockId = row?.landBlockId;
getListRoad();
const _id = row?.id || ids.value[0];
const res = await getLandTransferLedger(_id);
Object.assign(form.value, res.data);
console.log(form.value);
dialog.visible = true;
dialog.title = '修改项目土地流转台账';
};
/** 提交按钮 */
const submitForm = () => {
landTransferLedgerFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateLandTransferLedger(form.value).finally(() => (buttonLoading.value = false));
} else {
await addLandTransferLedger(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: LandTransferLedgerVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除项目土地流转台账编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delLandTransferLedger(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
// 选择地块
const handleLandBlockChange = (val) => {
getListRoad();
};
/** 查询地块信息列表 */
const getListLand = async () => {
const res = await listLandBlock({
pageNum: 1,
pageSize: 10000,
projectId: currentProject.value?.id
});
landBlockList.value = res.rows;
};
/** 查询进场道路信息列表 */
const getListRoad = async () => {
const res = await listEnterRoad({ pageNum: 1, pageSize: 10000, projectId: currentProject.value?.id, landBlockId: form.value.landBlockId });
enterRoadList.value = res.rows;
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value?.id,
(nid, oid) => {
queryParams.value.projectId = nid;
getListLand();
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
getListLand();
});
</script>

View File

@ -0,0 +1,358 @@
<template>
<div class="p-2">
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="110px">
<el-form-item label="对应地块" prop="landBlockId">
<el-select v-model="queryParams.landBlockId" clearable placeholder="请选择对应地块">
<el-option v-for="item in landBlockList" :key="item.id" :label="item.landName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="设计面积" prop="designArea">
<el-input v-model="queryParams.designArea" placeholder="请输入设计面积" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="责任人" prop="responsiblePerson">
<el-input v-model="queryParams.responsiblePerson" 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>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" :data="landTransferLedgerList">
<!-- 二级表格 -->
<el-table-column type="expand">
<template #default="scope">
<el-table :data="scope.row.unitBoList" border>
<el-table-column label="序号" align="center" type="index" width="100" />
<el-table-column label="地块名称" align="center" prop="unitProjectName" />
<el-table-column label="所属工区" align="center" prop="unitProjectArea" />
<el-table-column label="方阵状态" align="center" prop="unitProjectStatus" />
</el-table>
</template>
</el-table-column>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column label="土地类型" align="center" prop="landTypeName" />
<el-table-column label="地块" align="center" prop="landName" />
<el-table-column label="进场道路" align="center" prop="roadName" />
<el-table-column label="设计面积(亩)" align="center" prop="designArea" width="180" />
<el-table-column label="责任人" align="center" prop="responsiblePerson" />
<el-table-column label="预计完成时间" align="center" prop="expectedFinishDate" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.expectedFinishDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="流转状态" align="center" prop="transferStatusName" />
<el-table-column label="已流转面积(亩)" align="center" prop="transferAea" width="180" />
<el-table-column label="流转比例(%)" align="center" prop="transferRatio" width="180" />
<el-table-column label="土地租金(元)" align="center" prop="landRent" width="180" />
<el-table-column label="青苗赔偿(元)" align="center" prop="seedlingCompensation" width="180" />
<el-table-column label="总金额(元)" align="center" prop="totalAmount" width="150" />
<el-table-column label="状态说明" align="center" prop="statusDescription" />
<el-table-column label="问题总结" align="center" prop="issueSummary" />
<el-table-column label="下一步策略" align="center" prop="nextStrategy" width="180" />
<!-- <el-table-column label="操作" fixed="right" align="center" width="200">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['land:landTransferLedger:edit']">编辑</el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" @click="handleDelete(scope.row)" v-hasPermi="['land:landTransferLedger: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 draggable :title="dialog.title" v-model="dialog.visible" width="800px" append-to-body>
<el-form ref="landTransferLedgerFormRef" :model="form" :rules="rules" label-width="110px">
<el-row>
<el-col :span="12">
<el-form-item label="对应地块" prop="landBlockId">
<el-select v-model="form.landBlockId" clearable placeholder="请选择对应地块" @change="handleLandBlockChange">
<el-option v-for="item in landBlockList" :key="item.id" :label="item.landName" :value="item.id" />
</el-select> </el-form-item
></el-col>
<el-col :span="12" v-if="enterRoadList.length">
<el-form-item label="进场道路" prop="enterRoadId">
<el-select v-model="form.enterRoadId" clearable placeholder="请选择对应地块">
<el-option v-for="item in enterRoadList" :key="item.id" :label="item.roadName" :value="item.id" />
</el-select> </el-form-item
></el-col>
<el-col :span="12">
<el-form-item label="土地类型" prop="landType">
<el-select v-model="form.landType" placeholder="请选择土地类型" clearable>
<el-option v-for="dict in land_type" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select></el-form-item
></el-col>
<el-col :span="12">
<el-form-item label="流转台账状态" prop="transferStatus">
<el-select v-model="form.transferStatus" placeholder="请选择流转台账状态" clearable>
<el-option v-for="dict in transfer_status" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select></el-form-item
></el-col>
<el-col :span="12">
<el-form-item label="设计面积" prop="designArea"> <el-input v-model="form.designArea" placeholder="请输入设计面积" /> </el-form-item
></el-col>
<el-col :span="12"
><el-form-item label="责任人" prop="responsiblePerson">
<el-input v-model="form.responsiblePerson" placeholder="请输入责任人" /> </el-form-item
></el-col>
<el-col :span="12"
><el-form-item label="预计完成日期" prop="expectedFinishDate">
<el-date-picker clearable v-model="form.expectedFinishDate" type="date" value-format="YYYY-MM-DD" placeholder="请选择预计完成时间">
</el-date-picker> </el-form-item
></el-col>
<el-col :span="12"
><el-form-item label="已流转面积" prop="transferAea">
<el-input v-model="form.transferAea" placeholder="请输入已流转面积" /> </el-form-item
></el-col>
<el-col :span="12"
><el-form-item label="流转比例" prop="transferRatio">
<el-input v-model="form.transferRatio" placeholder="请输入流转比例" /> </el-form-item
></el-col>
<el-col :span="12">
<el-form-item label="土地租金" prop="landRent"> <el-input v-model="form.landRent" placeholder="请输入土地租金" /> </el-form-item
></el-col>
<el-col :span="12">
<el-form-item label="青苗赔偿" prop="seedlingCompensation">
<el-input v-model="form.seedlingCompensation" placeholder="请输入青苗赔偿" /> </el-form-item
></el-col>
<el-col :span="12">
<el-form-item label="总金额" prop="totalAmount">
<el-input type="number" v-model="form.totalAmount" placeholder="请输入总金额" /> </el-form-item
></el-col>
<el-col :span="24"
><el-form-item label="状态说明" prop="statusDescription">
<el-input v-model="form.statusDescription" type="textarea" placeholder="请输入内容" /> </el-form-item
></el-col>
<el-col :span="24"
><el-form-item label="问题总结" prop="issueSummary">
<el-input v-model="form.issueSummary" type="textarea" placeholder="请输入内容" /> </el-form-item
></el-col>
<el-col :span="24">
<el-form-item label="下一步策略" prop="nextStrategy">
<el-input v-model="form.nextStrategy" type="textarea" placeholder="请输入内容" /> </el-form-item
></el-col>
</el-row>
</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="LandTransferLedger" lang="ts">
import {
ListUnitLandTransferLedger,
getLandTransferLedger,
delLandTransferLedger,
addLandTransferLedger,
updateLandTransferLedger
} from '@/api/system/landTransfer/landTransferLedger';
import { listEnterRoad } from '@/api/system/landTransfer/enterRoad';
import { LandTransferLedgerVO, LandTransferLedgerQuery, LandTransferLedgerForm } from '@/api/system/landTransfer/landTransferLedger/types';
import { useUserStoreHook } from '@/store/modules/user';
import { listLandBlock } from '@/api/system/landTransfer/landBlock';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
// 获取用户 store
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目
const currentProject = computed(() => userStore.selectedProject);
const landTransferLedgerList = ref<LandTransferLedgerVO[]>([]);
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 landBlockList = ref([]);
const queryFormRef = ref<ElFormInstance>();
const landTransferLedgerFormRef = ref<ElFormInstance>();
const enterRoadList = ref([]);
const { land_type, transfer_status } = toRefs<any>(proxy?.useDict('land_type', 'transfer_status'));
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const initFormData: LandTransferLedgerForm = {
id: undefined,
projectId: currentProject.value?.id,
landType: undefined,
landBlockId: undefined,
enterRoadId: undefined,
designArea: undefined,
responsiblePerson: undefined,
expectedFinishDate: undefined,
transferAea: undefined,
transferRatio: undefined,
landRent: undefined,
seedlingCompensation: undefined,
totalAmount: undefined,
transferStatus: undefined,
statusDescription: undefined,
issueSummary: undefined,
nextStrategy: undefined
};
const data = reactive<PageData<LandTransferLedgerForm, LandTransferLedgerQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
projectId: currentProject.value?.id,
landType: undefined,
landBlockId: undefined,
enterRoadId: undefined,
designArea: undefined,
responsiblePerson: undefined,
expectedFinishDate: undefined,
transferAea: undefined,
transferRatio: undefined,
landRent: undefined,
seedlingCompensation: undefined,
totalAmount: undefined,
transferStatus: undefined,
statusDescription: undefined,
issueSummary: undefined,
nextStrategy: undefined,
params: {}
},
rules: {
id: [{ required: true, message: '主键ID不能为空', trigger: 'blur' }],
projectId: [{ required: true, message: '项目ID不能为空', trigger: 'blur' }],
landType: [{ required: true, message: '土地类型不能为空', trigger: 'change' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询项目土地流转台账列表 */
const getList = async () => {
loading.value = true;
const res = await ListUnitLandTransferLedger(queryParams.value);
landTransferLedgerList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
landTransferLedgerFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: LandTransferLedgerVO[]) => {
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?: LandTransferLedgerVO) => {
reset();
const _id = row?.id || ids.value[0];
const res = await getLandTransferLedger(_id);
Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = '修改项目土地流转台账';
};
/** 提交按钮 */
const submitForm = () => {
landTransferLedgerFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateLandTransferLedger(form.value).finally(() => (buttonLoading.value = false));
} else {
await addLandTransferLedger(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: LandTransferLedgerVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除项目土地流转台账编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delLandTransferLedger(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
// 选择地块
const handleLandBlockChange = (val) => {
console.log(val);
getListRoad();
};
/** 查询地块信息列表 */
const getListLand = async () => {
const res = await listLandBlock({
pageNum: 1,
pageSize: 10000,
projectId: currentProject.value?.id
});
landBlockList.value = res.rows;
};
/** 查询进场道路信息列表 */
const getListRoad = async () => {
const res = await listEnterRoad({ pageNum: 1, pageSize: 10000, projectId: currentProject.value?.id, landBlockId: form.value.landBlockId });
enterRoadList.value = res.rows;
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value?.id,
(nid, oid) => {
queryParams.value.projectId = nid;
getListLand();
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
getListLand();
});
</script>

View File

@ -0,0 +1,312 @@
<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="landBlockId">
<el-select v-model="queryParams.landBlockId" clearable placeholder="请选择对应地块">
<el-option v-for="item in landBlockList" :key="item.id" :label="item.landName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="设计面积" prop="designArea">
<el-input v-model="queryParams.designArea" 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="['land:nonTransferLedger:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['land:nonTransferLedger:remove']"
>删除</el-button
>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" :data="nonTransferLedgerList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="土地类型" align="center" prop="landTypeName" />
<el-table-column label="地块" align="center" prop="landName" />
<el-table-column label="进场道路" align="center" prop="roadName" />
<el-table-column label="设计面积" align="center" prop="designArea" />
<el-table-column label="不签合同面积" align="center" prop="noContractArea" />
<el-table-column label="不签合同原因" align="center" prop="noContractReason" />
<el-table-column label="不测量面积" align="center" prop="noSurveyArea" />
<el-table-column label="不流转原因" align="center" prop="nonTransferReason" />
<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="['land:nonTransferLedger:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button
link
type="primary"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['land:nonTransferLedger: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="800px" append-to-body>
<el-form ref="nonTransferLedgerFormRef" :model="form" :rules="rules" label-width="110px">
<el-row>
<el-col :span="12">
<el-form-item label="对应地块" prop="landBlockId">
<el-select v-model="form.landBlockId" clearable placeholder="请选择对应地块" @change="handleLandBlockChange">
<el-option v-for="item in landBlockList" :key="item.id" :label="item.landName" :value="item.id" />
</el-select> </el-form-item
></el-col>
<el-col :span="12" v-if="enterRoadList.length">
<el-form-item label="进场道路" prop="enterRoadId">
<el-select v-model="form.enterRoadId" clearable placeholder="请选择对应地块">
<el-option v-for="item in enterRoadList" :key="item.id" :label="item.roadName" :value="item.id" />
</el-select> </el-form-item
></el-col>
<el-col :span="12">
<el-form-item label="土地类型" prop="landType">
<el-select v-model="form.landType" placeholder="请选择土地类型" clearable>
<el-option v-for="dict in land_type" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select></el-form-item
></el-col>
<el-col :span="12">
<el-form-item label="设计面积" prop="designArea"> <el-input v-model="form.designArea" placeholder="请输入设计面积" /> </el-form-item
></el-col>
<el-col :span="12"
><el-form-item label="不签合同面积" prop="noContractArea">
<el-input v-model="form.noContractArea" placeholder="请输入不签合同面积" /> </el-form-item
></el-col>
<el-col :span="12">
<el-form-item label="不测量面积" prop="noSurveyArea">
<el-input v-model="form.noSurveyArea" placeholder="请输入不测量面积" /> </el-form-item
></el-col>
<el-col :span="24"
><el-form-item label="不签合同原因" prop="noContractReason">
<el-input v-model="form.noContractReason" type="textarea" placeholder="请输入内容" /> </el-form-item
></el-col>
<el-col :span="24"
><el-form-item label="不流转原因" prop="nonTransferReason">
<el-input v-model="form.nonTransferReason" type="textarea" placeholder="请输入内容" /> </el-form-item
></el-col>
</el-row>
</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="NonTransferLedger" lang="ts">
import {
listNonTransferLedger,
getNonTransferLedger,
delNonTransferLedger,
addNonTransferLedger,
updateNonTransferLedger
} from '@/api/system/landTransfer/nonTransferLedger';
import { NonTransferLedgerVO, NonTransferLedgerQuery, NonTransferLedgerForm } from '@/api/system/landTransfer/nonTransferLedger/types';
import { listEnterRoad } from '@/api/system/landTransfer/enterRoad';
import { listLandBlock } from '@/api/system/landTransfer/landBlock';
import { useUserStoreHook } from '@/store/modules/user';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
// 获取用户 store
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目
const currentProject = computed(() => userStore.selectedProject);
const nonTransferLedgerList = ref<NonTransferLedgerVO[]>([]);
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 landBlockList = ref([]);
const enterRoadList = ref([]);
const queryFormRef = ref<ElFormInstance>();
const nonTransferLedgerFormRef = ref<ElFormInstance>();
const { land_type } = toRefs<any>(proxy?.useDict('land_type', 'transfer_status'));
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const initFormData: NonTransferLedgerForm = {
id: undefined,
projectId: currentProject.value?.id,
landType: undefined,
landBlockId: undefined,
enterRoadId: undefined,
designArea: undefined,
noContractArea: undefined,
noContractReason: undefined,
noSurveyArea: undefined,
nonTransferReason: undefined
};
const data = reactive<PageData<NonTransferLedgerForm, NonTransferLedgerQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
projectId: currentProject.value?.id,
landType: undefined,
landBlockId: undefined,
enterRoadId: undefined,
designArea: undefined,
noContractArea: undefined,
noContractReason: undefined,
noSurveyArea: undefined,
nonTransferReason: undefined,
params: {}
},
rules: {
id: [{ required: true, message: '主键ID不能为空', trigger: 'blur' }],
projectId: [{ required: true, message: '项目ID不能为空', trigger: 'blur' }],
landType: [{ required: true, message: '土地类型不能为空', trigger: 'change' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询不流转台账列表 */
const getList = async () => {
loading.value = true;
const res = await listNonTransferLedger(queryParams.value);
nonTransferLedgerList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
nonTransferLedgerFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: NonTransferLedgerVO[]) => {
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?: NonTransferLedgerVO) => {
reset();
const _id = row?.id || ids.value[0];
const res = await getNonTransferLedger(_id);
Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = '修改不流转台账';
};
/** 提交按钮 */
const submitForm = () => {
nonTransferLedgerFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateNonTransferLedger(form.value).finally(() => (buttonLoading.value = false));
} else {
await addNonTransferLedger(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: NonTransferLedgerVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除不流转台账编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delNonTransferLedger(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 查询地块信息列表 */
const getListLand = async () => {
const res = await listLandBlock({
pageNum: 1,
pageSize: 10000,
projectId: currentProject.value?.id
});
landBlockList.value = res.rows;
};
/** 查询进场道路信息列表 */
const getListRoad = async () => {
const res = await listEnterRoad({ pageNum: 1, pageSize: 10000, projectId: currentProject.value?.id, landBlockId: form.value.landBlockId });
enterRoadList.value = res.rows;
};
// 选择地块
const handleLandBlockChange = (val) => {
console.log(val);
getListRoad();
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value?.id,
(nid, oid) => {
queryParams.value.projectId = nid;
getListLand();
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getListLand();
getList();
});
</script>

View File

@ -0,0 +1,370 @@
<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="110px">
<el-form-item label="对应地块" prop="landBlockId">
<el-select v-model="queryParams.landBlockId" clearable placeholder="请选择对应地块">
<el-option v-for="item in landBlockList" :key="item.id" :label="item.landName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="责任人" prop="responsiblePerson">
<el-input v-model="queryParams.responsiblePerson" 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">
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" :data="landTransferLedgerList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="土地类型" align="center" prop="landTypeName" />
<el-table-column label="地块" align="center" prop="landName" />
<el-table-column label="进场道路" align="center" prop="roadName" />
<el-table-column label="设计面积" align="center" prop="designArea" />
<el-table-column label="不签合同面积" align="center" prop="noContractArea" />
<el-table-column label="不签合同原因" align="center" prop="noContractReason" />
<el-table-column label="不测量面积" align="center" prop="noSurveyArea" />
<el-table-column label="不流转原因" align="center" prop="nonTransferReason" />
<el-table-column label="操作" align="center" fixed="right" width="200">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['land:landTransferLedger:query']">查看</el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" @click="handleDelete(scope.row)" v-hasPermi="['land:landTransferLedger: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 draggable title="查看信息" v-model="dialog.visible" width="900px" append-to-body>
<el-form disabled ref="landTransferLedgerFormRef" :model="form" :rules="rules" label-width="120px">
<el-row>
<el-col :span="12">
<el-form-item label="对应地块" prop="landBlockId">
<el-select v-model="form.landBlockId" clearable placeholder="请选择对应地块" @change="handleLandBlockChange">
<el-option v-for="item in landBlockList" :key="item.id" :label="item.landName" :value="item.id" />
</el-select> </el-form-item
></el-col>
<el-col :span="12">
<el-form-item label="进场道路" prop="enterRoadId">
<el-select v-model="form.enterRoadId" clearable placeholder="请选择对应地块">
<el-option v-for="item in enterRoadList" :key="item.id" :label="item.roadName" :value="item.id" />
</el-select> </el-form-item
></el-col>
<el-col :span="12">
<el-form-item label="土地类型" prop="landType">
<el-select v-model="form.landType" placeholder="请选择土地类型" clearable>
<el-option v-for="dict in land_type" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select></el-form-item
></el-col>
<el-col :span="12">
<el-form-item label="流转台账状态" prop="transferStatus">
<el-select v-model="form.transferStatus" :disabled="!form.id" placeholder="请选择流转台账状态" clearable>
<el-option
v-for="dict in land_transfer_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/> </el-select></el-form-item
></el-col>
<el-col :span="12">
<el-form-item label="设计面积(亩)" prop="designArea">
<el-input type="number" v-model="form.designArea" placeholder="请输入设计面积" /> </el-form-item
></el-col>
<el-col :span="12"
><el-form-item label="责任人" prop="responsiblePerson">
<el-input v-model="form.responsiblePerson" placeholder="请输入责任人" /> </el-form-item
></el-col>
<el-col :span="12"
><el-form-item label="预计完成日期" prop="expectedFinishDate">
<el-date-picker clearable v-model="form.expectedFinishDate" type="date" value-format="YYYY-MM-DD" placeholder="请选择预计完成时间">
</el-date-picker> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '1'" :span="12"
><el-form-item label="已流转面积(亩)" prop="transferAea">
<el-input v-model="form.transferAea" type="number" placeholder="请输入已流转面积" /> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '1'" :span="12"
><el-form-item label="流转比例(%)" prop="transferRatio">
<el-input v-model="form.transferRatio" type="number" placeholder="请输入流转比例" /> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '1'" :span="12">
<el-form-item label="土地租金(元)" prop="landRent">
<el-input type="number" v-model="form.landRent" placeholder="请输入土地租金" /> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '1'" :span="12">
<el-form-item label="青苗赔偿(元)" prop="seedlingCompensation">
<el-input v-model="form.seedlingCompensation" type="number" placeholder="请输入青苗赔偿" /> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '1'" :span="12">
<el-form-item label="总金额(元)" prop="totalAmount">
<el-input type="number" v-model="form.totalAmount" placeholder="请输入总金额" /> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '2'" :span="12"
><el-form-item label="不签合同面积(亩)" prop="noContractArea">
<el-input v-model="form.noContractArea" type="number" placeholder="请输入不签合同面积" /> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '2'" :span="12">
<el-form-item label="不测量面积(亩)" prop="noSurveyArea">
<el-input v-model="form.noSurveyArea" type="number" placeholder="请输入不测量面积" /> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '2'" :span="24"
><el-form-item label="不签合同原因" prop="noContractReason">
<el-input v-model="form.noContractReason" type="textarea" placeholder="请输入内容" /> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '2'" :span="24"
><el-form-item label="不流转原因" prop="nonTransferReason">
<el-input v-model="form.nonTransferReason" type="textarea" placeholder="请输入内容" /> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '1'" :span="24"
><el-form-item label="状态说明" prop="statusDescription">
<el-input v-model="form.statusDescription" type="textarea" placeholder="请输入内容" /> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '1'" :span="24"
><el-form-item label="问题总结" prop="issueSummary">
<el-input v-model="form.issueSummary" type="textarea" placeholder="请输入内容" /> </el-form-item
></el-col>
<el-col v-if="form.transferStatus == '1'" :span="24">
<el-form-item label="下一步策略" prop="nextStrategy">
<el-input v-model="form.nextStrategy" type="textarea" placeholder="请输入内容" /> </el-form-item
></el-col>
</el-row>
</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="LandTransferLedger" lang="ts">
import {
listLandTransferLedger,
getLandTransferLedger,
delLandTransferLedger,
addLandTransferLedger,
updateLandTransferLedger
} from '@/api/system/landTransfer/landTransferLedger';
import { listEnterRoad } from '@/api/system/landTransfer/enterRoad';
import { LandTransferLedgerVO, LandTransferLedgerQuery, LandTransferLedgerForm } from '@/api/system/landTransfer/landTransferLedger/types';
import { useUserStoreHook } from '@/store/modules/user';
import { listLandBlock } from '@/api/system/landTransfer/landBlock';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
// 获取用户 store
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目
const currentProject = computed(() => userStore.selectedProject);
const landTransferLedgerList = ref<LandTransferLedgerVO[]>([]);
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 landBlockList = ref([]);
const queryFormRef = ref<ElFormInstance>();
const landTransferLedgerFormRef = ref<ElFormInstance>();
const enterRoadList = ref([]);
const { land_type, land_transfer_status } = toRefs<any>(proxy?.useDict('land_type', 'land_transfer_status'));
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const initFormData = {
id: undefined,
projectId: currentProject.value?.id,
landType: undefined,
landBlockId: undefined,
enterRoadId: undefined,
designArea: undefined,
responsiblePerson: undefined,
expectedFinishDate: undefined,
transferAea: undefined,
transferRatio: undefined,
landRent: undefined,
seedlingCompensation: undefined,
totalAmount: undefined,
transferStatus: undefined,
statusDescription: undefined,
issueSummary: undefined,
nextStrategy: undefined,
noContractArea: undefined,
noContractReason: undefined,
noSurveyArea: undefined,
nonTransferReason: undefined
};
const data = reactive<PageData<LandTransferLedgerForm, LandTransferLedgerQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
projectId: currentProject.value?.id,
landType: undefined,
landBlockId: undefined,
enterRoadId: undefined,
designArea: undefined,
responsiblePerson: undefined,
expectedFinishDate: undefined,
transferAea: undefined,
transferRatio: undefined,
landRent: undefined,
seedlingCompensation: undefined,
totalAmount: undefined,
transferStatus: undefined,
statusDescription: undefined,
issueSummary: undefined,
nextStrategy: undefined,
params: {},
listType: 2
},
rules: {
id: [{ required: true, message: '主键ID不能为空', trigger: 'blur' }],
projectId: [{ required: true, message: '项目ID不能为空', trigger: 'blur' }],
landType: [{ required: true, message: '土地类型不能为空', trigger: 'change' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询项目土地流转台账列表 */
const getList = async () => {
loading.value = true;
const res = await listLandTransferLedger(queryParams.value);
landTransferLedgerList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
dialog.visible = false;
reset();
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
landTransferLedgerFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: LandTransferLedgerVO[]) => {
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
/** 新增按钮操作 */
const handleAdd = () => {
reset();
form.value.transferStatus = '0';
dialog.visible = true;
enterRoadList.value = [];
dialog.title = '添加项目土地流转台账';
};
/** 修改按钮操作 */
const handleUpdate = async (row?: LandTransferLedgerVO) => {
reset();
form.value.landBlockId = row?.landBlockId;
getListRoad();
const _id = row?.id || ids.value[0];
const res = await getLandTransferLedger(_id);
Object.assign(form.value, res.data);
console.log(form.value);
dialog.visible = true;
dialog.title = '修改项目土地流转台账';
};
/** 提交按钮 */
const submitForm = () => {
landTransferLedgerFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateLandTransferLedger(form.value).finally(() => (buttonLoading.value = false));
} else {
await addLandTransferLedger(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: LandTransferLedgerVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除项目土地流转台账编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delLandTransferLedger(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
// 选择地块
const handleLandBlockChange = (val) => {
getListRoad();
};
/** 查询地块信息列表 */
const getListLand = async () => {
const res = await listLandBlock({
pageNum: 1,
pageSize: 10000,
projectId: currentProject.value?.id
});
landBlockList.value = res.rows;
};
/** 查询进场道路信息列表 */
const getListRoad = async () => {
const res = await listEnterRoad({ pageNum: 1, pageSize: 10000, projectId: currentProject.value?.id, landBlockId: form.value.landBlockId });
enterRoadList.value = res.rows;
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value?.id,
(nid, oid) => {
queryParams.value.projectId = nid;
getListLand();
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
getListLand();
});
</script>

View File

@ -0,0 +1,441 @@
<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(() => proxy?.$cache.local.getJSON('ProjectTeamList') || []);
const initFormData: LeaveForm = {
id: undefined,
userId: undefined,
userName: undefined,
userExplain: undefined,
userTime: undefined,
leaveType: undefined,
startTime: undefined,
endTime: undefined,
gangerId: undefined,
gangerName: undefined,
gangerOpinion: undefined,
gangerExplain: undefined,
gangerTime: undefined,
managerOpinion: undefined,
managerExplain: undefined,
managerTime: undefined,
projectId: undefined,
teamId: undefined,
remark: undefined
};
const data = reactive<PageData<LeaveForm, LeaveQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
userName: undefined,
leaveType: undefined,
gangerOpinion: undefined,
managerOpinion: undefined,
projectId: undefined,
teamId: undefined,
params: {}
},
rules: {
id: [{ required: true, message: '主键id不能为空', trigger: 'blur' }],
userId: [{ required: true, message: '申请人id不能为空', trigger: 'blur' }],
userName: [{ required: true, message: '申请人名字不能为空', trigger: 'blur' }],
leaveType: [{ required: true, message: '请假类型不能为空', trigger: 'change' }],
startTime: [{ required: true, message: '请假开始时间不能为空', trigger: 'blur' }],
endTime: [{ required: true, message: '请假结束时间不能为空', trigger: 'blur' }],
gangerOpinion: [{ required: true, message: '班组长意见不能为空', trigger: 'change' }],
managerOpinion: [{ required: true, message: '管理员意见不能为空', trigger: 'change' }],
projectId: [{ required: true, message: '项目id不能为空', trigger: 'blur' }]
}
});
const auditForm = reactive<AuditReissueCardForm>({
id: undefined,
managerOpinion: '2',
managerExplain: undefined
});
const { queryParams, form, rules } = toRefs(data);
//审核进度
const auditProgress = computed(() => {
if (auditStatus.value) return 3;
if (managerStatus.value) return 2;
if (teamStatus.value) return 1;
return 0;
});
//审核状态
const auditStatus = computed(() => {
if (detailObj.value.status == '3' || detailObj.value.status == '4') return true;
return false;
});
//管理员审核状态
const managerStatus = computed(() => {
switch (detailObj.value.managerOpinion) {
case '1':
return false;
case '2':
return 'success';
case '3':
return 'error';
}
});
//班组审核状态
const teamStatus = computed(() => {
switch (detailObj.value.gangerOpinion) {
case '1':
return false;
case '2':
return 'success';
case '3':
return 'error';
}
});
//结果状态
const resultsStatus = computed(() => {
if (detailObj.value.status == '3') return 'success';
if (detailObj.value.status == '4') return 'error';
return '';
});
/** 查询施工人员请假申请列表 */
const getList = async () => {
loading.value = true;
const res = await listLeave(queryParams.value);
leaveList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 提交按钮 */
const submitForm = async () => {
await AuditReissueCard(auditForm);
proxy?.$modal.msgSuccess('审批成功');
dialog.visible = false;
await getList();
};
const handleDetail = (row: ReissueCardVO) => {
detailObj.value = row;
console.log('🚀 ~ handleDetail ~ row:', row);
dialog.details = true;
};
/** 审批按钮操作 */
const handleUpdate = async (row?: LeaveVO) => {
reset();
const _id = row?.id || ids.value[0];
auditForm.id = _id;
dialog.visible = true;
dialog.title = '修改施工人员补卡申请';
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'project/leave/export',
{
...queryParams.value
},
`leave_${new Date().getTime()}.xlsx`
);
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value?.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
});
</script>
<style lang="scss" scoped>
.block_box {
border: 1px solid #9eccfa;
border-radius: 6px;
padding: 10px 20px 20px 10px;
margin: 15px;
> span {
color: #409eff;
font-weight: 700;
font-size: 14px;
}
}
</style>

View File

@ -0,0 +1,727 @@
<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="expand" width="50">
<template #default="{ row }">
<div class="w212.25 ml-12.5">
<el-button class="mb" type="primary" size="small" @click="handleOpenSetChild(row.id)" icon="plus">添加子项目</el-button>
<el-table :data="row.children" border stripe>
<el-table-column label="序号" type="index" width="55" align="center" />
<el-table-column label="名称" align="center" prop="projectName" width="296">
<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.projectName }}</el-link
>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="199" />
<el-table-column fixed="right" align="center" label="操作" class-name="small-padding fixed-width" width="299">
<template #default="scope">
<el-space>
<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="handleOpenSetChild(row.id, scope.row.id, scope.row.projectName)"
v-hasPermi="['project:project:edit']"
>修改
</el-button>
<el-button link type="danger" icon="Delete" @click="handleChildDel(scope.row.id)" v-hasPermi="['project:project:remove']"
>删除
</el-button>
</el-space>
</template>
</el-table-column>
</el-table>
</div>
</template>
</el-table-column>
<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">
<!-- <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.projectName }}</el-link
>
</template> -->
</el-table-column>
<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>
<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="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>
<el-dialog title="添加子项目" v-model="childProjectStatus" width="400">
<span>填写子项目名称</span>
<el-input v-model="childProjectForm.projectName"></el-input>
<template #footer>
<span>
<el-button @click="childProjectStatus = false">取消</el-button>
<el-button type="primary" @click="handleSetChild">确定</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup name="Project" lang="ts">
import {
addChildProject,
addProject,
addProjectFacilities,
addProjectPilePoint,
addProjectSquare,
delProject,
getChildProject,
getProject,
listProject,
updateProject
} from '@/api/project/project';
import { ProjectForm, ProjectQuery, ProjectVO, childProjectQuery, 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 childProjectStatus = ref(false);
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 childProjectForm = reactive<childProjectQuery>({
projectName: '',
pid: '',
id: ''
});
//被选中的节点
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 handleChildDel = async (id) => {
await proxy?.$modal.confirm('是否确认删除项目编号为"' + id + '"的数据项?').finally(() => (loading.value = false));
await delProject(id);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
//增加/修改子项目
const handleOpenSetChild = async (pid, id?, name?) => {
childProjectStatus.value = true;
childProjectForm.id = id;
childProjectForm.pid = pid;
childProjectForm.projectName = name;
};
const resetChildQuert = () => {
childProjectForm.id = '';
childProjectForm.pid = '';
childProjectForm.projectName = '';
};
//增加/修改子项目
const handleSetChild = async () => {
if (!childProjectForm.projectName.trim()) return proxy.$modal.msgError('请填写项目名称');
if (childProjectForm.id) {
let res = await updateProject({ id: childProjectForm.id, projectName: childProjectForm.projectName });
if (res.code == 200) {
proxy.$modal.msgSuccess('修改成功');
childProjectStatus.value = false;
resetChildQuert();
getList();
}
} else {
let res = await addChildProject(childProjectForm);
if (res.code == 200) {
proxy.$modal.msgSuccess('添加成功');
childProjectStatus.value = false;
resetChildQuert();
getList();
}
}
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'project/project/export',
{
...queryParams.value
},
`project_${new Date().getTime()}.xlsx`
);
};
onMounted(() => {
getList();
});
</script>
<style scoped>
.block-box {
border: 1px solid #9eccfa;
border-radius: 6px;
padding: 10px 20px 0 10px;
margin-bottom: 20px;
}
.block-box > div {
color: #409eff;
font-weight: 700;
font-size: 14px;
margin-bottom: 10px;
}
</style>

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,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 'element-plus';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { type_of_work, user_sex_type, user_clock_type } = toRefs<any>(proxy?.useDict('type_of_work', 'user_sex_type', 'user_clock_type'));
interface Props {
userId?: string | number;
}
const props = defineProps<Props>();
const loading = ref<boolean>(false);
const userDetail = ref<ConstructionUserVO>();
const getUserDetail = async () => {
loading.value = true;
const res = await getConstructionUser(props.userId);
if (res.data && res.code === 200) {
userDetail.value = res.data;
}
loading.value = false;
};
onMounted(() => {
getUserDetail();
});
watch(
() => props.userId,
(newId, oldId) => {
if (newId !== oldId) {
getUserDetail();
}
}
);
</script>
<style lang="scss" scoped>
.block_box {
border: 1px solid #9eccfa;
border-radius: 6px;
padding: 10px 20px 20px 10px;
margin: 15px;
> span {
color: #409eff;
font-weight: 700;
font-size: 14px;
}
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,396 @@
<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(() => proxy?.$cache.local.getJSON('ProjectTeamList') || []);
const initFormData: ReissueCardForm = {
id: undefined,
userId: undefined,
userExplain: undefined,
gangerId: undefined,
gangerOpinion: undefined,
gangerExplain: undefined,
managerOpinion: undefined,
managerExplain: undefined,
projectId: currentProject.value?.id,
attendanceId: undefined,
remark: undefined
};
const data = reactive<PageData<ReissueCardForm, ReissueCardQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
userName: undefined,
gangerOpinion: undefined,
managerOpinion: undefined,
projectId: currentProject.value?.id,
teamId: undefined,
reissueCardType: undefined,
params: {}
},
rules: {
id: [{ required: true, message: '主键id不能为空', trigger: 'blur' }],
userId: [{ required: true, message: '申请人id不能为空', trigger: 'blur' }],
gangerId: [{ required: true, message: '班组长不能为空', trigger: 'blur' }],
gangerOpinion: [{ required: true, message: '班组长意见不能为空', trigger: 'blur' }],
managerOpinion: [{ required: true, message: '管理员意见不能为空', trigger: 'blur' }],
projectId: [{ required: true, message: '项目id不能为空', trigger: 'blur' }],
attendanceId: [{ required: true, message: '考勤表主键id不能为空', trigger: 'blur' }]
}
});
const { queryParams, form, rules } = toRefs(data);
//审核进度
const auditProgress = computed(() => {
if (auditStatus.value) return 3;
if (managerStatus.value) return 2;
if (teamStatus.value) return 1;
return 0;
});
//审核状态
const auditStatus = computed(() => {
if (detailObj.value.status == '3' || detailObj.value.status == '4') return true;
return false;
});
//管理员审核状态
const managerStatus = computed(() => {
switch (detailObj.value.managerOpinion) {
case '1':
return false;
case '2':
return 'success';
case '3':
return 'error';
}
});
//班组审核状态
const teamStatus = computed(() => {
switch (detailObj.value.gangerOpinion) {
case '1':
return false;
case '2':
return 'success';
case '3':
return 'error';
}
});
//结果状态
const resultsStatus = computed(() => {
if (detailObj.value.status == '3') return 'success';
if (detailObj.value.status == '4') return 'error';
return '';
});
/** 查询施工人员补卡申请列表 */
async function getList() {
loading.value = true;
const res = await listReissueCard(queryParams.value);
reissueCardList.value = res.rows;
total.value = res.total;
loading.value = false;
}
/** 表单重置 */
const reset = () => {
auditForm.managerExplain = '';
auditForm.managerOpinion = '2';
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 新增按钮操作 */
const handleAdd = () => {
reset();
dialog.visible = true;
dialog.title = '添加施工人员补卡申请';
};
/** 审批按钮操作 */
const handleUpdate = async (row?: ReissueCardVO) => {
reset();
const _id = row?.id || ids.value[0];
auditForm.id = _id;
dialog.visible = true;
dialog.title = '修改施工人员补卡申请';
};
const handleDetail = (row: ReissueCardVO) => {
detailObj.value = row;
dialog.details = true;
};
/** 审批操作 */
const submitAudit = async () => {
await AuditReissueCard(auditForm);
proxy?.$modal.msgSuccess('审批成功');
dialog.visible = false;
auditForm.managerExplain = '';
auditForm.managerOpinion = '2';
await getList();
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value?.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
});
</script>
<style lang="scss" scoped>
.block_box {
border: 1px solid #9eccfa;
border-radius: 6px;
padding: 10px 20px 20px 10px;
margin: 15px;
> span {
color: #409eff;
font-weight: 700;
font-size: 14px;
}
}
</style>

View File

@ -0,0 +1,190 @@
<template>
<div class="system-busSalaryDetails-container">
<el-card shadow="hover">
<div class="info_s">
<div>
<el-button type="success" @click="DownloadSalaryMOdel"
><el-icon><Download /></el-icon>下载模版</el-button
>
<el-button type="primary" @click="uploadSalary"
><el-icon><Upload /></el-icon>上传工资表</el-button
>
<el-button type="danger" :disabled="!(ids.length > 0)" @click="delSalary"
><el-icon><Delete /></el-icon>删除</el-button
>
</div>
<el-popover placement="top-start" title="" :width="200" trigger="hover" :content="DetailMoney + '元'">
<template #reference>
<el-tag class="m-2" size="large"
><span style="font-size: 20px; cursor: pointer">金额:{{ totalMoney }}</span></el-tag
>
</template>
</el-popover>
</div>
<el-table v-loading="loading" @selection-change="handleSelectionChange" size="large" border :data="tableData.data" height="76vh">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" align="center" type="index" min-width="50px" />
<el-table-column label="标题" align="center" prop="title" min-width="120px" />
<el-table-column label="金额" align="center" prop="money" min-width="100px" />
<el-table-column label="操作" align="center" class-name="small-padding" min-width="200px" fixed="right">
<template #default="scope">
<el-button type="primary" link @click="handleView(scope.row)"
><el-icon><View /></el-icon>详情</el-button
>
<el-button type="success" link @click="bookSalary(scope.row)"
><el-icon><View /></el-icon>查看工资表</el-button
>
<el-button type="primary" link @click="DownloadSalary(scope.row)"
><el-icon><Download /></el-icon>下载工资表</el-button
>
</template>
</el-table-column>
</el-table>
</el-card>
<!-- <uploadSalary ref="uploadSalaryRef" @busSalaryDetailsList="busSalaryDetailsList"></uploadSalary>
<detail ref="detailRef" @busSalaryDetailsList="busSalaryDetailsList"></detail>
<documentDetail ref="documentDetailRef" v-if="showDocumentDetail" @onClose="showDocumentDetail = false"></documentDetail> -->
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, getCurrentInstance, nextTick, toRaw } from 'vue';
// import uploadSalary from '/@/views/system/salaryExcel/component/uploadSalary.vue';
// import detail from '/@/views/system/salaryExcel/component/detail.vue';
// import { readAllImportedListData, getTheSourceExcelAccordingToTheIdOfThePayroll, deletePayroll } from '/@/api/system/salaryExcel';
// import documentDetail from '/@/views/OnlineEngineering/comm/documentsDetail/index.vue';
import { ElMessageBox, ElMessage } from 'element-plus';
import { useUserStoreHook } from '@/store/modules/user';
const stores = useUserStoreHook();
const { proxy } = <any>getCurrentInstance();
const loading = ref(false);
const uploadSalaryRef = ref();
const editRef = ref();
const documentDetailRef = ref();
const detailRef = ref();
const showAll = ref(false);
const single = ref(true);
const multiple = ref(true);
const showDocumentDetail = ref(false);
const tableData = reactive({
data: [],
total: 0
});
const totalMoney = ref(0);
const DetailMoney = ref(0);
const ids = ref<any[]>([]);
const uploadSalary = () => {
uploadSalaryRef.value.openDialog();
};
const initTableData = () => {
busSalaryDetailsList();
};
const busSalaryDetailsList = () => {
loading.value = true;
readAllImportedListData().then((res: any) => {
let list = res.data.list ?? [];
let moneySum = 0;
list.forEach((item) => {
moneySum += parseInt(item.money);
});
DetailMoney.value = moneySum;
totalMoney.value = moneySum >= 10000 ? (moneySum / 10000).toFixed(2) + '万' : moneySum;
tableData.data = list;
loading.value = false;
});
};
const handleView = (row: any) => {
detailRef.value.openDialog(toRaw(row));
};
const bookSalary = (row: any) => {
getTheSourceExcelAccordingToTheIdOfThePayroll({ id: row.id }).then((res: any) => {
if (res.code == 0) {
showDocumentDetail.value = true;
let obj = {
suffix: '.' + res.data.Suffix,
name: res.data.Name,
filenPathCoding: res.data.Path,
id: row.id
};
nextTick(() => {
documentDetailRef.value.openDialog(obj);
});
}
});
};
const DownloadSalary = (row: any) => {
getTheSourceExcelAccordingToTheIdOfThePayroll({ id: row.id }).then((res: any) => {
if (res.code == 0) {
window.open(res.data.Path, '_blank');
}
});
};
const DownloadSalaryMOdel = () => {
window.open('http://zmkg.cqet.top:8899/file/masterMask/coryStorageTemplate/工资表模板.xlsx', '_blank');
};
const delSalary = () => {
ElMessageBox.confirm('是否删除选中数据', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
deletePayroll({ ids: ids.value }).then(() => {
ElMessage.success('删除成功');
busSalaryDetailsList();
});
})
.catch(() => {});
};
const handleSelectionChange = (selection: any[]) => {
ids.value = selection.map((item) => item.id);
};
onMounted(() => {
// initTableData();
});
</script>
<style lang="scss" scoped>
.colBlock {
display: block;
}
.colNone {
display: none;
}
.system-busSalaryDetails-container {
.el-tag__content {
font-size: 20px !important;
font-weight: 600;
}
.info_s {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
}
input[type='file'] {
display: none;
}
label {
display: inline-block;
background-color: #007bff; /*设置背景色*/
color: #fff; /*设置字体颜色*/
padding: 3px 10px; /*设置内边距*/
border-radius: 5px; /*设置圆角*/
cursor: pointer; /*将鼠标光标设置为手型*/
font-size: 13px;
}
}
</style>

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,306 @@
<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="contractorId">
<el-select v-model="queryParams.contractorId" filterable placeholder="请选择分包方">
<el-option v-for="(item, i) of contractorList" :key="i" :label="item.name" :value="item.id"> </el-option>
</el-select>
</el-form-item>
<el-form-item label="合同编号" prop="contractNumber">
<el-input v-model="queryParams.contractNumber" placeholder="请输入合同编号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="合同名称" prop="contractName">
<el-input v-model="queryParams.contractName" placeholder="请输入合同名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="合同类型" prop="contractType">
<el-select v-model="queryParams.contractType" placeholder="请选择合同类型" clearable>
<el-option v-for="dict in subcontract_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="['contractor:subcontract:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['contractor:subcontract:edit']"
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['contractor:subcontract:remove']"
>删除</el-button
>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" :data="subcontractList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="分包方" align="center" prop="contractorName" />
<el-table-column label="合同编号" align="center" prop="contractNumber" />
<el-table-column label="合同名称" align="center" prop="contractName" />
<el-table-column label="合同类型" align="center" prop="contractType">
<template #default="scope">
<dict-tag :options="subcontract_type" :value="scope.row.contractType" />
</template>
</el-table-column>
<el-table-column label="合同金额" align="center" prop="contractAmount" />
<el-table-column label="合同时间" align="center" prop="contractTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.contractTime, '{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-tooltip content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['contractor:subcontract:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button
link
type="primary"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['contractor:subcontract: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 draggable :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="subcontractFormRef" :model="form" :rules="rules" label-width="110px">
<el-form-item label="分包方" prop="contractorId">
<el-select v-model="form.contractorId" filterable placeholder="请选择分包方">
<el-option v-for="(item, i) of contractorList" :key="i" :label="item.name" :value="item.id"> </el-option>
</el-select>
</el-form-item>
<el-form-item label="合同文件" prop="contractFileId">
<file-upload :fileType="['doc', 'xls', 'ppt', 'txt', 'pdf', 'png', 'jpg', 'jpeg']" v-model="form.contractFileId" />
</el-form-item>
<el-form-item label="合同名称" prop="contractName">
<el-input v-model="form.contractName" placeholder="请输入合同名称" />
</el-form-item>
<el-form-item label="合同编号" prop="contractNumber">
<el-input v-model="form.contractNumber" placeholder="请输入合同编号" />
</el-form-item>
<el-form-item label="合同类型" prop="contractType">
<el-select v-model="form.contractType" placeholder="请选择合同类型">
<el-option v-for="dict in subcontract_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="合同金额(元)" prop="contractAmount">
<el-input v-model="form.contractAmount" type="number" placeholder="请输入合同金额" />
</el-form-item>
<el-form-item label="合同日期" prop="contractTime">
<el-date-picker clearable v-model="form.contractTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择合同日期"> </el-date-picker>
</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="Subcontract" lang="ts">
import { listSubcontract, getSubcontract, delSubcontract, addSubcontract, updateSubcontract } from '@/api/project/subcontract';
import { SubcontractVO, SubcontractQuery, SubcontractForm } from '@/api/project/subcontract/types';
import { listContractor } from '@/api/project/contractor';
import { useUserStoreHook } from '@/store/modules/user';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
// 获取用户 store
const userStore = useUserStoreHook();
const currentProject = computed(() => userStore.selectedProject);
const { subcontract_type } = toRefs<any>(proxy?.useDict('subcontract_type'));
const subcontractList = ref<SubcontractVO[]>([]);
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 contractorList = ref([]); //分包列表
const queryFormRef = ref<ElFormInstance>();
const subcontractFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const initFormData: SubcontractForm = {
id: undefined,
projectId: currentProject.value?.id,
contractorId: undefined,
contractFileId: undefined,
contractNumber: undefined,
contractName: undefined,
contractType: undefined,
contractAmount: undefined,
contractTime: undefined,
remark: undefined
};
const data = reactive<PageData<SubcontractForm, SubcontractQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
projectId: currentProject.value?.id,
contractorId: undefined,
contractNumber: undefined,
contractName: undefined,
contractType: undefined,
params: {}
},
rules: {
contractorId: [{ required: true, message: '分包方不能为空', trigger: 'blur' }],
contractFileId: [{ required: true, message: '合同文件不能为空', trigger: 'blur' }],
contractType: [{ required: true, message: '合同类型不能为空', trigger: 'change' }],
contractNumber: [{ required: true, message: '合同编号不能为空', trigger: 'change' }],
contractName: [{ required: true, message: '合同名称不能为空', trigger: 'change' }],
contractAmount: [{ required: true, message: '合同金额不能为空', trigger: 'change' }],
contractTime: [{ required: true, message: '合同时间不能为空', trigger: 'change' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询分包合同列表 */
const getList = async () => {
loading.value = true;
const res = await listSubcontract(queryParams.value);
subcontractList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 查询分包单位列表 */
const getSubList = async () => {
const res = await listContractor({
pageNum: 1,
pageSize: 10000,
projectId: currentProject.value?.id
});
contractorList.value = res.rows;
handleQuery();
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
subcontractFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
if (contractorList.value.length == 1) queryParams.value.contractorId = contractorList.value[0].id;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: SubcontractVO[]) => {
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?: SubcontractVO) => {
reset();
const _id = row?.id || ids.value[0];
const res = await getSubcontract(_id);
Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = '修改分包合同';
};
/** 提交按钮 */
const submitForm = () => {
subcontractFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateSubcontract(form.value).finally(() => (buttonLoading.value = false));
} else {
await addSubcontract(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: SubcontractVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除分包合同编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delSubcontract(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value?.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getSubList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getSubList();
});
</script>

View File

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

View File

@ -0,0 +1,248 @@
<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(() => proxy?.$cache.local.getJSON('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>