日计划完善

This commit is contained in:
BianLzhaoMin 2025-12-30 14:02:57 +08:00
parent 4d59cb2325
commit 0e9570ca37
10 changed files with 1292 additions and 206 deletions

View File

@ -115,6 +115,7 @@ const getComponentProps = (item) => {
rangeSeparator: item.rangeSeparator || '-',
startPlaceholder: item.startPlaceholder,
endPlaceholder: item.endPlaceholder,
style: item.style,
}
case 'month':
return {
@ -133,21 +134,49 @@ const getComponentProps = (item) => {
}
}
// paramsList
const processFormData = (data) => {
const processedData = { ...data }
props.formColumns.forEach((item) => {
// paramsList
if (item.paramsList && Array.isArray(item.paramsList) && item.paramsList.length > 0) {
const value = processedData[item.prop]
//
if (Array.isArray(value) && value.length > 0) {
item.paramsList.forEach((paramName, index) => {
if (value[index] !== undefined && value[index] !== null && value[index] !== '') {
processedData[paramName] = value[index]
}
})
}
// month[0] month[1]
delete processedData[item.prop]
}
})
return processedData
}
//
const handleSearch = () => {
emit('search', { ...formData })
const processedData = processFormData(formData)
emit('search', processedData)
}
//
const handleReset = () => {
formRef.value?.resetFields()
initFormData()
emit('reset', { ...formData })
const processedData = processFormData(formData)
emit('reset', processedData)
}
//
defineExpose({
getFormData: () => ({ ...formData }),
getFormData: () => processFormData(formData),
resetForm: handleReset,
formRef,
})

View File

