整体细节处理

This commit is contained in:
Teo
2025-04-10 18:34:00 +08:00
parent 2643f4abc8
commit 1f6734db48
23 changed files with 458 additions and 255 deletions

View File

@ -1,4 +1,3 @@
import * as echarts from 'echarts';
const grid = {
left: 100,
right: 100,
@ -14,17 +13,17 @@ const titleList = [
{ name: '请假人数', color: '#000' }
];
export const echartsConfig = (ref: any, list?: any) => {
const commandstatsIntance = echarts.init(ref, 'macarons');
// export const echartsConfig = (ref: any, list?: any) => {
// const commandstatsIntance = echarts.init(ref, 'macarons');
// };
export const option = (list?: any) => {
const attendanceArray = list.map((item) => item.attendance);
const halfAttendanceArray = list.map((item) => item.halfAttendance);
const absenteeismArray = list.map((item) => item.absenteeism);
const leaveArray = list.map((item) => item.leave);
const rawData = [attendanceArray, halfAttendanceArray, absenteeismArray, leaveArray];
//y轴数据
const data = list.map((item) => item.clockDate);
const series: any = titleList.map((item, sid) => {
return {
name: item.name,
@ -42,7 +41,8 @@ export const echartsConfig = (ref: any, list?: any) => {
data: rawData[sid]
};
});
commandstatsIntance.setOption({
const data = list.map((item) => item.clockDate);
const option = {
legend: {
selectedMode: false,
right: 0
@ -58,5 +58,6 @@ export const echartsConfig = (ref: any, list?: any) => {
},
series,
color
});
};
return option;
};

View File

@ -107,7 +107,7 @@ export interface AttendanceForm extends BaseEntity {
userId?: string | number;
typeOfWork?: string;
teamId?: string;
clockMonth?: string;
clockDate?: string;
/**
* 人脸照
@ -187,7 +187,6 @@ export interface AttendanceQuery extends PageQuery {
projectId?: string | number;
typeOfWork?: string | number;
teamId?: string | number;
clockMonth?: string | number;
/**
* 打卡日期

View File

@ -113,6 +113,7 @@ export interface ProjectVO {
* 创建时间
*/
createTime: string;
type?: string;
}
export interface locationType {

View File

@ -35,7 +35,7 @@ export interface ProjectTeamForm extends BaseEntity {
* 主键id
*/
id?: string | number;
peopleNumber?: string | number;
/**
* 项目id
*/
@ -62,7 +62,7 @@ export interface ProjectTeamQuery extends PageQuery {
* 项目id
*/
projectId?: string | number;
peopleNumber?: string | number;
/**
* 班组名称
*/

View File

@ -3,6 +3,8 @@ export interface WorkerDailyReportVO {
* 申请人名字
*/
userName: string;
userId?: string;
id?: string;
/**
* 今日完成工作
@ -23,7 +25,6 @@ export interface WorkerDailyReportVO {
* 需协调与帮助
*/
coordinationHelp: string;
}
export interface WorkerDailyReportForm extends BaseEntity {
@ -36,6 +37,10 @@ export interface WorkerDailyReportForm extends BaseEntity {
* 项目id
*/
projectId?: string | number;
teamName?: string;
resubmitReason?: string;
reportDate?: string;
isResubmit: string;
/**
* 班组id
@ -75,12 +80,30 @@ export interface WorkerDailyReportForm extends BaseEntity {
/**
* 附件
*/
file?: string;
fileList?: Array<string>;
dailyPieceItemVoList?: dailyPieceItemVO[];
}
interface dailyPieceItemVO {
/**
* 主键id
*/
id?: string | number;
/**
* 计件类型
*/
pieceType?: string;
/**
* 数量
*/
pieceCount?: number;
pieceUnit?: string;
remark?: string;
}
export interface WorkerDailyReportQuery extends PageQuery {
/**
* 项目id
*/
@ -101,11 +124,9 @@ export interface WorkerDailyReportQuery extends PageQuery {
*/
userName?: string;
/**
* 日期范围参数
*/
params?: any;
/**
* 日期范围参数
*/
params?: any;
isResubmit?: string;
}

View File

@ -14,6 +14,8 @@
:headers="headers"
class="upload-file-uploader"
:list-type="isConstruction ? 'picture-card' : 'text'"
:accept="accept"
:drag="isDarg"
>
<!-- 上传按钮 -->
<el-button v-if="!isConstruction && !isImportInfo" type="primary">选取文件</el-button>
@ -89,7 +91,9 @@ const props = defineProps({
//是否为导入资料
isImportInfo: propTypes.bool.def(false),
//ip地址
uploadUrl: propTypes.string.def('/resource/oss/upload')
uploadUrl: propTypes.string.def('/resource/oss/upload'),
//可拖拽上传
isDarg: propTypes.bool.def(false)
});
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@ -106,6 +110,11 @@ const showTip = computed(() => props.isShowTip && (props.fileType || props.fileS
const fileUploadRef = ref<ElUploadInstance>();
const accept = computed(() => {
console.log('🚀 ~ accept ~ props.fileType:', props.fileType.map((value) => `.${value}`).join(','));
return props.fileType.map((value) => `.${value}`).join(',');
});
watch(
() => props.modelValue,
async (val) => {

View File

@ -41,8 +41,6 @@ const handleSelect = (projectId: string) => {
const selectedProject = projects.value.find((p) => p.id === projectId);
if (selectedProject) {
userStore.setSelectedProject(selectedProject);
// getProjectTeam();
location.reload();
}
};
</script>

View File

@ -1,10 +1,10 @@
<template>
<el-menu :default-active="activeMenu" mode="horizontal" :ellipsis="false" @select="handleSelect">
<template v-for="(item, index) in topMenus">
<el-menu-item v-if="index < visibleNumber" :key="index" :style="{ '--theme': theme }" :index="item.path"
><svg-icon v-if="item.meta && item.meta.icon && item.meta.icon !== '#'" :icon-class="item.meta ? item.meta.icon : ''" />
{{ item.meta?.title }}</el-menu-item
>
<el-menu-item v-if="index < visibleNumber" :key="index" :style="{ '--theme': theme }" :index="item.path">
<svg-icon v-if="item.meta && item.meta.icon && item.meta.icon !== '#'" :icon-class="item.meta ? item.meta.icon : ''" />
{{ item.meta?.title }}
</el-menu-item>
</template>
<!-- 顶部菜单超出数量折叠 -->

View File

@ -55,6 +55,10 @@ const theme = computed(() => useSettingsStore().theme);
watch(route, () => {
addTags();
moveToCurrentTag();
//记录超过五个就删除第二个
if (visitedViews.value?.length > 6) {
closeSelectedTag(visitedViews.value[1]);
}
});
watch(visible, (value) => {
if (value) {

View File

@ -82,7 +82,7 @@ declare global {
declare interface PageData<T, D> {
form: T;
queryParams: D;
rules: ElFormRules;
rules?: ElFormRules;
memberRules?: ElFormRules;
}

View File

@ -17,8 +17,8 @@
<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="clockMonth">
<el-date-picker clearable v-model="queryParams.clockMonth" type="month" value-format="YYYY-MM" placeholder="请选择打卡日期" />
<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>
@ -149,15 +149,10 @@
</el-dialog> -->
<!-- 考勤详情对话框 -->
<el-dialog v-model="dialog.details" width="1300px">
<el-calendar ref="calendar" class="h170 pos-relative">
<el-calendar ref="calendar" v-model="calendarDay" class="h170 pos-relative">
<template #header="{ date }">
<span>
<el-button-group>
<el-button type="primary" size="small" icon="ArrowLeft" @click="selectDate('prev-month', date)">上一月</el-button>
<el-button type="primary" size="small" @click="selectDate('next-month', date)">
下一月<el-icon class="el-icon--right"><ArrowRight /></el-icon>
</el-button>
</el-button-group>
<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">
@ -167,7 +162,7 @@
</div>
</template>
<template #date-cell="{ data }">
<div class="flex-c">
<div class="flex-c" @click="handleViewPlayCard(data)">
<p class="time">{{ day(data) }}</p>
<img v-if="!isplayCard(data)" src="http://zmkg.cqet.top:8899/assets/empty-CZvxqguX.png" /><span v-if="!isplayCard(data)"
>暂无打卡记录</span
@ -197,11 +192,13 @@ import {
listAttendanceTwoWeek,
listAttendanceMonth
} from '@/api/project/attendance';
import { echartsConfig } from '@/api/project/attendance/echarts';
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'));
@ -220,15 +217,18 @@ 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,
@ -246,8 +246,7 @@ const initFormData: AttendanceForm = {
lat: undefined,
remark: undefined,
typeOfWork: undefined,
teamId: undefined,
clockMonth: undefined
teamId: undefined
};
const data = reactive<PageData<AttendanceForm, AttendanceQuery>>({
form: { ...initFormData },
@ -261,7 +260,6 @@ const data = reactive<PageData<AttendanceForm, AttendanceQuery>>({
projectId: currentProject.value.id,
typeOfWork: undefined,
teamId: undefined,
clockMonth: undefined,
params: {}
},
rules: {
@ -303,14 +301,30 @@ const attendanceStatus = computed(() => (date) => {
const { queryParams, form, rules } = toRefs(data);
const calendar = ref<CalendarInstance>();
const selectDate = async (val: CalendarDateType, date) => {
if (!calendar.value) return;
calendar.value.selectDate(val);
const clockMonth = incrementMonth(date, val == 'prev-month' ? -1 : 1);
const handleMonth = async (e: any) => {
calendarDay.value = e;
handleCalendarMonth(e);
};
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;
@ -323,9 +337,10 @@ const getList = async () => {
/** 查询近两周考勤列表 */
const getListTwoWeek = async () => {
loading.value = true;
const res = await listAttendanceTwoWeek({ projectId: currentProject.value.id });
const res = await listAttendanceTwoWeek(queryParams.value);
attendanceTwoWeekList.value = res.data;
echartsConfig(commandstats.value, attendanceTwoWeekList.value);
echartsOption.value = { ...option(attendanceTwoWeekList.value) };
commandstatsIntance.value.setOption(echartsOption.value);
};
/** 取消按钮 */
@ -344,6 +359,7 @@ const reset = () => {
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
getListTwoWeek();
};
/** 重置按钮操作 */
@ -352,19 +368,6 @@ const resetQuery = () => {
handleQuery();
};
/** 多选框选中数据 */
// const handleSelectionChange = (selection: AttendanceVO[]) => {
// 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 incrementMonth = (dateStr: string, monthsToAdd: number) => {
const [yearPart, monthPart] = dateStr.replace(/\s/g, '').split('年');
@ -429,10 +432,34 @@ const submitForm = () => {
// `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>

View File

@ -160,6 +160,20 @@ const resetQuery = () => {
handleQuery();
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
});

View File

@ -157,6 +157,20 @@ const handleDelete = async (row?: ConstructionBlacklistVO) => {
await getList();
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
});

View File

@ -85,7 +85,6 @@
<el-button type="primary" plain icon="Edit" @click="downloadTemplate">下载资料模板 </el-button>
</el-col>
<el-col :span="1.5" v-show="informationStatus">
<!-- <el-button type="warning" plain icon="Edit" @click="importInformation">导入员工资料 </el-button> -->
<file-upload
v-model="filePath"
isImportInfo
@ -104,7 +103,11 @@
<el-table v-loading="loading" :data="constructionUserList" @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="userName">
<template #default="scope">
<el-link type="primary" @click="handleUpdate(scope.row)">{{ scope.row.userName }}</el-link>
</template>
</el-table-column>
<el-table-column label="分包公司" align="center" prop="contractorVo.name" />
<el-table-column label="班组" align="center" prop="teamId">
<template #default="scope">
@ -170,7 +173,7 @@
<el-button link type="danger" icon="Avatar" @click="handleJoinBlacklist(scope.row)" v-hasPermi="['project:constructionBlacklist:add']">
黑名单
</el-button>
<el-button link type="primary" icon="Switch" @click="handleToggle(scope.row)"> 切换人脸 </el-button>
<!-- <el-button link type="primary" icon="Switch" @click="handleToggle(scope.row)"> 切换人脸 </el-button> -->
<el-button link type="primary" icon="Switch" @click="handleChange(scope.row)"> 人员迁移 </el-button>
<el-button link type="primary" icon="ChatLineSquare" @click="handleExit(scope.row)"> 入退场记录 </el-button>
<el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['project:constructionUser:remove']">
@ -332,7 +335,7 @@
</div>
</template>
</el-dialog>
<el-dialog title="施工人员详情" v-model="showDetailDrawer">
<el-dialog title="施工人员详情" v-model="showDetailDrawer" width="800px">
<construction-user-detail :user-id="currentUserId" />
</el-dialog>
<el-dialog :title="skipName + '-人员迁移'" v-model="skip" width="500px">
@ -434,13 +437,19 @@
<el-calendar ref="calendar" v-model="calendarDay">
<template #header="{ date }">
<span>{{ date }}</span>
<div class="status-detail flex items-center justify-between">
<div class="green">全天考勤正常</div>
<div class="orange">半勤</div>
<div class="red">缺卡</div>
<div class="gray">请假</div>
</div>
<el-date-picker v-model="monthValue" type="month" placeholder="请选择月份" @change="handleMonth" />
</template>
<template #date-cell="{ data }">
<div
class="w100% h100% position-relative m-0 monthDay"
:class="data.isSelected ? 'is-selected' : ''"
@click="handleViewPlayCard(playCardIdx(data))"
@click="handleViewPlayCard(playCardIdx(data), data)"
>
{{ data.day.split('-').slice(1).join('-') }}
<div :style="{ background: playCardColor(data) }" v-if="playCardIdx(data) != -1"></div>
@ -494,6 +503,7 @@ import {
import { ElLoadingService } from 'element-plus';
import type { CalendarDateType, CalendarInstance } from 'element-plus';
import { AttendanceMonthVO } from '@/api/project/attendance/types';
import { parseTime } from '@/utils/ruoyi';
const calendar = ref<CalendarInstance>();
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@ -710,7 +720,12 @@ const getList = async () => {
};
/** 查看打卡记录详情 */
const handleViewPlayCard = async (idx: number) => {
const handleViewPlayCard = async (idx: number, data: any) => {
if (data.type == 'next-month' || data.type == 'prev-month') {
monthValue.value = data.date;
handleCalendarMonth(monthValue.value);
}
const statusColor = calendarList.value[idx]?.status;
if (idx == -1 || statusColor == '4' || statusColor == '3') {
return proxy?.$modal.msgWarning('暂无打卡记录数据');
@ -767,7 +782,16 @@ const getContractorList = async () => {
const handleMonth = async (e: any) => {
calendarDay.value = e;
const res = await listConstructionMonth({ userId: dialog.id, clockMonth: e });
handleCalendarMonth(e);
};
const handleCalendarMonth = async (e?) => {
let clockMonth;
if (e) {
clockMonth = parseTime(e, '{y}-{m}');
}
const res = await listConstructionMonth({ userId: dialog.id, clockMonth });
calendarList.value = res.data;
};
@ -858,10 +882,9 @@ const handleShowDrawer = (row?: ConstructionUserVO) => {
const handlePlayCard = async (row: ConstructionUserVO) => {
const _id = row?.id || ids.value[0];
skipName.value = row?.userName;
const res = await listConstructionMonth({ userId: _id });
calendarList.value = res.data;
dialog.id = _id;
await handleCalendarMonth();
playCardCalendar.value = true;
};
@ -889,15 +912,15 @@ const handleChange = async (row: ConstructionUserVO) => {
skip.value = true;
};
//切换人脸
const handleToggle = async (row: ConstructionUserVO) => {
reset();
skipName.value = row?.userName;
const _id = row?.id || ids.value[0];
const res = await getConstructionUser(_id);
Object.assign(form.value, res.data);
showFaceDrawer.value = true;
};
// //切换人脸
// const handleToggle = async (row: ConstructionUserVO) => {
// reset();
// skipName.value = row?.userName;
// const _id = row?.id || ids.value[0];
// const res = await getConstructionUser(_id);
// Object.assign(form.value, res.data);
// showFaceDrawer.value = true;
// };
const handleExit = async (row: ConstructionUserVO) => {
const _id = row?.id || ids.value[0];
@ -1031,12 +1054,66 @@ const handleClockStatus = async (row: ConstructionUserVO) => {
playCardLoding.value = false;
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
getContractorList();
});
</script>
<style scoped lang="scss">
.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%;
}
}
.red {
&::before {
background-color: red;
}
}
.gray {
&::before {
background-color: gray;
}
}
.orange {
&::before {
background-color: orange;
}
}
.green {
&::before {
background-color: green;
}
}
}
.monthDay {
padding: 8px;
> div {

View File

@ -15,9 +15,10 @@
<el-col :span="16">
<file-upload
v-model="ossIdMap[activeMenu]"
:limit="1"
:limit="20"
:file-size="50"
:file-type="['pdf']"
isDarg
@update:model-value="
(args) => {
handleOssUpdate(args);

View File

@ -263,7 +263,19 @@ const handleContractorFile = (row?: ContractorVO) => {
console.log(currentContractorId.value);
visible.value = true;
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
});

View File

@ -407,6 +407,20 @@ const handleExport = () => {
);
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
});

View File

@ -52,7 +52,7 @@
<dict-tag :options="sys_normal_disable" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="项目类型" align="center" prop="projectType">
<el-table-column label="项目类型" align="center" prop="projectType" width="120">
<template #default="scope">
<dict-tag :options="project_type" :value="scope.row.projectType" />
</template>
@ -62,11 +62,10 @@
<dict-tag :options="project_category_type" :value="scope.row.projectCategory" />
</template>
</el-table-column>
<el-table-column label="项目地址" align="center" prop="projectSite" />
<el-table-column label="负责人" align="center" prop="principal" />
<el-table-column label="负责人电话" align="center" prop="principalPhone" />
<el-table-column label="实际容量" align="center" prop="actual" />
<el-table-column label="计划容量" align="center" prop="plan" />
<el-table-column label="负责人电话" align="center" prop="principalPhone" width="100" />
<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" />
@ -108,7 +107,7 @@
</el-col>
<el-col :span="12" :offset="0">
<el-form-item label="负责人电话" prop="principalPhone">
<el-input v-model="form.principalPhone" placeholder="请输入负责人电话" />
<el-input v-model="form.principalPhone" placeholder="请输入负责人电话" type="number" />
</el-form-item>
</el-col>
<el-col :span="12" :offset="0">
@ -417,7 +416,7 @@ const handleUpdate = async (row?: ProjectVO) => {
/** 上传安全协议书按钮操作 */
const uploadVisible = ref<boolean>(false);
const fileUploadParam = ref({
const fileUploadParam = ref<{ id: string | number; securityAgreement: string }>({
id: undefined,
securityAgreement: undefined
});

View File

@ -14,7 +14,7 @@
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<!-- <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>
@ -49,7 +49,7 @@
导出
</el-button>
</el-col>
</el-row>
</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" />

View File

@ -43,6 +43,11 @@
<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" />
@ -134,7 +139,8 @@ const initFormData: ProjectTeamForm = {
projectId: currentProject.value.id,
teamName: undefined,
isClockIn: undefined,
remark: undefined
remark: undefined,
peopleNumber: undefined
};
const data = reactive<PageData<ProjectTeamForm, ProjectTeamQuery>>({
form: { ...initFormData },
@ -146,7 +152,8 @@ const data = reactive<PageData<ProjectTeamForm, ProjectTeamQuery>>({
projectId: currentProject.value.id,
teamName: undefined,
isClockIn: undefined,
params: {}
params: {},
peopleNumber: undefined
},
rules: {
id: [{ required: true, message: '主键id不能为空', trigger: 'blur' }],
@ -257,6 +264,19 @@ const handleExport = () => {
`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();

View File

@ -361,6 +361,20 @@ const submitAudit = async () => {
await getList();
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
});

View File

@ -14,11 +14,11 @@
<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-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-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
@ -100,7 +100,7 @@
<el-input v-model="form.projectId" placeholder="请输入项目id" />
</el-form-item> -->
<el-form-item label="工种" prop="workType">
<el-select v-model="form.workType" placeholder="请选择工种">
<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>
@ -110,18 +110,18 @@
</el-select>
</el-form-item>
<el-form-item label="工资计算方式" prop="wageCalculationType">
<el-select v-model="form.wageCalculationType" placeholder="请选择工资计算方式">
<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-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> -->
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
@ -298,6 +298,20 @@ const handleExport = () => {
);
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getList();
}
);
onUnmounted(() => {
listeningProject();
});
onMounted(() => {
getList();
});

View File

@ -4,11 +4,18 @@
<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 label="申请人" prop="userName">
<el-input v-model="queryParams.userName" placeholder="请输入申请人" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="申请人名字" prop="userName">
<el-input v-model="queryParams.userName" placeholder="请输入申请人名字" clearable @keyup.enter="handleQuery" />
<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>
@ -20,99 +27,75 @@
</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:workerDailyReport:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['project:workerDailyReport:edit']"
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete()"
v-hasPermi="['project:workerDailyReport:remove']"
>删除</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['project:workerDailyReport:export']">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" :data="workerDailyReportList" @selection-change="handleSelectionChange">
<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" />
<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-tooltip content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['project:workerDailyReport:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button
link
type="primary"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['project:workerDailyReport:remove']"
></el-button>
</el-tooltip>
<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>
<el-form ref="workerDailyReportFormRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="项目id" prop="projectId">
<el-input v-model="form.projectId" placeholder="请输入项目id" />
</el-form-item>
<el-form-item label="班组id" prop="teamId">
<el-input v-model="form.teamId" placeholder="请输入班组id" />
</el-form-item>
<el-form-item label="申请人id" prop="userId">
<el-input v-model="form.userId" placeholder="请输入申请人id" />
</el-form-item>
<el-form-item label="申请人名字" prop="userName">
<el-input v-model="form.userName" placeholder="请输入申请人名字" />
</el-form-item>
<el-form-item label="今日完成工作" prop="todayCompletedWork">
<el-input v-model="form.todayCompletedWork" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="未完成工作" prop="unfinishedWork">
<el-input v-model="form.unfinishedWork" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="明日工作" prop="tomorrowWork">
<el-input v-model="form.tomorrowWork" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="需协调与帮助" prop="coordinationHelp">
<el-input v-model="form.coordinationHelp" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="附件" prop="file">
<file-upload v-model="form.file" />
</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>
<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>
</template>
</div>
</el-dialog>
</div>
</template>
@ -126,6 +109,7 @@ import {
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;
@ -151,6 +135,17 @@ const dialog = reactive<DialogOption>({
title: ''
});
const reSubmitType = ref<SpecialType[]>([
{
label: '打卡',
value: '1'
},
{
label: '补卡',
value: '2'
}
]);
const initFormData: WorkerDailyReportForm = {
id: undefined,
projectId: currentProject.value?.id,
@ -161,7 +156,8 @@ const initFormData: WorkerDailyReportForm = {
unfinishedWork: undefined,
tomorrowWork: undefined,
coordinationHelp: undefined,
file: undefined
fileList: undefined,
isResubmit: undefined
};
const data = reactive<PageData<WorkerDailyReportForm, WorkerDailyReportQuery>>({
form: { ...initFormData },
@ -172,16 +168,21 @@ const data = reactive<PageData<WorkerDailyReportForm, WorkerDailyReportQuery>>({
teamId: undefined,
userId: undefined,
userName: undefined,
params: {}
},
rules: {
id: [{ required: true, message: '主键id不能为空', trigger: 'blur' }],
projectId: [{ required: true, message: '项目id不能为空', trigger: 'blur' }],
userId: [{ required: true, message: '申请人id不能为空', trigger: 'blur' }]
params: {},
isResubmit: '1'
}
});
const { queryParams, form, rules } = toRefs(data);
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 () => {
@ -192,18 +193,6 @@ const getList = async () => {
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
workerDailyReportFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
@ -216,23 +205,8 @@ const resetQuery = () => {
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: WorkerDailyReportVO[]) => {
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?: WorkerDailyReportVO) => {
reset();
/** 详情按钮操作 */
const handleDetail = async (row?: WorkerDailyReportVO) => {
const _id = row?.id || ids.value[0];
const res = await getWorkerDailyReport(_id);
Object.assign(form.value, res.data);
@ -240,44 +214,34 @@ const handleUpdate = async (row?: WorkerDailyReportVO) => {
dialog.title = '修改施工人员日报';
};
/** 提交按钮 */
const submitForm = () => {
workerDailyReportFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateWorkerDailyReport(form.value).finally(() => (buttonLoading.value = false));
} else {
await addWorkerDailyReport(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value.id,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getList();
}
);
/** 删除按钮操作 */
const handleDelete = async (row?: WorkerDailyReportVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除施工人员日报编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delWorkerDailyReport(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'project/workerDailyReport/export',
{
...queryParams.value
},
`workerDailyReport_${new Date().getTime()}.xlsx`
);
};
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>