接口调试

This commit is contained in:
BianLzhaoMin 2025-12-24 18:00:03 +08:00
parent a1cb84cde5
commit adc33f74f5
16 changed files with 529 additions and 317 deletions

View File

@ -17,3 +17,21 @@ export function getPersonNatureAndCategoryAndPositionSelectAPI(data) {
params: data,
})
}
// 公共下拉选数据 - 获取工作量类别
// export function getWorkloadCategorySelectAPI(data) {
// return request({
// url: '/workloadCategory/getWorkloadCategorySelect',
// method: 'GET',
// params: data,
// })
// }
// 公共下拉选数据 - 获取人员列表
export function getPersonnelCommonListAPI(data) {
return request({
url: '/personnel/getPersonnelListSelect',
method: 'GET',
params: data,
})
}

View File

@ -1,37 +1,46 @@
import request from '@/utils/request'
// 计划管理- 查询列表
export function listPlanAPI(query) {
// 计划管理- 查询列表
export function listMonthlyPlanAPI(query) {
return request({
url: '/personnel/getPersonnelList',
url: '/monthlyPlan/getMonthlyPlanList',
method: 'GET',
params: query,
})
}
// 计划管理- 新增
export function addPlanAPI(data) {
// 计划管理- 新增
export function addMonthlyPlanAPI(data) {
return request({
url: '/personnel/addPersonnel',
url: '/monthlyPlan/addMonthlyPlan',
method: 'POST',
data,
})
}
// 计划管理- 修改
export function updatePlanAPI(data) {
// 计划管理- 修改
export function updateMonthlyPlanAPI(data) {
return request({
url: '/personnel/updatePersonnel',
url: '/monthlyPlan/updatePersonnel',
method: 'POST',
data,
})
}
// 计划管理- 删除
export function delPlanAPI(data) {
// 计划管理- 删除
export function delMonthlyPlanAPI(data) {
return request({
url: `/personnel/delPersonnel`,
url: `/monthlyPlan/delMonthlyPlan`,
method: 'POST',
data,
})
}
// 月计划新增计划时的弹框- 查询列表
export function listMonthlyPlanPopupAPI(query) {
return request({
url: '/planManagement/getPlanManagementLists',
method: 'GET',
params: query,
})
}

View File

@ -3,7 +3,7 @@ import request from '@/utils/request'
// 计划管理- 查询列表
export function listPlanAPI(query) {
return request({
url: '/personnel/getPersonnelList',
url: '/planManagement/getPlanManagementList',
method: 'GET',
params: query,
})
@ -12,7 +12,7 @@ export function listPlanAPI(query) {
// 计划管理- 新增
export function addPlanAPI(data) {
return request({
url: '/personnel/addPersonnel',
url: '/planManagement/addPlanManagement',
method: 'POST',
data,
})
@ -21,7 +21,7 @@ export function addPlanAPI(data) {
// 计划管理- 修改
export function updatePlanAPI(data) {
return request({
url: '/personnel/updatePersonnel',
url: '/planManagement/updatePlanManagement',
method: 'POST',
data,
})
@ -30,7 +30,7 @@ export function updatePlanAPI(data) {
// 计划管理- 删除
export function delPlanAPI(data) {
return request({
url: `/personnel/delPersonnel`,
url: `/planManagement/delPlanManagement`,
method: 'POST',
data,
})

View File

@ -68,6 +68,7 @@ const componentMap = {
input: ItemInput,
select: ItemSelect,
date: ItemDate,
month: ItemDate,
cascader: ItemCascader,
}
@ -115,6 +116,12 @@ const getComponentProps = (item) => {
startPlaceholder: item.startPlaceholder,
endPlaceholder: item.endPlaceholder,
}
case 'month':
return {
...baseProps,
dateType: 'month',
valueFormat: item.valueFormat || 'YYYY-MM',
}
case 'cascader':
return {
...baseProps,

View File

@ -29,7 +29,7 @@ import './permission' // permission control
import { useDict } from '@/utils/dict'
import { getConfigKey } from "@/api/system/config"
import { parseTime, resetForm, addDateRange, handleTree, selectDictLabel, selectDictLabels } from '@/utils/ruoyi'
import { parseTime, resetForm, addDateRange, handleTree, selectDictLabel, selectDictLabels, createDictFormatter } from '@/utils/ruoyi'
// 分页组件
import Pagination from '@/components/Pagination'
@ -58,6 +58,7 @@ app.config.globalProperties.addDateRange = addDateRange
app.config.globalProperties.getConfigKey = getConfigKey
app.config.globalProperties.selectDictLabel = selectDictLabel
app.config.globalProperties.selectDictLabels = selectDictLabels
app.config.globalProperties.createDictFormatter = createDictFormatter
// 全局组件挂载
app.component('DictTag', DictTag)

View File

@ -6,6 +6,7 @@ const useOptionsStore = defineStore('options', {
personNatureOptions: [], // 人员性质
personCategoryOptions: [], // 人员分类
inspectionStationOptions: [], // 运检站
personnelCommonOptions: [], // 人员列表
}),
actions: {
// 通用的设置方法,方便 Hook 调用

View File

@ -92,6 +92,26 @@ export function selectDictLabel(datas, value) {
return actions.join('')
}
/**
* 创建字典 formatter 函数用于表格列配置
* @param {Array} dictData 字典数据数组
* @param {String} fieldName 字段名默认为当前列的 prop
* @returns {Function} formatter 函数
* @example
* // 在表格列配置中使用
* {
* prop: 'riskLevel',
* label: '风险等级',
* formatter: createDictFormatter(plan_risk_level.value)
* }
*/
export function createDictFormatter(dictData, fieldName = null) {
return (row, column, cellValue) => {
const value = fieldName ? row[fieldName] : cellValue
return selectDictLabel(dictData, value)
}
}
// 回显数据字典(字符串、数组)
export function selectDictLabels(datas, value, separator) {
if (value === undefined || value.length === 0) {

View File

@ -56,8 +56,9 @@ import {
getInspectionStationSelectAPI,
getPersonNatureAndCategoryAndPositionSelectAPI,
} from '@/api/common.js'
import config from './config'
import { useOptions } from '@/hooks/useOptions'
import { bus, BUS_EVENTS } from '@/utils/bus'
import config from './config'
import ComTable from '@/components/ComTable/index.vue'
import ComButton from '@/components/ComButton/index.vue'
import ComDialog from '@/components/ComDialog/index.vue'
@ -155,6 +156,7 @@ const actionColumns = [
if (result.code === 200) {
proxy.$modal.msgSuccess('删除成功')
comTableRef.value?.refresh()
bus.emit(BUS_EVENTS.REFRESH_OPTIONS, 'personnelCommonOptions')
}
})
},
@ -190,6 +192,7 @@ const onHandleSave = async () => {
proxy.$modal.msgSuccess(editId.value ? '编辑成功' : '新增成功')
dialogConfig.outerVisible = false
comTableRef.value?.refresh()
bus.emit(BUS_EVENTS.REFRESH_OPTIONS, 'personnelCommonOptions')
}
} catch (error) {
return Promise.reject(error)

View File

@ -12,12 +12,11 @@
>
<el-form-item label="月计划执行月份:" prop="month" class="month-item">
<el-date-picker
v-model="formData.month"
type="month"
v-model="formData.month"
value-format="YYYY-MM"
placeholder="xxxx-xx"
placeholder="请选择月份"
style="width: 200px"
clearable
/>
</el-form-item>
</el-form>
@ -25,11 +24,11 @@
<!-- 搜索区域 -->
<div class="search-section">
<el-input
v-model.trim="formData.keyword"
placeholder="输入关键字"
clearable
@keyup.enter="onSearch"
class="search-input"
placeholder="输入关键字"
v-model.trim="formData.keyword"
>
<template #prefix>
<el-icon class="search-icon" @click="onSearch">
@ -52,16 +51,18 @@
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column
prop="name"
prop="projectName"
label="项目名称"
min-width="260"
show-overflow-tooltip
align="center"
/>
<el-table-column
prop="workTask"
prop="workContent"
label="工作任务"
min-width="360"
show-overflow-tooltip
align="center"
/>
</el-table>
</div>
@ -71,6 +72,8 @@
<script setup name="MonthlyPlanAddForm">
import { ref, watch, getCurrentInstance, reactive } from 'vue'
import { Search } from '@element-plus/icons-vue'
import { listMonthlyPlanPopupAPI } from '@/api/planMange/monthlyPlan'
import dayjs from 'dayjs'
const props = defineProps({
//
@ -96,7 +99,7 @@ const tableData = ref([
const selectedRows = ref([])
const formData = ref({
month: props.defaultMonth || '',
month: dayjs().format('YYYY-MM'), //
keyword: '',
})
@ -106,16 +109,15 @@ const rules = {
// /
const fetchData = async () => {
if (!props.loadTaskList) return
await formRef.value.validate()
loading.value = true
try {
const params = {
month: formData.value.month,
keyword: formData.value.keyword,
planManagementMonth: formData.value.month,
keyWord: formData.value.keyword,
}
const res = await props.loadTaskList(params)
tableData.value = res?.rows || res?.data?.rows || res?.data || []
const res = await listMonthlyPlanPopupAPI(params)
tableData.value = res?.data
} catch (e) {
console.error('加载计划任务列表失败:', e)
tableData.value = []
@ -154,6 +156,10 @@ defineExpose({
return true
},
})
onMounted(() => {
fetchData()
})
</script>
<style scoped lang="scss">

View File

@ -62,16 +62,25 @@ export const buildFormColumns = () => [
// 月计划列表表格列
export const tableColumns = [
{ prop: 'stationName', label: '运检站' },
{ prop: 'majorName', label: '专业' },
{ prop: 'businessTypeName', label: '业务类型' },
{ prop: 'projectName', label: '项目名称' },
{ prop: 'workTask', label: '工作任务' },
{ prop: 'inspectionStationName', label: '运检站', fixed: true },
{ prop: 'planMajorId', label: '专业', fixed: true },
{ prop: 'businessTypeId', label: '业务类型', fixed: true },
{ prop: 'projectName', label: '项目名称', fixed: true },
{ prop: 'workContent', label: '工作任务' },
{ prop: 'riskLevelName', label: '风险等级' },
{ prop: 'categoryName', label: '类别' },
{ prop: 'workAmount', label: '工作量' },
{ prop: 'baseCount', label: '基数' },
{ prop: 'planStartDate', label: '计划开始时间' },
{ prop: 'planCategoryId', label: '类别' },
{ prop: 'workAmount', label: '工作量', width: '140' },
{ prop: 'towerBaseNumber', label: '基塔数' },
{ prop: 'plannedStartTime', label: '计划开始时间', width: '140' },
{ prop: 'plannedEndTime', label: '计划结束时间', width: '140' },
{ prop: 'planPersonnel', label: '计划投入管理人员数量' },
{ prop: 'planSkilledWorkerDay', label: '计划投入管理人员工日' },
{ prop: 'planCarNum', label: '计划投入管理人员车辆数' },
{ prop: 'planSkilledWorkerNum', label: '计划投入熟练工人员数量' },
{ prop: 'planAuxiliaryWorkerNum', label: '计划投入辅助工人员数量' },
{ prop: 'planAuxiliaryWorkerDay', label: '计划投入施工人员工日' },
{ prop: 'planSubCarNum', label: '计划投入分包车辆数' },
{ prop: 'actualWorkingDay', label: '实际工作天数' },
]
export const dialogConfig = reactive({

View File

@ -12,21 +12,21 @@
ref="formRef"
:model="formData"
:rules="rules"
label-width="180"
label-width="140"
size="large"
:disabled="isDetail"
>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="运检站">
<el-input v-model="formData.stationName" disabled />
<el-input v-model="formData.inspectionStationName" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="专业" prop="majorId">
<el-form-item label="专业" prop="planMajorId">
<el-select
v-model="formData.majorId"
v-model="formData.planMajorId"
placeholder="请选择专业"
clearable
>
@ -88,8 +88,28 @@
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="类别" prop="typeId">
<el-select v-model="formData.typeId" placeholder="请选择类别" clearable>
<el-form-item label="风险等级" prop="riskLevel">
<el-select
v-model="formData.riskLevel"
placeholder="请选择风险等级"
clearable
>
<el-option
v-for="item in riskLevelOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="类别" prop="planCategoryId">
<el-select
v-model="formData.planCategoryId"
placeholder="请选择类别"
clearable
>
<el-option
v-for="item in riskLevelOptions"
:key="item.value"
@ -104,10 +124,13 @@
<el-row :gutter="24">
<template v-for="(item, index) in formData.workLoadList" :key="index">
<el-col :span="8">
<el-form-item :label="index == 0 ? '工作量' : ''" prop="workType">
<el-form-item
:label="index == 0 ? '工作量' : ''"
:prop="`workLoadList.${index}.workloadCategoryId`"
>
<el-select
clearable
v-model="item.workType"
v-model="item.workloadCategoryId"
placeholder="请选择工作量类别"
>
<el-option
@ -120,9 +143,12 @@
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label-width="0" prop="count">
<el-form-item
label-width="0"
:prop="`workLoadList.${index}.workloadNum`"
>
<el-input
v-model="item.count"
v-model="item.workloadNum"
style="width: 240px"
placeholder="输入数量"
>
@ -150,11 +176,11 @@
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="塔基数" prop="towerCount">
<el-form-item label="基塔数" prop="towerBaseNumber">
<el-input
clearable
placeholder="请输入基数"
v-model.trim="formData.towerCount"
placeholder="请输入数"
v-model.trim="formData.towerBaseNumber"
/>
</el-form-item>
</el-col>
@ -164,22 +190,24 @@
<el-col :span="12">
<el-form-item label="计划开始时间">
<el-date-picker
v-model="formData.planStartDate"
v-model="formData.plannedStartTime"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择计划开始时间"
style="width: 100%"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="计划结束时间">
<el-date-picker
v-model="formData.planEndDate"
v-model="formData.plannedEndTime"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择计划结束时间"
style="width: 100%"
disabled
/>
</el-form-item>
</el-col>
@ -187,7 +215,7 @@
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="计划投入管理人员" prop="planManagers">
<el-form-item label="计划投入管理人员" prop="planPersonnel">
<el-input
v-model="selectedManagerNames"
readonly
@ -206,57 +234,58 @@
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="计划投入车辆数量" prop="planVehicleCount">
<el-form-item label="计划投入管理人员车辆数" prop="planCarNum">
<el-input
clearable
placeholder="请输入车辆数量"
v-model.trim="formData.planVehicleCount"
v-model.trim="formData.planCarNum"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="7">
<el-form-item label="计划投入熟练工人数" prop="skilledStaffCount">
<el-form-item label="计划投入熟练工人员数量" prop="planSkilledWorkerNum">
<el-input
clearable
placeholder="请输入熟练工人数"
v-model.trim="formData.skilledStaffCount"
placeholder="请输入熟练工人"
v-model.trim="formData.planSkilledWorkerNum"
/>
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item
label="计划投入工日"
prop="skilledWorkDays"
prop="planSkilledWorkerDay"
label-width="auto"
>
<el-input
clearable
placeholder="请输入熟练工工日"
v-model.trim="formData.skilledWorkDays"
placeholder="计划投入工日"
v-model.trim="formData.planSkilledWorkerDay"
/>
</el-form-item>
</el-col>
<el-col :span="7">
<el-form-item label="计划投入辅助工人数" prop="assistantStaffCount">
<el-form-item label="计划投入辅助工人员数量" prop="planAuxiliaryWorkerNum">
<el-input
clearable
placeholder="请输入辅助工人数"
v-model.trim="formData.assistantStaffCount"
placeholder="请输入辅助工人"
v-model.trim="formData.planAuxiliaryWorkerNum"
/>
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item
label="计划投入工日"
prop="assistantWorkDays"
prop="planAuxiliaryWorkerDay"
label-width="auto"
>
<el-input
clearable
placeholder="请输入辅助工工日"
v-model.trim="formData.assistantWorkDays"
placeholder="计划投入工日"
v-model.trim="formData.planAuxiliaryWorkerDay"
/>
</el-form-item>
</el-col>
@ -264,20 +293,20 @@
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="计划投入分包车辆" prop="subcontractVehicleCount">
<el-form-item label="计划投入分包车辆数" prop="planSubCarNum">
<el-input
clearable
placeholder="请输入分包车辆数量"
v-model.trim="formData.subcontractVehicleCount"
v-model.trim="formData.planSubCarNum"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="实际工作天数">
<el-form-item label="实际工作天数" prop="actualWorkingDay">
<el-input
clearable
placeholder="请输入实际工作天数"
v-model.trim="formData.actualWorkDays"
v-model.trim="formData.actualWorkingDay"
/>
</el-form-item>
</el-col>
@ -372,7 +401,7 @@
type="primary"
size="small"
plain
:disabled="!day.isInRange || !formData.planManagers.length"
:disabled="!day.isInRange || !formData.planPersonnel.length"
@click="onFillManagersForDay(day.date)"
>
安排人员
@ -414,18 +443,49 @@
/>
</div>
<el-table
border
ref="personTableRef"
:data="filteredPersons"
height="400px"
@selection-change="onManagerSelectionChange"
>
<el-table-column type="selection" width="50" />
<el-table-column prop="org" label="人员所属单位" width="140" />
<el-table-column prop="name" label="姓名" width="120" />
<el-table-column prop="gender" label="性别" width="80" />
<el-table-column prop="station" label="岗位" width="140" />
<el-table-column prop="position" label="岗位性质" width="140" />
<el-table-column prop="type" label="人员分类" />
<el-table-column type="selection" width="50" align="center" />
<el-table-column
show-overflow-tooltip
prop="org"
label="人员所属单位"
align="center"
/>
<el-table-column
show-overflow-tooltip
prop="name"
label="姓名"
width="120"
align="center"
/>
<el-table-column
show-overflow-tooltip
prop="gender"
label="性别"
align="center"
/>
<el-table-column
show-overflow-tooltip
prop="station"
label="岗位"
align="center"
/>
<el-table-column
show-overflow-tooltip
prop="position"
label="岗位性质"
align="center"
/>
<el-table-column
show-overflow-tooltip
prop="type"
label="人员分类"
align="center"
/>
</el-table>
</el-col>
<el-col :span="8">
@ -468,15 +528,25 @@
<script setup name="MonthlyPlanEdit">
import { ref, reactive, computed, getCurrentInstance, nextTick } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { addPlanAPI, updatePlanAPI } from '@/api/planMange/plan.js'
import { updatePlanAPI } from '@/api/planMange/plan.js'
import { getPersonnelCommonListAPI } from '@/api/common.js'
import { listPlanProfessionalAPI } from '@/api/basicManage/planProfessional'
import { Search } from '@element-plus/icons-vue'
import { useOptions } from '@/hooks/useOptions'
import ComButton from '@/components/ComButton/index.vue'
import ComDialog from '@/components/ComDialog/index.vue'
import { Search } from '@element-plus/icons-vue'
const route = useRoute()
const router = useRouter()
const { proxy } = getCurrentInstance()
// 使 Hook
const { options: personnelCommonOptions } = useOptions(
'personnelCommonOptions',
getPersonnelCommonListAPI,
{},
)
const mode = computed(() => route.query.mode || 'add')
const isDetail = computed(() => mode.value === 'detail')
@ -488,36 +558,47 @@ const pageTitle = computed(() => {
const formRef = ref(null)
const getInitFormData = () => ({
planId: null,
stationName: '测试运检站1',
majorId: null,
businessTypeId: null,
projectName: '测试项目123',
workContent:
'工作内容非常多工作内容非常多···工作内容非常多···工作内容非常多···工作内容非常多···工作内容非常多···工作内容非常多······--',
riskLevel: null,
// 2025 12
month: '2025-12',
planStartDate: '2025-12-06',
planEndDate: '2025-12-30',
typeId: null,
towerCount: '',
planManagers: [],
planVehicleCount: '',
skilledStaffCount: '',
skilledWorkDays: '',
assistantStaffCount: '',
assistantWorkDays: '',
subcontractVehicleCount: '',
actualWorkDays: '',
//
const routeParams = computed(() => ({
inspectionStationName: route.query.inspectionStationName || '',
projectName: route.query.projectName || '',
workContent: route.query.workContent || '',
plannedStartTime: route.query.plannedStartTime || '',
plannedEndTime: route.query.plannedEndTime || '',
monthlyPlanId: route.query.monthlyPlanId || null,
}))
const getInitFormData = () => ({
monthlyPlanId: routeParams.value.monthlyPlanId,
//
inspectionStationName: routeParams.value.inspectionStationName,
projectName: routeParams.value.projectName,
workContent: routeParams.value.workContent,
plannedStartTime: routeParams.value.plannedStartTime,
plannedEndTime: routeParams.value.plannedEndTime,
//
majorId: null, //
businessTypeId: null, //
riskLevel: null, //
planCategoryId: null, //
towerBaseNumber: '', //
planPersonnel: [], //
planPersonnelWorkDays: '', //
planCarNum: '', //
planSkilledWorkerNum: '', //
planAuxiliaryWorkerNum: '', //
planAuxiliaryWorkerDay: '', //
planSkilledWorkerDay: '', //
planSubCarNum: '', //
actualWorkingDay: '', //
workLoadList: [
{
workType: '',
count: '',
workloadCategoryId: '', // id
unitPrice: '', //
workloadNum: '', //
},
],
personnelArrangementList: [], // [{day: '', personnelNames: ''}]
})
const formData = ref(getInitFormData())
@ -528,10 +609,7 @@ const stationOptions = [
{ label: '大理运检站', value: 2 },
]
const majorOptions = [
{ label: '输电专业', value: 1 },
{ label: '变电专业', value: 2 },
]
const majorOptions = ref([])
const businessTypeOptions = [
{ label: '日常巡视', value: 1 },
@ -545,21 +623,30 @@ const riskLevelOptions = [
]
const rules = {
majorId: [{ required: true, message: '请选择专业', trigger: 'change' }],
planMajorId: [{ required: true, message: '请选择专业', trigger: 'change' }],
businessTypeId: [{ required: true, message: '请选择业务类型', trigger: 'change' }],
typeId: [{ required: true, message: '请输选择类别', trigger: 'change' }],
workType: [{ required: true, message: '请选择计工作量类别', trigger: 'change' }],
count: [{ required: true, message: '请输入数量', trigger: 'blur' }],
towerCount: [{ required: true, message: '请输入塔基数量', trigger: 'blur' }],
planManagers: [{ required: true, message: '请选择计划投入管理人员', trigger: 'blur' }],
planVehicleCount: [{ required: true, message: '请输入计划投入车数量', trigger: 'blur' }],
skilledStaffCount: [{ required: true, message: '请输入计划投入熟练工人数', trigger: 'blur' }],
skilledWorkDays: [{ required: true, message: '请输入计划投入工日', trigger: 'blur' }],
assistantStaffCount: [{ required: true, message: '请输入计划投入辅助工人数', trigger: 'blur' }],
subcontractVehicleCount: [
{ required: true, message: '请输入计划投入分包车辆数量', trigger: 'blur' },
riskLevel: [{ required: true, message: '请选择风险等级', trigger: 'change' }],
planCategoryId: [{ required: true, message: '请选择类别', trigger: 'change' }],
towerBaseNumber: [{ required: true, message: '请输入基塔数', trigger: 'blur' }],
planPersonnel: [{ required: true, message: '请选择计划投入管理人员', trigger: 'blur' }],
planPersonnelWorkDays: [
{ required: true, message: '请输入计划投入管理人员工日', trigger: 'blur' },
],
assistantWorkDays: [{ required: true, message: '请输入辅助工工日', trigger: 'blur' }],
planCarNum: [{ required: true, message: '请输入计划投入管理人员车辆数', trigger: 'blur' }],
planSkilledWorkerNum: [
{ required: true, message: '请输入计划投入熟练工人员数量', trigger: 'blur' },
],
planAuxiliaryWorkerNum: [
{ required: true, message: '请输入计划投入辅助工人员数量', trigger: 'blur' },
],
planSkilledWorkerDay: [
{ required: true, message: '请输入计划投入熟练工人员工日', trigger: 'blur' },
],
planAuxiliaryWorkerDay: [
{ required: true, message: '请输入计划投入辅助工人员工日', trigger: 'blur' },
],
planSubCarNum: [{ required: true, message: '请输入计划投入分包车辆数', trigger: 'blur' }],
actualWorkingDay: [{ required: true, message: '请输入实际工作天数', trigger: 'blur' }],
}
const onBack = () => {
@ -577,12 +664,30 @@ const onSubmit = () => {
return
}
//
//
const {
inspectionStationName,
projectName,
workContent,
plannedStartTime,
plannedEndTime,
...submitData
} = formData.value
// personnelArrangementList
submitData.personnelArrangementList = Object.keys(dayAssignments.value).map((date) => {
const managers = dayAssignments.value[date] || []
return {
day: date,
personnelNames: managers.map((p) => p.name).join('、'),
}
})
console.log('submitData组装后的参数', submitData)
// const API = mode.value === 'edit' ? updatePlanAPI : addPlanAPI
// const payload = { ...formData.value }
// try {
// const res = await API(payload)
// const res = await API(submitData)
// if (res.code === 200) {
// proxy.$modal.msgSuccess(mode.value === 'edit' ? '' : '')
// onBack()
@ -595,8 +700,9 @@ const onSubmit = () => {
const onAddWorkLoad = () => {
formData.value.workLoadList.push({
workType: '',
count: '',
workloadCategoryId: '',
unitPrice: '',
workloadNum: '',
})
}
@ -618,86 +724,34 @@ const managerDialog = reactive({
visible: false,
keyword: '',
selected: [],
data: [
{
id: 1,
org: '昆明运检站',
name: '张三',
gender: '男',
station: '站长',
position: '全职',
type: '运检人员',
},
{
id: 2,
org: '昆明运检站',
name: '李四钱七',
gender: '男',
station: '副站长',
position: '全职',
type: '运检人员',
},
{
id: 3,
org: '昆明运检站',
name: '王五',
gender: '男',
station: '安全员',
position: '全职',
type: '运检人员',
},
{
id: 4,
org: '大理运检站',
name: '赵六钱七',
gender: '女',
station: '文员',
position: '派遣',
type: '后勤人员',
},
{
id: 5,
org: '大理运检站',
name: '钱七',
gender: '男',
station: '驾驶员',
position: '派遣',
type: '运检人员',
},
{
id: 6,
org: '大理运检站',
name: '钱七钱七',
gender: '男',
station: '驾驶员',
position: '派遣',
type: '运检人员',
},
{
id: 7,
org: '大理运检站',
name: '钱七',
gender: '男',
station: '驾驶员',
position: '派遣',
type: '运检人员',
},
],
})
//
const personList = computed(() => {
return (personnelCommonOptions.value || []).map((item) => ({
...item,
org: item.inspectionStationName, //
gender: item.sex === '1' ? '男' : '女',
station: item.positionName, //
position: item.personnelNatureName, //
type: item.personnelClassificationName, //
}))
})
const filteredPersons = computed(() => {
if (!managerDialog.keyword) return managerDialog.data
const list = personList.value
if (!managerDialog.keyword) return list
const keyword = managerDialog.keyword.toLowerCase()
return managerDialog.data.filter(
(item) =>
item.name.toLowerCase().includes(keyword) ||
item.org.toLowerCase().includes(keyword) ||
item.station.toLowerCase().includes(keyword),
)
return list.filter((item) => {
const name = (item.name || '').toLowerCase()
const org = (item.org || '').toLowerCase()
const station = (item.station || '').toLowerCase()
return name.includes(keyword) || org.includes(keyword) || station.includes(keyword)
})
})
const selectedManagerNames = computed(() =>
formData.value.planManagers.map((item) => item.name).join('、'),
formData.value.planPersonnel.map((item) => item.name).join('、'),
)
const onOpenPersonPicker = async () => {
@ -706,14 +760,14 @@ const onOpenPersonPicker = async () => {
await nextTick()
if (personTableRef.value) {
personTableRef.value.clearSelection()
managerDialog.data.forEach((row) => {
const exists = formData.value.planManagers.find((item) => item.id === row.id)
personList.value.forEach((row) => {
const exists = formData.value.planPersonnel.find((item) => item.id === row.id)
if (exists) {
personTableRef.value.toggleRowSelection(row, true)
}
})
}
managerDialog.selected = [...formData.value.planManagers]
managerDialog.selected = [...formData.value.planPersonnel]
}
const onManagerSelectionChange = (rows) => {
@ -723,7 +777,7 @@ const onManagerSelectionChange = (rows) => {
const onRemoveManager = (item) => {
managerDialog.selected = managerDialog.selected.filter((row) => row.id !== item.id)
if (personTableRef.value) {
const target = managerDialog.data.find((row) => row.id === item.id)
const target = personList.value.find((row) => row.id === item.id)
if (target) personTableRef.value.toggleRowSelection(target, false)
}
}
@ -734,7 +788,7 @@ const onClearManagers = () => {
}
const onConfirmManager = () => {
formData.value.planManagers = [...managerDialog.selected]
formData.value.planPersonnel = [...managerDialog.selected]
managerDialog.visible = false
managerDialogConfig.outerVisible = false
}
@ -744,33 +798,29 @@ const onCloseDialogOuter = (visible) => {
managerDialogConfig.outerVisible = visible
}
//
//
const dayAssignments = ref({}) // { '2025-01-01': [person, ...] }
const maxShowInCell = 5
const calendarDays = computed(() => {
const monthStr = formData.value.month
if (!monthStr) return []
const start = formData.value.plannedStartTime
const end = formData.value.plannedEndTime
if (!start || !end) return []
const [yearStr, monthStrNum] = monthStr.split('-')
//
const [yearStr, monthStr] = start.split('-')
const year = Number(yearStr)
const month = Number(monthStrNum)
const month = Number(monthStr)
if (!year || !month) return []
const daysInMonth = new Date(year, month, 0).getDate()
const start = formData.value.planStartDate
const end = formData.value.planEndDate
const pad = (n) => (n < 10 ? `0${n}` : `${n}`)
const list = []
for (let d = 1; d <= daysInMonth; d++) {
const date = `${year}-${pad(month)}-${pad(d)}`
const label = `${month}${pad(d)}`
let isInRange = false
if (start && end) {
isInRange = date >= start && date <= end
}
const isInRange = date >= start && date <= end
list.push({
date,
label,
@ -783,8 +833,8 @@ const calendarDays = computed(() => {
//
const onFillManagersForDay = (date) => {
if (!formData.value.planManagers || !formData.value.planManagers.length) return
dayAssignments.value[date] = formData.value.planManagers.map((p) => ({ ...p }))
if (!formData.value.planPersonnel || !formData.value.planPersonnel.length) return
dayAssignments.value[date] = formData.value.planPersonnel.map((p) => ({ ...p }))
}
//
@ -799,6 +849,27 @@ const onRemovePersonFromDay = (date, person) => {
const list = dayAssignments.value[date] || []
dayAssignments.value[date] = list.filter((item) => item.id !== person.id)
}
//
const getMajorOptions = async () => {
const res = await listPlanProfessionalAPI({
pageNum: 1,
pageSize: 1000,
category: 0,
})
console.log('专业列表', res)
if (res.code === 200) {
majorOptions.value = res.rows?.map((item) => ({
label: item.planMajorName,
value: item.planMajorId,
}))
}
}
onMounted(() => {
getMajorOptions()
})
</script>
<style scoped lang="scss">

View File

@ -5,7 +5,7 @@
ref="comTableRef"
:form-columns="formColumns"
:table-columns="tableColumns"
:load-data="listPlanAPI"
:load-data="listMonthlyPlanAPI"
:show-toolbar="true"
:show-action="true"
:action-columns="actionColumns"
@ -54,7 +54,11 @@
<script setup name="MonthlyPlan">
import { ref, computed, getCurrentInstance } from 'vue'
import { useRouter } from 'vue-router'
import { listPlanAPI, delPlanAPI } from '@/api/planMange/plan.js'
import {
listMonthlyPlanAPI,
addMonthlyPlanAPI,
delMonthlyPlanAPI,
} from '@/api/planMange/monthlyPlan.js'
import config from './config'
import ComTable from '@/components/ComTable/index.vue'
import ComButton from '@/components/ComButton/index.vue'
@ -90,9 +94,24 @@ const actionColumns = [
type: 'primary',
link: true,
handler: (row) => {
const {
monthlyPlanId,
inspectionStationName,
projectName,
workContent,
plannedStartTime,
plannedEndTime,
} = row
router.push({
path: '/plan/monthlyPlanEdit/index',
query: { id: row.planId, mode: 'edit' },
query: {
monthlyPlanId,
inspectionStationName,
projectName,
workContent,
plannedStartTime,
plannedEndTime,
},
})
},
},
@ -102,7 +121,7 @@ const actionColumns = [
link: true,
handler: (row) => {
proxy.$modal.confirm('是否确认删除该月计划?').then(async () => {
const result = await delPlanAPI({ planId: row.planId })
const result = await delMonthlyPlanAPI({ monthlyPlanId: row.monthlyPlanId })
if (result.code === 200) {
proxy.$modal.msgSuccess('删除成功')
comTableRef.value?.refresh()
@ -123,8 +142,28 @@ const onHandleCancel = () => {
}
//
const onHandleSave = () => {
const onHandleSave = async () => {
addFormRef.value.validate()
const paramsList = addFormRef.value.getSelectedTasks().map((item) => ({
planManagementId: item.planManagementId,
planManagementMonth: item.planManagementMonth,
inspectionStationId: item.inspectionStationId,
inspectionStationName: item.inspectionStationName,
projectName: item.projectName,
workContent: item.workContent,
planManagementMonth: item.planManagementMonth,
plannedStartTime: item.stareDate,
plannedEndTime: item.endDate,
riskLevel: item.riskLevel,
}))
const result = await addMonthlyPlanAPI(paramsList)
if (result.code === 200) {
proxy.$modal.msgSuccess('保存成功')
dialogConfig.outerVisible = false
comTableRef.value?.refresh()
}
}
//

View File

@ -8,9 +8,9 @@
class="add-and-edit-form"
>
<!-- 月份 -->
<el-form-item label="月份" prop="month">
<el-form-item label="月份" prop="planManagementMonth">
<el-date-picker
v-model="formData.month"
v-model="formData.planManagementMonth"
type="month"
value-format="YYYY-MM"
placeholder="请选择月份"
@ -42,27 +42,27 @@
</el-form-item>
<!-- 实施部门 -->
<el-form-item label="实施部门" prop="deptId">
<el-form-item label="实施部门" prop="inspectionStationId">
<el-select
clearable
filterable
style="width: 100%"
placeholder="请选择实施部门"
v-model="formData.deptId"
v-model="formData.inspectionStationId"
>
<el-option
v-for="item in deptOptions"
:key="item.value"
:value="item.value"
:label="item.label"
v-for="item in inspectionStationOptions"
:key="item.id"
:value="item.id"
:label="item.value"
/>
</el-select>
</el-form-item>
<!-- 计划开始时间 -->
<el-form-item label="计划开始时间" prop="planStartDate">
<el-form-item label="计划开始时间" prop="stareDate">
<el-date-picker
v-model="formData.planStartDate"
v-model="formData.stareDate"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择计划开始时间"
@ -71,9 +71,9 @@
</el-form-item>
<!-- 计划结束时间 -->
<el-form-item label="计划结束时间" prop="planEndDate">
<el-form-item label="计划结束时间" prop="endDate">
<el-date-picker
v-model="formData.planEndDate"
v-model="formData.endDate"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择计划结束时间"
@ -90,7 +90,7 @@
v-model="formData.riskLevel"
>
<el-option
v-for="item in riskLevelOptions"
v-for="item in plan_risk_level"
:key="item.value"
:value="item.value"
:label="item.label"
@ -114,35 +114,29 @@
<script setup name="AddAndEditForm">
import { ref } from 'vue'
const { proxy } = getCurrentInstance()
const { plan_risk_level } = proxy.useDict('plan_risk_level')
const props = defineProps({
formData: {
type: Object,
default: () => ({}),
},
inspectionStationOptions: {
type: Array,
default: () => [],
},
})
const formRef = ref(null)
//
const deptOptions = [
{ label: '实施部门一', value: 1 },
{ label: '实施部门二', value: 2 },
]
const riskLevelOptions = [
{ label: '低风险', value: 1 },
{ label: '中风险', value: 2 },
{ label: '高风险', value: 3 },
]
const rules = {
month: [{ required: true, message: '请选择月份', trigger: 'change' }],
planManagementMonth: [{ required: true, message: '请选择月份', trigger: 'change' }],
projectName: [{ required: true, message: '请输入项目名称', trigger: 'blur' }],
workContent: [{ required: true, message: '请输入作业内容', trigger: 'blur' }],
deptId: [{ required: true, message: '请选择实施部门', trigger: 'change' }],
planStartDate: [{ required: true, message: '请选择计划开始时间', trigger: 'change' }],
planEndDate: [{ required: true, message: '请选择计划结束时间', trigger: 'change' }],
inspectionStationId: [{ required: true, message: '请选择实施部门', trigger: 'change' }],
stareDate: [{ required: true, message: '请选择计划开始时间', trigger: 'change' }],
endDate: [{ required: true, message: '请选择计划结束时间', trigger: 'change' }],
riskLevel: [{ required: true, message: '请选择风险等级', trigger: 'change' }],
}

View File

@ -1,57 +1,26 @@
import { reactive } from 'vue'
// 静态选项(后续可替换为接口下拉)
const stationOptions = [
{ label: '昆明运检站', value: 1 },
{ label: '大理运检站', value: 2 },
]
const majorOptions = [
{ label: '输电专业', value: 1 },
{ label: '变电专业', value: 2 },
]
const businessTypeOptions = [
{ label: '日常巡视', value: 1 },
{ label: '缺陷处理', value: 2 },
]
const riskLevelOptions = [
{ label: '低风险', value: 1 },
{ label: '中风险', value: 2 },
{ label: '高风险', value: 3 },
]
// 搜索表单配置(计划管理列表筛选)
export const buildFormColumns = () => [
export const buildFormColumns = (inspectionStationOptions = [], riskLevelOptions = []) => [
{
type: 'month',
prop: 'month',
prop: 'planManagementMonth',
placeholder: '请选择月份',
},
{
type: 'select',
prop: 'stationId',
placeholder: '请选择运检站',
options: stationOptions,
prop: 'inspectionStationId',
placeholder: '请选择部门',
options: inspectionStationOptions.map((item) => ({
label: item.value,
value: item.id,
})),
},
{
type: 'input',
prop: 'keyword',
prop: 'keyWord',
placeholder: '请输入关键字',
},
{
type: 'select',
prop: 'majorId',
placeholder: '请选择专业',
options: majorOptions,
},
{
type: 'select',
prop: 'businessTypeId',
placeholder: '请选择业务类型',
options: businessTypeOptions,
},
{
type: 'select',
prop: 'riskLevel',
@ -62,7 +31,7 @@ export const buildFormColumns = () => [
export const tableColumns = [
{
prop: 'month',
prop: 'planManagementMonth',
label: '月份',
},
{
@ -74,19 +43,19 @@ export const tableColumns = [
label: '作业内容',
},
{
prop: 'deptName',
prop: 'inspectionStationName',
label: '实施部门',
},
{
prop: 'planStartDate',
prop: 'stareDate',
label: '计划开始时间',
},
{
prop: 'planEndDate',
prop: 'endDate',
label: '计划结束时间',
},
{
prop: 'riskLevelName',
prop: 'riskLevel',
label: '风险等级',
},
]

View File

@ -12,14 +12,20 @@
>
<template #toolbar>
<ComButton type="primary" icon="Plus" @click="onHandleAdd">新建计划</ComButton>
<ComButton type="info" icon="Upload" pain @click="onHandleAdd">导入计划</ComButton>
<ComButton type="info" icon="Upload" pain @click="onHandleImport">
导入计划
</ComButton>
</template>
</ComTable>
<ComDialog :dialog-config="dialogConfig" @closeDialogOuter="onCloseDialogOuter">
<template #outerContent>
<!-- 将表单抽离到独立组件中保持 index.vue 简洁 -->
<AddAndEditForm ref="formRef" :form-data="addAndEditForm" />
<AddAndEditForm
ref="formRef"
:form-data="addAndEditForm"
:inspection-station-options="inspectionStationOptions"
/>
<el-row class="common-btn-row">
<ComButton plain type="info" @click="onHandleCancel">取消</ComButton>
@ -33,6 +39,8 @@
<script setup name="Plan">
import { ref, nextTick, getCurrentInstance, computed } from 'vue'
import { listPlanAPI, addPlanAPI, updatePlanAPI, delPlanAPI } from '@/api/planMange/plan.js'
import { getInspectionStationSelectAPI } from '@/api/common.js'
import { useOptions } from '@/hooks/useOptions'
import config from './config'
import ComTable from '@/components/ComTable/index.vue'
@ -40,24 +48,51 @@ import ComButton from '@/components/ComButton/index.vue'
import ComDialog from '@/components/ComDialog/index.vue'
import AddAndEditForm from './addAndEditForm.vue'
const { tableColumns, dialogConfig, buildFormColumns } = config
const { tableColumns: baseTableColumns, dialogConfig, buildFormColumns } = config
const { proxy } = getCurrentInstance()
const formRef = ref(null)
const comTableRef = ref(null)
const editId = ref(null)
//
const { plan_risk_level } = proxy.useDict('plan_risk_level')
//
const formColumns = computed(() => buildFormColumns())
const formColumns = computed(() =>
buildFormColumns(inspectionStationOptions.value, plan_risk_level.value),
)
// formatter
const tableColumns = computed(() => {
return baseTableColumns.map((column) => {
if (column.prop === 'riskLevel') {
return {
...column,
formatter: proxy.createDictFormatter(plan_risk_level.value, 'riskLevel'),
}
}
return column
})
})
// 使 Hook
const { options: inspectionStationOptions } = useOptions(
'inspectionStationOptions',
getInspectionStationSelectAPI,
{},
)
console.log(inspectionStationOptions, 'inspectionStationOptions')
// 1.
const getInitFormData = () => ({
month: '', //
planManagementMonth: '', //
projectName: '', //
workContent: '', //
deptId: null, //
planStartDate: '', //
planEndDate: '', //
inspectionStationId: null, //
stareDate: '', //
endDate: '', //
riskLevel: null, //
remark: '', //
})
@ -70,12 +105,32 @@ const actionColumns = [
type: 'primary',
link: true,
handler: (row) => {
editId.value = row.planId
editId.value = row.planManagementId
dialogConfig.outerTitle = '编辑计划'
dialogConfig.outerVisible = true
// 2. 使 nextTick
nextTick(() => {
Object.assign(addAndEditForm.value, row)
const {
planManagementMonth,
projectName,
workContent,
inspectionStationId,
stareDate,
endDate,
riskLevel,
remark,
} = row
Object.assign(addAndEditForm.value, {
planManagementMonth,
projectName,
workContent,
inspectionStationId: inspectionStationId + '',
stareDate,
endDate,
riskLevel,
remark,
})
})
},
},
@ -85,7 +140,9 @@ const actionColumns = [
link: true,
handler: (row) => {
proxy.$modal.confirm('是否确认删除该计划?').then(async () => {
const result = await delPlanAPI(row.planId)
const result = await delPlanAPI({
planManagementId: row.planManagementId,
})
if (result.code === 200) {
proxy.$modal.msgSuccess('删除成功')
comTableRef.value?.refresh()
@ -116,9 +173,11 @@ const onHandleSave = async () => {
try {
// 3. validate
await formRef.value.validate()
const API = editId.value ? updatePlanAPI : addPlanAPI
const result = await API(addAndEditForm.value)
const API = editId.value ? updatePlanAPI : addPlanAPI
const params = JSON.parse(JSON.stringify(addAndEditForm.value))
editId.value ? (params.planManagementId = editId.value) : null
const result = await API(params)
if (result.code === 200) {
proxy.$modal.msgSuccess(editId.value ? '编辑成功' : '新增成功')
dialogConfig.outerVisible = false
@ -129,6 +188,11 @@ const onHandleSave = async () => {
}
}
//
const onHandleImport = () => {
console.log('导入计划')
}
//
const onCloseDialogOuter = (visible) => {
dialogConfig.outerVisible = visible

View File

@ -3,7 +3,8 @@ import path from 'path'
import createVitePlugins from './vite/plugins'
// const baseUrl = 'http://192.168.0.133:58080' // 后端接口地址 超子
const baseUrl = 'http://localhost:58080' // 后端接口地址 超子
// const baseUrl = 'http://localhost:58080' // 后端接口地址
const baseUrl = 'http://192.168.0.60:58080' // 后端接口地址 福海
// https://vitejs.dev/config/
export default defineConfig(({ mode, command }) => {