@ -17,6 +17,7 @@
v-model="formData.nowDate"
value-format="YYYY-MM-DD"
placeholder="请选择计划日期"
@change="onHandleDateChange"
/>
</el-form-item>
</el-form>
@ -122,6 +123,10 @@ const onSelectionChange = (rows) => {
selectedRows.value = rows
}
const onHandleDateChange = (value) => {
fetchData()
}
//
defineExpose({
getSelectedTasks: () => selectedRows.value,

View File

@ -1,33 +1,16 @@
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 = () => [
{
type: 'month',
type: 'date',
dateType: 'daterange',
paramsList: ['startDate', 'endDate'],
prop: 'month',
placeholder: '请选择月份',
style: {
width: '240px',
},
placeholder: '请选择日期',
},
{
@ -37,37 +20,42 @@ export const buildFormColumns = () => [
},
{
type: 'input',
prop: 'keyword',
prop: 'projectName',
placeholder: '请输入项目名称',
},
{
type: 'input',
prop: 'keyword',
prop: 'workContent',
placeholder: '请输入工作任务',
},
{
type: 'select',
prop: 'riskLevel',
prop: 'planCompletionStatus',
placeholder: '请选择计划状态',
options: riskLevelOptions,
options: [
{ label: '未开始', value: '未开始' },
{ label: '进行中', value: '进行中' },
{ label: '完成', value: '完成' },
],
},
]
// 月计划列表表格列
export const tableColumns = [
{ prop: 'dayPlan', label: '日期', fixed: true, width: '140' },
{ prop: 'inspectionStationName', label: '运检站', fixed: true },
{ prop: 'planMajorName', label: '专业', fixed: true },
{ prop: 'projectName', label: '项目名称', fixed: true },
{ prop: 'workContent', label: '工作任务' },
{ prop: 'riskLevel', label: '风险等级' },
{ prop: 'plannedWorkload', label: '计划工作量(基)' },
{ prop: 'inspectionStationName', label: '运检站', fixed: true, width: '140' },
{ prop: 'planMajorName', label: '专业', fixed: true, width: '80' },
{ prop: 'projectName', label: '项目名称', fixed: true, width: '140' },
{ prop: 'workContent', label: '工作任务', width: '140' },
{ prop: 'riskLevel', label: '风险等级', width: '80' },
{ prop: 'plannedWorkload', label: '计划工作量(基)', width: '80' },
]
export const tableColumns_1 = [
{
prop: 'stationName',
label: '拟投入作业人员数量',
fixed: false,
width: '80',
formatter: (row) => {
return row.proposedPersonnelList?.filter((item) => item.dataSource == 0).length || ''
@ -77,7 +65,7 @@ export const tableColumns_1 = [
prop: 'majorName',
label: '拟投入作业人员姓名',
fixed: false,
width: '180',
width: '200',
formatter: (row) => {
return (
row.proposedPersonnelList
@ -91,15 +79,14 @@ export const tableColumns_1 = [
prop: 'proposedLongTimeCar',
label: '拟投入车辆',
fixed: false,
width: '180',
formatter: (row) => {
return `长租车${row.proposedLongTimeCar}辆,临租车${row.proposedTemporaryCar}` || ''
},
width: '200',
slot: 'proposedLongTimeCar',
},
{
prop: 'projectName',
label: '实际投入作业人员数量',
fixed: false,
width: '80',
formatter: (row) => {
return row.proposedPersonnelList?.filter((item) => item.dataSource == 1).length || ''
},
@ -108,6 +95,7 @@ export const tableColumns_1 = [
prop: 'workTask',
label: '实际投入作业人员姓名',
fixed: false,
width: '200',
formatter: (row) => {
return (
row.proposedPersonnelList
@ -121,44 +109,184 @@ export const tableColumns_1 = [
prop: 'actualLongTimeCar',
label: '实际投入车辆',
fixed: false,
width: '200',
slot: 'actualLongTimeCar',
// formatter: (row) => {
// return `长租车${row.actualLongTimeCar}辆,临租车${row.actualTemporaryCar}辆` || ''
// },
},
{ prop: 'actualWorkContent', label: '实际完成工作内容', fixed: false, width: '200' },
{ prop: 'actualWorkload', label: '实际完成工作量(基)', fixed: false, width: '80' },
{
prop: 'completionPercentage',
label: '完成比例',
fixed: false,
width: '80',
formatter: (row) => {
return `长租车${row.actualLongTimeCar}辆,临租车${row.actualTemporaryCar}` || ''
return row.completionPercentage || ''
},
},
{ prop: 'actualWorkContent', label: '实际完成工作内容', fixed: false },
{ prop: 'actualWorkload', label: '实际完成工作量(基)', fixed: false },
{ prop: 'completionPercentage', label: '完成比例', fixed: false },
{ prop: 'planCompletionStatus', label: '作业计划完成情况', fixed: false },
{ prop: 'planChanges', label: '计划变更及未完成情况说明', fixed: false },
{ prop: 'planCompletionStatus', label: '作业计划完成情况', fixed: false, width: '200' },
{ prop: 'planChanges', label: '计划变更及未完成情况说明', fixed: false, width: '200' },
]
export const tableColumns_2 = [
{ prop: 'stationName', label: '拟投入高处作业人员数量', fixed: false },
{ prop: 'majorName', label: '高处作业人员姓名', fixed: false },
{ prop: 'businessTypeName', label: '拟投入地面作业人员数量', fixed: false },
{ prop: 'projectName', label: '地面作业人员姓名', fixed: false },
{ prop: 'workTask', label: '拟投入检修熟练工数量(分包高空作业人员)', fixed: false },
{ prop: 'riskLevelName', label: '拟投入检修辅助工数量(分包地面作业人员)', fixed: false },
{ prop: 'categoryName', label: '拟投入车辆', fixed: false },
{ prop: 'categoryName', label: '实际投入高处作业人员数量', fixed: false },
{ prop: 'categoryName', label: '高处作业人员姓名', fixed: false },
{ prop: 'categoryName', label: '实际投入地面作业人员数量', fixed: false },
{ prop: 'categoryName', label: '地面作业人员姓名', fixed: false },
{
prop: 'categoryName',
prop: 'stationName',
label: '拟投入高处作业人员数量',
fixed: false,
width: '80',
formatter: (row) => {
return row.proposedPersonnelList?.filter((item) => item.dataSource == 2).length || ''
},
},
{
prop: 'proposedPersonnelListHigh',
label: '高处作业人员姓名',
fixed: false,
width: '200',
formatter: (row) => {
return (
row.proposedPersonnelList
?.filter((item) => item.dataSource == 2)
.map((item) => item.name)
.join(',') || ''
)
},
},
{
prop: 'proposedPersonnelListGroundNum',
label: '拟投入地面作业人员数量',
fixed: false,
width: '80',
formatter: (row) => {
return row.proposedPersonnelList?.filter((item) => item.dataSource == 3).length || ''
},
},
{
prop: 'proposedPersonnelListGround',
label: '地面作业人员姓名',
width: '200',
fixed: false,
formatter: (row) => {
return (
row.proposedPersonnelList
?.filter((item) => item.dataSource == 3)
.map((item) => item.name)
.join(',') || ''
)
},
},
{
prop: 'proposedProficientPersonnel',
label: '拟投入检修熟练工数量(分包高空作业人员)',
fixed: false,
width: '80',
},
{
prop: 'proposedAssistancePersonnel',
label: '拟投入检修辅助工数量(分包地面作业人员)',
fixed: false,
width: '80',
},
{
prop: 'proposedLongTimeCar',
label: '拟投入车辆',
fixed: false,
width: '200',
slot: 'proposedLongTimeCar',
// formatter: (row) => {
// return `长租车${row.proposedLongTimeCar}辆,临租车${row.proposedTemporaryCar}辆` || ''
// },
},
{
prop: 'proposedPersonnelListHighNum',
label: '实际投入高处作业人员数量',
fixed: false,
width: '80',
formatter: (row) => {
return row.proposedPersonnelList?.filter((item) => item.dataSource == 4).length || ''
},
},
{
prop: 'proposedPersonnelListHighName',
label: '高处作业人员姓名',
width: '200',
fixed: false,
formatter: (row) => {
return (
row.proposedPersonnelList
?.filter((item) => item.dataSource == 4)
.map((item) => item.name)
.join(',') || ''
)
},
},
{
prop: 'proposedPersonnelListNum',
label: '实际投入地面作业人员数量',
width: '80',
fixed: false,
formatter: (row) => {
return row.proposedPersonnelList?.filter((item) => item.dataSource == 5).length || ''
},
},
{
prop: 'proposedPersonnelList',
label: '地面作业人员姓名',
width: '200',
fixed: false,
formatter: (row) => {
return (
row.proposedPersonnelList
?.filter((item) => item.dataSource == 5)
.map((item) => item.name)
.join(',') || ''
)
},
},
{
prop: 'actualProficientPersonnel',
label: '实际投入检修熟练工数量(分包高空作业人员)',
fixed: false,
width: '80',
},
{
prop: 'categoryName',
prop: 'actualAssistancePersonnel',
label: '实际投入检修辅助工数量(分包高空作业人员)',
fixed: false,
width: '80',
},
{ prop: 'categoryName', label: '实际投入车辆', fixed: false },
{ prop: 'categoryName', label: '实际完成工作内容', fixed: false },
{ prop: 'categoryName', label: '完成比例', fixed: false },
{ prop: 'categoryName', label: '作业计划完成情况', fixed: false },
{ prop: 'categoryName', label: '计划变更及未完成情况说明', fixed: false },
{
prop: 'actualLongTimeCar',
label: '实际投入车辆',
width: '200',
fixed: false,
slot: 'actualLongTimeCar',
// formatter: (row) => {
// return `长租车${row.actualLongTimeCar}辆,临租车${row.actualTemporaryCar}辆` || ''
// },
},
{
prop: 'workloadCategoryName',
label: '实际完成工作内容',
width: '200',
fixed: false,
formatter: (row) => {
return row.actualWorkloadList?.map((item) => item.workloadCategoryName).join(',') || ''
},
},
{
prop: 'completionPercentage',
label: '完成比例',
fixed: false,
width: '80',
formatter: (row) => {
return row.completionPercentage || ''
},
},
{ prop: 'planCompletionStatus', label: '作业计划完成情况', fixed: false, width: '200' },
{ prop: 'planChanges', label: '计划变更及未完成情况说明', fixed: false, width: '200' },
]
export const dialogConfig = reactive({

View File

@ -307,22 +307,34 @@ const getRepairFormData = () => ({
planChanges: '', //
})
//
//
const getProjectFormData = () => ({
dayPlanId: routeParams.value.dayPlanId,
//
inspectionStationName: routeParams.value.inspectionStationName,
projectName: routeParams.value.projectName,
planMajorName: routeParams.value.planMajorName,
dayPlan: routeParams.value.dayPlan,
//
// TODO:
planPersonnelList: [], //
planPersonnel: '', // 使
//
actualPersonnelList: [], //
actualPersonnel: '', // 使
// TODO:
plannedWorkload: null,
highAltitudePersonnelList: [],
groundPersonnelList: [],
proposedProficientPersonnel: null,
proposedProficientDay: null,
proposedAssistancePersonnel: null,
proposedAssistanceDay: null,
proposedLongTimeCar: null,
proposedTemporaryCar: null,
proposedSubCar: null,
actualHighAltitudePersonnelList: [],
actualGroundPersonnelList: [],
actualProficientPersonnel: null,
actualAssistancePersonnel: null,
actualLongTimeCar: null,
actualTemporaryCar: null,
actualSubCar: null,
actualWorkContent: '',
completionPercentage: null,
planCompletionStatus: null,
planChanges: '',
})
//
@ -347,19 +359,17 @@ const rules = computed(() => ({}))
const onBack = () => {
proxy.$tab.closeOpenPage({
path: '/plan/dailyPlan',
query: {
dayPlanType: dayPlanType.value,
},
})
}
const onSubmit = async () => {
try {
// validate Promise<boolean>
const valid = await formRef.value?.validate()
console.log(valid, 'valid')
if (!valid) {
console.log('校验没有通过')
//
// validate fields
return
}
@ -374,7 +384,7 @@ const onSubmit = async () => {
proposedPersonnelList.push({
dayPlanId: route.query.id,
inspectionStationName: item.inspectionStationName,
personnelld: item.id,
personnelId: item.id,
name: item.name,
dataSource: 0, //
})
@ -383,18 +393,18 @@ const onSubmit = async () => {
proposedPersonnelList.push({
dayPlanId: route.query.id,
inspectionStationName: item.inspectionStationName,
personnelld: item.id,
personnelId: item.id,
name: item.name,
dataSource: 1, //
})
})
} else if (type === '1' || type === 1) {
// / &
} else if (type === '1' || type === 1 || type === '2' || type === 2) {
// / &
;(formData.value.highAltitudePersonnelList || []).forEach((item) => {
proposedPersonnelList.push({
dayPlanId: route.query.id,
inspectionStationName: item.inspectionStationName,
personnelld: item.id,
personnelId: item.id,
name: item.name,
dataSource: 2, //
})
@ -403,7 +413,7 @@ const onSubmit = async () => {
proposedPersonnelList.push({
dayPlanId: route.query.id,
inspectionStationName: item.inspectionStationName,
personnelld: item.id,
personnelId: item.id,
name: item.name,
dataSource: 3, //
})
@ -412,7 +422,7 @@ const onSubmit = async () => {
proposedPersonnelList.push({
dayPlanId: route.query.id,
inspectionStationName: item.inspectionStationName,
personnelld: item.id,
personnelId: item.id,
name: item.name,
dataSource: 4, //
})
@ -421,7 +431,7 @@ const onSubmit = async () => {
proposedPersonnelList.push({
dayPlanId: route.query.id,
inspectionStationName: item.inspectionStationName,
personnelld: item.id,
personnelId: item.id,
name: item.name,
dataSource: 5, //
})
@ -447,17 +457,17 @@ const onSubmit = async () => {
} = formData.value
submitData.proposedPersonnelList = proposedPersonnelList
submitData.workloadList = formData.value.actualWorkloadList
submitData.dayPlanType = type
if (type === '1' || type === 1) {
submitData.workloadList = formData.value.actualWorkloadList
}
console.log('submitData日计划提交参数', submitData)
//
const result = await updateDailyPlanAPI(submitData)
if (result.code === 200) {
proxy.$modal.msgSuccess('保存成功')
onBack()
}
} catch (error) {
console.log(error, 'error')
return Promise.reject(error)
}
}
@ -504,9 +514,12 @@ const filteredPersons = computed(() => {
})
const selectedManagerNames = computed(() => {
//
if (dayPlanType.value === '1' || dayPlanType.value === 1) {
//
if (
dayPlanType.value === '1' ||
dayPlanType.value === 1 ||
dayPlanType.value === '2' ||
dayPlanType.value === 2
) {
const highAltitude = (formData.value.highAltitudePersonnelList || [])
.map((item) => item.name)
.join('、')
@ -515,7 +528,6 @@ const selectedManagerNames = computed(() => {
.join('、')
return [highAltitude, ground].filter(Boolean).join('、') || ''
}
// 使 planPersonnelList
return (formData.value.planPersonnelList || []).map((item) => item.name).join('、')
})
@ -525,7 +537,6 @@ const onOpenPersonPicker = async (type = 'plan') => {
await nextTick()
if (personTableRef.value) {
personTableRef.value.clearSelection()
//
let currentList = []
if (type === 'plan') {
currentList = formData.value.planPersonnelList || []
@ -612,12 +623,167 @@ const onCloseDialogOuter = (visible) => {
//
const getDetail = async () => {
// TODO: API
// const result = await getDailyPlanDetailAPI({ dayPlanId: route.query.id })
// if (result.code === 200 && result.data) {
// const data = result.data
// //
// }
try {
const result = await getDailyPlanDetailAPI({ dayPlanId: route.query.id })
if (result.code === 200 && result.data) {
const data = result.data
const type = dayPlanType.value
//
const baseFields = {
dayPlanId: data.dayPlanId,
plannedWorkload: data.plannedWorkload,
proposedLongTimeCar: data.proposedLongTimeCar,
proposedTemporaryCar: data.proposedTemporaryCar,
actualLongTimeCar: data.actualLongTimeCar,
actualTemporaryCar: data.actualTemporaryCar,
actualWorkContent: data.actualWorkContent,
actualWorkload: data.actualWorkload,
completionPercentage: data.completionPercentage,
planCompletionStatus: data.planCompletionStatus,
planChanges: data.planChanges,
}
// proposedPersonnelList dataSource
const proposedPersonnelList = data.proposedPersonnelList || []
if (type === '0' || type === 0) {
// 使 planPersonnelList actualPersonnelList
baseFields.planPersonnelList = proposedPersonnelList
.filter((item) => item.dataSource === 0 || item.dataSource === '0')
.map((item) => ({
id: item.personnelId,
name: item.name || '',
inspectionStationName: item.inspectionStationName || '',
}))
baseFields.actualPersonnelList = proposedPersonnelList
.filter((item) => item.dataSource === 1 || item.dataSource === '1')
.map((item) => ({
id: item.personnelId,
name: item.name || '',
inspectionStationName: item.inspectionStationName || '',
}))
} else if (type === '1' || type === 1 || type === '2' || type === 2) {
// 使 highAltitudePersonnelListgroundPersonnelListactualHighAltitudePersonnelListactualGroundPersonnelList
baseFields.highAltitudePersonnelList = proposedPersonnelList
.filter((item) => item.dataSource === 2 || item.dataSource === '2')
.map((item) => ({
id: item.personnelId,
name: item.name || '',
inspectionStationName: item.inspectionStationName || '',
}))
baseFields.groundPersonnelList = proposedPersonnelList
.filter((item) => item.dataSource === 3 || item.dataSource === '3')
.map((item) => ({
id: item.personnelId,
name: item.name || '',
inspectionStationName: item.inspectionStationName || '',
}))
baseFields.actualHighAltitudePersonnelList = proposedPersonnelList
.filter((item) => item.dataSource === 4 || item.dataSource === '4')
.map((item) => ({
id: item.personnelId,
name: item.name || '',
inspectionStationName: item.inspectionStationName || '',
}))
baseFields.actualGroundPersonnelList = proposedPersonnelList
.filter((item) => item.dataSource === 5 || item.dataSource === '5')
.map((item) => ({
id: item.personnelId,
name: item.name || '',
inspectionStationName: item.inspectionStationName || '',
}))
//
baseFields.proposedProficientPersonnel = data.proposedProficientPersonnel
baseFields.proposedProficientDay = data.proposedProficientDay
baseFields.proposedAssistancePersonnel = data.proposedAssistancePersonnel
baseFields.proposedAssistanceDay = data.proposedAssistanceDay
baseFields.proposedSubCar = data.proposedSubCar
baseFields.actualProficientPersonnel = data.actualProficientPersonnel
baseFields.actualAssistancePersonnel = data.actualAssistancePersonnel
baseFields.actualSubCar = data.actualSubCar
// workloadList
if (type === '1' || type === 1) {
baseFields.actualWorkloadList =
data.workloadList && data.workloadList.length > 0
? data.workloadList.map((item) => ({
workloadCategoryId: item.workloadCategoryId || '',
workloadCategoryName: item.workloadCategoryName || '',
unitPrice: item.unitPrice || '',
workloadNum: item.workloadNum || '',
}))
: [
{
workloadCategoryId: '',
workloadCategoryName: '',
unitPrice: '',
workloadNum: '',
},
]
}
}
//
formData.value = {
...formData.value,
...baseFields,
}
//
let hasActualData = false
if (type === '0' || type === 0) {
//
hasActualData =
baseFields.actualPersonnelList?.length > 0 ||
baseFields.actualWorkload ||
baseFields.actualWorkContent ||
baseFields.actualLongTimeCar ||
baseFields.actualTemporaryCar ||
baseFields.planCompletionStatus
} else if (type === '1' || type === 1) {
//
hasActualData =
baseFields.actualHighAltitudePersonnelList?.length > 0 ||
baseFields.actualGroundPersonnelList?.length > 0 ||
(baseFields.actualWorkloadList?.length > 0 &&
baseFields.actualWorkloadList[0]?.workloadCategoryId) ||
baseFields.actualWorkload ||
baseFields.actualProficientPersonnel ||
baseFields.actualAssistancePersonnel ||
baseFields.actualLongTimeCar ||
baseFields.actualTemporaryCar ||
baseFields.actualSubCar ||
baseFields.planCompletionStatus
} else if (type === '2' || type === 2) {
//
hasActualData =
baseFields.actualHighAltitudePersonnelList?.length > 0 ||
baseFields.actualGroundPersonnelList?.length > 0 ||
baseFields.actualWorkContent ||
baseFields.actualWorkload ||
baseFields.actualProficientPersonnel ||
baseFields.actualAssistancePersonnel ||
baseFields.actualLongTimeCar ||
baseFields.actualTemporaryCar ||
baseFields.actualSubCar ||
baseFields.planCompletionStatus
}
if (hasActualData) {
nextTick(() => {
formRef.value?.showActualCompletionForm?.()
})
}
}
} catch (error) {
console.error('获取详情失败:', error)
}
}
//

View File

@ -1,82 +1,514 @@
<template>
<el-card shadow="never" class="card-section">
<template #header>
<div class="card-header">投入的资源情况项目部</div>
</template>
<el-form
ref="formRef"
:model="formData"
:rules="!isDetail ? rules : {}"
size="large"
label-width="auto"
:disabled="isDetail"
>
<!-- 项目部类型的表单字段稍后完善 -->
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="计划工作量" prop="planWorkload">
<el-input-number
:model-value="formData.planWorkload"
@update:model-value="(val) => updateField('planWorkload', val)"
:min="0"
:precision="2"
placeholder="请输入计划工作量"
style="width: 100%"
/>
</el-form-item>
</el-col>
<div>
<el-card shadow="never" class="card-section">
<template #header>
<div class="card-header">计划投入资源情况</div>
</template>
<el-form
ref="formRef"
size="large"
:model="formData"
label-width="180"
:disabled="isDetail"
:rules="!isDetail ? rules : {}"
:validate-on-rule-change="false"
>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="计划工作量" prop="plannedWorkload">
<el-input
clearable
maxlength="7"
show-word-limit
placeholder="请输入计划工作量"
:model-value="formData.plannedWorkload"
@update:model-value="(val) => updateField('plannedWorkload', val)"
>
<template #suffix>
<span class="input-suffix"></span>
</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-col :span="12">
<el-form-item label="拟投入作业人员" prop="planPersonnelList">
<el-input
:model-value="selectedManagerNames"
placeholder="请选择作业人员"
readonly
@click="onOpenPersonPicker"
class="clickable-suffix"
>
<template #suffix>
<el-icon class="clickable-suffix">
<Search />
</el-icon>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="拟投入高处作业人员" prop="highAltitudePersonnelList">
<el-input
readonly
class="clickable-suffix"
@click="onOpenPersonPicker('highAltitude')"
placeholder="请选择高处作业人员"
:model-value="selectedHighAltitudeNames"
>
<template #suffix>
<el-icon class="clickable-suffix">
<Search />
</el-icon>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="拟投入地面作业人员" prop="groundPersonnelList">
<el-input
readonly
class="clickable-suffix"
@click="onOpenPersonPicker('ground')"
placeholder="请选择地面作业人员"
:model-value="selectedGroundNames"
>
<template #suffix>
<el-icon class="clickable-suffix">
<Search />
</el-icon>
</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="7">
<el-form-item prop="proposedProficientPersonnel">
<template #label>
<div style="display: flex; flex-direction: column">
<span>计划投入熟练工人员数量</span>
<span
style="
font-size: 12px;
color: #999;
transform: translateY(-20px);
"
>
(分包高空作业人员)
</span>
</div>
</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-input
clearable
maxlength="7"
show-word-limit
placeholder="熟练工人员数量"
:model-value="formData.proposedProficientPersonnel"
@update:model-value="
(val) => updateField('proposedProficientPersonnel', val)
"
/>
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item
label="计划投入工日"
prop="proposedProficientDay"
label-width="120"
>
<el-input
clearable
maxlength="7"
placeholder="工日"
:model-value="formData.proposedProficientDay"
@update:model-value="
(val) => updateField('proposedProficientDay', val)
"
/>
</el-form-item>
</el-col>
<el-col :span="7">
<el-form-item prop="proposedAssistancePersonnel">
<template #label>
<div style="display: flex; flex-direction: column">
<span>计划投入辅助工人员数量</span>
<span
style="
font-size: 12px;
color: #999;
transform: translateY(-20px);
"
>
(分包地面作业人员)
</span>
</div>
</template>
<el-input
clearable
maxlength="7"
show-word-limit
placeholder="辅助工人员数量"
:model-value="formData.proposedAssistancePersonnel"
@update:model-value="
(val) => updateField('proposedAssistancePersonnel', val)
"
/>
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item
label="计划投入工日"
prop="proposedAssistanceDay"
label-width="120"
>
<el-input
clearable
maxlength="7"
placeholder="工日"
:model-value="formData.proposedAssistanceDay"
@update:model-value="
(val) => updateField('proposedAssistanceDay', val)
"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="拟投入长租车" prop="planLongRentCar">
<el-input-number
:model-value="formData.planLongRentCar"
@update:model-value="(val) => updateField('planLongRentCar', val)"
:min="0"
placeholder="请输入长租车数量"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="拟投入长租车" prop="proposedLongTimeCar">
<el-input
clearable
maxlength="7"
show-word-limit
placeholder="请输入长租车数量"
:model-value="formData.proposedLongTimeCar"
@update:model-value="
(val) => updateField('proposedLongTimeCar', val)
"
>
<template #suffix>
<span class="input-suffix"></span>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="拟投入临租车" prop="planTempRentCar">
<el-input-number
:model-value="formData.planTempRentCar"
@update:model-value="(val) => updateField('planTempRentCar', val)"
:min="0"
placeholder="请输入临租车数量"
style="width: 100%"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<el-col :span="12">
<el-form-item label="拟投入临租车" prop="proposedTemporaryCar">
<el-input
clearable
maxlength="7"
show-word-limit
placeholder="请输入临租车数量"
:model-value="formData.proposedTemporaryCar"
@update:model-value="
(val) => updateField('proposedTemporaryCar', val)
"
>
<template #suffix>
<span class="input-suffix"></span>
</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="拟投入分包车" prop="proposedSubCar">
<el-input
clearable
maxlength="7"
show-word-limit
placeholder="请输入分包车数量"
:model-value="formData.proposedSubCar"
@update:model-value="(val) => updateField('proposedSubCar', val)"
>
<template #suffix>
<span class="input-suffix"></span>
</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<el-card
v-if="showActualCompletion"
shadow="never"
class="card-section"
style="margin-top: 20px"
>
<template #header>
<div class="card-header">实际完成情况</div>
</template>
<el-form
ref="actualFormRef"
:model="formData"
:rules="!isDetail ? actualRules : {}"
size="large"
label-width="180"
:disabled="isDetail"
:validate-on-rule-change="false"
>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item
label="实际投入高处作业人员"
prop="actualHighAltitudePersonnelList"
>
<el-input
readonly
class="clickable-suffix"
@click="onOpenActualPersonPicker('highAltitude')"
placeholder="请选择高处作业人员"
:model-value="selectedActualHighAltitudeNames"
>
<template #suffix>
<el-icon class="clickable-suffix">
<Search />
</el-icon>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="实际投入地面作业人员" prop="actualGroundPersonnelList">
<el-input
readonly
class="clickable-suffix"
@click="onOpenActualPersonPicker('ground')"
placeholder="请选择地面作业人员"
:model-value="selectedActualGroundNames"
>
<template #suffix>
<el-icon class="clickable-suffix">
<Search />
</el-icon>
</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item prop="actualProficientPersonnel">
<template #label>
<div style="display: flex; flex-direction: column">
<span>实际投入检修熟练工数量</span>
<span
style="
font-size: 12px;
color: #999;
transform: translateY(-20px);
"
>
(分包高空作业人员)
</span>
</div>
</template>
<el-input
clearable
maxlength="7"
show-word-limit
placeholder="熟练工人员数量"
:model-value="formData.actualProficientPersonnel"
@update:model-value="
(val) => updateField('actualProficientPersonnel', val)
"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="actualAssistancePersonnel">
<template #label>
<div style="display: flex; flex-direction: column">
<span>实际投入检修辅助工数量</span>
<span
style="
font-size: 12px;
color: #999;
transform: translateY(-20px);
"
>
(分包地面作业人员)
</span>
</div>
</template>
<el-input
clearable
maxlength="7"
show-word-limit
placeholder="辅助工人员数量"
:model-value="formData.actualAssistancePersonnel"
@update:model-value="
(val) => updateField('actualAssistancePersonnel', val)
"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="实际投入长租车" prop="actualLongTimeCar">
<el-input
clearable
maxlength="7"
show-word-limit
placeholder="请输入长租车数量"
:model-value="formData.actualLongTimeCar"
@update:model-value="(val) => updateField('actualLongTimeCar', val)"
>
<template #suffix>
<span class="input-suffix"></span>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="实际投入临租车" prop="actualTemporaryCar">
<el-input
clearable
maxlength="7"
show-word-limit
placeholder="请输入临租车数量"
:model-value="formData.actualTemporaryCar"
@update:model-value="
(val) => updateField('actualTemporaryCar', val)
"
>
<template #suffix>
<span class="input-suffix"></span>
</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="实际投入分包车" prop="actualSubCar">
<el-input
clearable
maxlength="7"
show-word-limit
placeholder="请输入分包车数量"
:model-value="formData.actualSubCar"
@update:model-value="(val) => updateField('actualSubCar', val)"
>
<template #suffix>
<span class="input-suffix"></span>
</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="实际完成工作量" prop="actualWorkload">
<el-input
clearable
maxlength="7"
show-word-limit
placeholder="请输入实际完成工作量"
:model-value="formData.actualWorkload"
@update:model-value="(val) => updateField('actualWorkload', val)"
>
<template #suffix>
<span class="input-suffix"></span>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="完成比例" prop="completionPercentage">
<el-input
:model-value="calculatedCompletionPercentage"
placeholder="自动计算"
readonly
disabled
>
<template #suffix>
<span class="input-suffix">%</span>
</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="24">
<el-form-item label="实际完成工作内容" prop="actualWorkContent">
<el-input
:model-value="formData.actualWorkContent"
@update:model-value="(val) => updateField('actualWorkContent', val)"
type="textarea"
:autosize="{ minRows: 6, maxRows: 12 }"
placeholder="请输入实际完成工作内容"
maxlength="500"
show-word-limit
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="作业计划完成情况" prop="planCompletionStatus">
<el-select
:model-value="formData.planCompletionStatus"
@update:model-value="
(val) => updateField('planCompletionStatus', val)
"
placeholder="请选择作业计划完成情况"
clearable
style="width: 100%"
>
<el-option
v-for="item in planCompletionStatusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="24">
<el-form-item label="计划变更及未完成情况说明" prop="planChanges">
<el-input
:model-value="formData.planChanges"
@update:model-value="(val) => updateField('planChanges', val)"
type="textarea"
:autosize="{ minRows: 6, maxRows: 12 }"
placeholder="请输入计划变更及未完成情况说明"
maxlength="500"
show-word-limit
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<div class="form-actions" v-if="!isDetail">
<ComButton
v-if="!showActualCompletion"
type="primary"
@click="showActualCompletion = true"
>
填写实际完成情况
</ComButton>
<ComButton v-else plain type="info" @click="onCancelActualCompletion">
取消实际完成情况
</ComButton>
</div>
</div>
</template>
<script setup name="ProjectForm">
import { ref, computed } from 'vue'
import { ref, computed, nextTick, watch } from 'vue'
import { Search } from '@element-plus/icons-vue'
import ComButton from '@/components/ComButton/index.vue'
const props = defineProps({
formData: {
@ -93,34 +525,273 @@ const props = defineProps({
},
})
const emit = defineEmits(['open-person-picker', 'update:formData'])
const emit = defineEmits(['open-person-picker', 'update:formData', 'open-actual-person-picker'])
const formRef = ref(null)
const actualFormRef = ref(null)
const showActualCompletion = ref(false)
const planCompletionStatusOptions = [
{ label: '完成', value: '完成' },
{ label: '进行中', value: '进行中' },
{ label: '未完成', value: '未完成' },
]
//
const updateField = (field, value) => {
emit('update:formData', {
const newData = {
...props.formData,
[field]: value,
}
if (field === 'actualWorkload' || field === 'plannedWorkload') {
newData.completionPercentage = calculateCompletionPercentage(
newData.actualWorkload,
newData.plannedWorkload,
)
}
emit('update:formData', newData)
}
const calculateCompletionPercentage = (actualWorkload, plannedWorkload) => {
try {
const actual = Number(actualWorkload)
const planned = Number(plannedWorkload)
if (isNaN(actual) || isNaN(planned)) {
return null
}
if (planned <= 0) {
return null
}
if (actual < 0) {
return null
}
const percentage = (actual / planned) * 100
const roundedPercentage = Math.round(percentage * 100) / 100
return roundedPercentage > 100 ? 100 : roundedPercentage
} catch (error) {
console.error('计算完成比例时出错:', error)
return null
}
}
const calculatedCompletionPercentage = computed(() => {
const percentage = calculateCompletionPercentage(
props.formData.actualWorkload,
props.formData.plannedWorkload,
)
return percentage !== null ? percentage : ''
})
watch(
() => [props.formData.actualWorkload, props.formData.plannedWorkload],
([actualWorkload, plannedWorkload]) => {
if (showActualCompletion.value) {
const percentage = calculateCompletionPercentage(actualWorkload, plannedWorkload)
if (percentage !== null && percentage !== props.formData.completionPercentage) {
emit('update:formData', {
...props.formData,
completionPercentage: percentage,
})
}
}
},
{ immediate: true },
)
watch(
() => showActualCompletion.value,
(isShow) => {
if (isShow && props.formData.actualWorkload && props.formData.plannedWorkload) {
const percentage = calculateCompletionPercentage(
props.formData.actualWorkload,
props.formData.plannedWorkload,
)
if (percentage !== null) {
emit('update:formData', {
...props.formData,
completionPercentage: percentage,
})
}
}
},
)
const positiveIntegerPattern = /^[1-9]\d*$/
const nonNegativeIntegerPattern = /^(0|[1-9]\d*)$/
const rules = computed(() => ({
plannedWorkload: [
{ required: true, message: '请输入计划工作量', trigger: 'blur' },
{ pattern: positiveIntegerPattern, message: '请输入正整数', trigger: 'blur' },
],
highAltitudePersonnelList: [
{ required: true, message: '请选择拟投入高处作业人员', trigger: 'change' },
],
groundPersonnelList: [
{ required: true, message: '请选择拟投入地面作业人员', trigger: 'change' },
],
proposedProficientPersonnel: [
{ required: true, message: '请输入计划投入熟练工人员数量', trigger: 'blur' },
{ pattern: nonNegativeIntegerPattern, message: '请输入非负整数', trigger: 'blur' },
],
proposedProficientDay: [
{ required: true, message: '请输入计划投入工日', trigger: 'blur' },
{ pattern: positiveIntegerPattern, message: '请输入正整数', trigger: 'blur' },
],
proposedAssistancePersonnel: [
{ required: true, message: '请输入计划投入辅助工人员数量', trigger: 'blur' },
{ pattern: nonNegativeIntegerPattern, message: '请输入非负整数', trigger: 'blur' },
],
proposedAssistanceDay: [
{ required: true, message: '请输入计划投入工日', trigger: 'blur' },
{ pattern: positiveIntegerPattern, message: '请输入正整数', trigger: 'blur' },
],
proposedLongTimeCar: [
{ required: true, message: '请输入拟投入长租车数量', trigger: 'blur' },
{ pattern: nonNegativeIntegerPattern, message: '请输入非负整数', trigger: 'blur' },
],
proposedTemporaryCar: [
{ required: true, message: '请输入拟投入临租车数量', trigger: 'blur' },
{ pattern: nonNegativeIntegerPattern, message: '请输入非负整数', trigger: 'blur' },
],
proposedSubCar: [
{ required: true, message: '请输入拟投入分包车数量', trigger: 'blur' },
{ pattern: nonNegativeIntegerPattern, message: '请输入非负整数', trigger: 'blur' },
],
}))
const actualRules = computed(() => ({
actualHighAltitudePersonnelList: [
{ required: true, message: '请选择实际投入高处作业人员', trigger: 'change' },
],
actualGroundPersonnelList: [
{ required: true, message: '请选择实际投入地面作业人员', trigger: 'change' },
],
actualProficientPersonnel: [
{ required: true, message: '请输入实际投入检修熟练工数量', trigger: 'blur' },
{ pattern: nonNegativeIntegerPattern, message: '请输入非负整数', trigger: 'blur' },
],
actualAssistancePersonnel: [
{ required: true, message: '请输入实际投入检修辅助工数量', trigger: 'blur' },
{ pattern: nonNegativeIntegerPattern, message: '请输入非负整数', trigger: 'blur' },
],
actualLongTimeCar: [
{ required: true, message: '请输入实际投入长租车数量', trigger: 'blur' },
{ pattern: nonNegativeIntegerPattern, message: '请输入非负整数', trigger: 'blur' },
],
actualTemporaryCar: [
{ required: true, message: '请输入实际投入临租车数量', trigger: 'blur' },
{ pattern: nonNegativeIntegerPattern, message: '请输入非负整数', trigger: 'blur' },
],
actualSubCar: [
{ required: true, message: '请输入实际投入分包车数量', trigger: 'blur' },
{ pattern: nonNegativeIntegerPattern, message: '请输入非负整数', trigger: 'blur' },
],
actualWorkContent: [{ required: true, message: '请输入实际完成工作内容', trigger: 'blur' }],
actualWorkload: [
{ required: true, message: '请输入实际完成工作量', trigger: 'blur' },
{ pattern: positiveIntegerPattern, message: '请输入正整数', trigger: 'blur' },
],
completionPercentage: [
{
required: true,
validator: (rule, value, callback) => {
const percentage = calculateCompletionPercentage(
props.formData.actualWorkload,
props.formData.plannedWorkload,
)
if (percentage === null || percentage === '') {
callback(new Error('请先填写计划工作量和实际完成工作量'))
} else {
callback()
}
},
trigger: 'blur',
},
],
planCompletionStatus: [
{ required: true, message: '请选择作业计划完成情况', trigger: 'change' },
],
planChanges: [{ required: false, message: '请输入计划变更及未完成情况说明', trigger: 'blur' }],
}))
const selectedHighAltitudeNames = computed(() =>
(props.formData.highAltitudePersonnelList || []).map((item) => item.name).join('、'),
)
const selectedGroundNames = computed(() =>
(props.formData.groundPersonnelList || []).map((item) => item.name).join('、'),
)
const selectedActualHighAltitudeNames = computed(() =>
(props.formData.actualHighAltitudePersonnelList || []).map((item) => item.name).join('、'),
)
const selectedActualGroundNames = computed(() =>
(props.formData.actualGroundPersonnelList || []).map((item) => item.name).join('、'),
)
const onOpenPersonPicker = (type) => {
emit('open-person-picker', type)
}
const onOpenActualPersonPicker = (type) => {
emit('open-person-picker', `actual_${type}`)
}
const onCancelActualCompletion = () => {
showActualCompletion.value = false
const clearedData = {
...props.formData,
actualHighAltitudePersonnelList: [],
actualGroundPersonnelList: [],
actualProficientPersonnel: null,
actualAssistancePersonnel: null,
actualLongTimeCar: null,
actualTemporaryCar: null,
actualSubCar: null,
actualWorkContent: '',
actualWorkload: null,
completionPercentage: null,
planCompletionStatus: null,
planChanges: '',
}
emit('update:formData', clearedData)
nextTick(() => {
actualFormRef.value?.clearValidate()
})
}
//
const rules = computed(() => ({
planWorkload: [{ required: true, message: '请输入计划工作量', trigger: 'blur' }],
planPersonnelList: [{ required: true, message: '请选择拟投入作业人员', trigger: 'change' }],
planLongRentCar: [{ required: true, message: '请输入拟投入长租车数量', trigger: 'blur' }],
planTempRentCar: [{ required: true, message: '请输入拟投入临租车数量', trigger: 'blur' }],
}))
const onOpenPersonPicker = () => {
emit('open-person-picker')
}
//
defineExpose({
validate: () => formRef.value?.validate(),
clearValidate: () => formRef.value?.clearValidate(),
validate: async () => {
const results = []
if (formRef.value) {
results.push(await formRef.value.validate())
}
if (showActualCompletion.value && actualFormRef.value) {
results.push(await actualFormRef.value.validate())
}
return results.every((r) => r !== false)
},
clearValidate: () => {
formRef.value?.clearValidate()
actualFormRef.value?.clearValidate()
},
scrollToField: (prop) => {
if (formRef.value) {
formRef.value.scrollToField(prop)
}
if (actualFormRef.value) {
actualFormRef.value.scrollToField(prop)
}
},
showActualCompletionForm: () => {
showActualCompletion.value = true
},
})
</script>
@ -172,4 +843,16 @@ defineExpose({
.clickable-suffix {
cursor: pointer;
}
.input-suffix {
color: #909399;
font-size: 14px;
padding-right: 8px;
}
.form-actions {
margin-top: 20px;
display: flex;
justify-content: flex-start;
}
</style>

View File

@ -12,6 +12,7 @@
label-width="180"
:disabled="isDetail"
:rules="!isDetail ? rules : {}"
:validate-on-rule-change="false"
>
<el-row :gutter="24">
<el-col :span="12">
@ -241,6 +242,7 @@
size="large"
label-width="180"
:disabled="isDetail"
:validate-on-rule-change="false"
>
<el-row :gutter="24">
<el-col :span="12">
@ -251,8 +253,8 @@
<el-input
readonly
class="clickable-suffix"
@click="onOpenActualPersonPicker('highAltitude')"
placeholder="请选择高处作业人员"
@click="onOpenActualPersonPicker('highAltitude')"
:model-value="selectedActualHighAltitudeNames"
>
<template #suffix>
@ -409,7 +411,7 @@
:class="{ 'hide-required': index !== 0 }"
>
<template #label>
<span v-if="index == 0">工作量</span>
<span v-if="index == 0">实际完成工作内容</span>
<span v-else style="visibility: hidden">工作量</span>
</template>
<el-select
@ -648,7 +650,7 @@ const calculateCompletionPercentage = (actualWorkload, plannedWorkload) => {
const percentage = (actual / planned) * 100
const roundedPercentage = Math.round(percentage * 100) / 100
return roundedPercentage
return roundedPercentage > 100 ? 100 : roundedPercentage
} catch (error) {
console.error('计算完成比例时出错:', error)
return null
@ -911,8 +913,8 @@ const onCancelActualCompletion = () => {
...props.formData,
actualHighAltitudePersonnelList: [],
actualGroundPersonnelList: [],
actualSkilledWorkerNum: null,
actualAuxiliaryWorkerNum: null,
actualProficientPersonnel: null,
actualAssistancePersonnel: null,
actualLongTimeCar: null,
actualTemporaryCar: null,
actualSubCar: null,
@ -960,6 +962,9 @@ defineExpose({
actualFormRef.value.scrollToField(prop)
}
},
showActualCompletionForm: () => {
showActualCompletion.value = true
},
})
</script>

View File

@ -12,6 +12,7 @@
size="large"
label-width="140"
:disabled="isDetail"
:validate-on-rule-change="false"
>
<el-row :gutter="24">
<el-col :span="12">
@ -109,10 +110,11 @@
size="large"
label-width="140"
:disabled="isDetail"
:validate-on-rule-change="false"
>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="实际入作业人员" prop="actualPersonnelList">
<el-form-item label="实际入作业人员" prop="actualPersonnelList">
<el-input
:model-value="selectedActualManagerNames"
placeholder="请选择作业人员"
@ -349,7 +351,8 @@ const calculateCompletionPercentage = (actualWorkload, plannedWorkload) => {
const roundedPercentage = Math.round(percentage * 100) / 100
// 100%100%
return roundedPercentage
return roundedPercentage > 100 ? 100 : roundedPercentage
} catch (error) {
console.error('计算完成比例时出错:', error)
return null
@ -485,8 +488,8 @@ const onCancelActualCompletion = () => {
const clearedData = {
...props.formData,
actualPersonnelList: [],
proposedLongTimeCar: null,
proposedTemporaryCar: null,
actualLongTimeCar: null,
actualTemporaryCar: null,
actualWorkContent: '',
actualWorkload: null,
completionPercentage: null,
@ -524,6 +527,9 @@ defineExpose({
actualFormRef.value.scrollToField(prop)
}
},
showActualCompletionForm: () => {
showActualCompletion.value = true
},
})
</script>

View File

@ -23,6 +23,20 @@
:action-columns="actionColumns"
:defaultQueryParams="{ dayPlanType: tableType }"
>
<template #proposedLongTimeCar="{ row }">
<span v-if="row.proposedLongTimeCar && row.proposedTemporaryCar">
长租车{{ row.proposedLongTimeCar }}
<br />
临租车{{ row.proposedTemporaryCar }}
</span>
</template>
<template #actualLongTimeCar="{ row }">
<span v-if="row.actualLongTimeCar && row.actualTemporaryCar">
长租车{{ row.actualLongTimeCar }}
<br />
临租车{{ row.actualTemporaryCar }}
</span>
</template>
<template #toolbar>
<ComButton type="primary" icon="Plus" @click="onHandleAdd">新增日计划</ComButton>
<ComButton
@ -50,8 +64,8 @@
</template>
<script setup name="MonthlyPlan">
import { ref, computed, getCurrentInstance } from 'vue'
import { useRouter } from 'vue-router'
import { ref, computed, getCurrentInstance, onMounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { listDailyPlanAPI, delDailyPlanAPI, addDailyPlanAPI } from '@/api/planMange/dailyPlan.js'
import useDictStore from '@/store/modules/dict'
import { selectDictLabel } from '@/utils/ruoyi'
@ -63,6 +77,7 @@ import ComDialog from '@/components/ComDialog/index.vue'
import AddForm from './addForm.vue'
const router = useRouter()
const route = useRoute()
const { proxy } = getCurrentInstance()
const dictStore = useDictStore()
@ -76,7 +91,16 @@ const {
const comTableRef = ref(null)
const addFormRef = ref(null)
const tableType = ref('0')
const tableType = ref(route.query.dayPlanType || '0')
onMounted(() => {
if (route.query.dayPlanType) {
tableType.value = route.query.dayPlanType
}
})
//
const { plan_risk_level } = proxy.useDict('plan_risk_level')
// 使
const formColumns = computed(() => buildFormColumns())
@ -87,7 +111,7 @@ const createDynamicDictFormatter = (dictType, fieldName = null) => {
const value = fieldName ? row[fieldName] : cellValue
// store
const dictData = dictStore.getDict(dictType) || []
return selectDictLabel(dictData, value)
return selectDictLabel(dictData, value) || value
}
}
@ -105,9 +129,36 @@ const tableColumns = computed(() => {
})
})
// tableColumns_2 tableType
const processedTableColumns_2 = computed(() => {
return tableColumns_2.map((column) => {
//
if (column.label === '实际完成工作内容') {
return {
...column,
formatter: (row) => {
// type === '1'使 actualWorkloadList
if (tableType.value === '1') {
return (
row.workloadList?.map((item) => item.workloadCategoryName).join(',') ||
''
)
}
// type === '2'使 actualWorkContent
if (tableType.value === '2') {
return row.actualWorkContent || ''
}
return ''
},
}
}
return column
})
})
const initTableColumns = computed(() => {
if (tableType.value === '0') return [...tableColumns.value, ...tableColumns_1]
if (tableType.value !== '0') return [...tableColumns.value, ...tableColumns_2]
if (tableType.value !== '0') return [...tableColumns.value, ...processedTableColumns_2.value]
})
//

View File

@ -58,6 +58,10 @@ export const tableColumns = [
prop: 'riskLevel',
label: '风险等级',
},
{
prop: 'remark',
label: '备注',
},
]
export const dialogConfig = reactive({

View File

@ -15,6 +15,10 @@
<ComButton type="info" icon="Upload" pain @click="onHandleImport">
导入计划
</ComButton>
<ComButton type="info" icon="Download" pain @click="onHandleDownloadTemplate">
模板下载
</ComButton>
</template>
</ComTable>
@ -207,6 +211,11 @@ const onHandleImport = () => {
console.log('导入计划')
}
//
const onHandleDownloadTemplate = () => {
console.log('模板下载')
}
//
const onCloseDialogOuter = (visible) => {
dialogConfig.outerVisible = visible