Browse Source

奇龙修改

master
shenzhouyu 1 month ago
parent
commit
47f5244e68
  1. 57
      src/api/project/gantt.js
  2. 57
      src/views/modules/project/modules/projectModelForm.vue
  3. 30
      src/views/modules/project/modules/projectModelFormDetail.vue
  4. 26
      src/views/modules/project/modules/projectPartModelTable.vue
  5. 36
      src/views/modules/project/modules/projectPartModelTableDetail.vue
  6. 118
      src/views/modules/project/projectPartIndex.vue
  7. 209
      src/views/modules/project/projectPartProgress.vue

57
src/api/project/gantt.js

@ -12,60 +12,11 @@ export const getProjectGanttData = data => createAPI(`/project/pmprojectpartmode
* @param {Object} data - 查询参数
* @returns {Promise} API响应
*/
export const getGanttLegend = data => createAPI(`/project/gantt/getGanttLegend`, 'get', data);
export const getGanttLegend = data => createAPI(`/project/pmprojectpartmodeldetail/getGanttLegend`, 'get', data);
/**
* 获取项目进度数据
* @param {Object} data - 查询参数
* @returns {Promise} API响应
*/
export const getProjectProgress = data => createAPI(`/project/gantt/getProjectProgress`, 'get', data);
/**
* 更新项目任务进度
* @param {Object} data - 任务数据
* @returns {Promise} API响应
*/
export const updateProjectTask = data => createAPI(`/project/gantt/updateProjectTask`, 'post', data);
/**
* 批量更新项目任务
* @param {Object} data - 批量任务数据
* @returns {Promise} API响应
*/
export const batchUpdateProjectTasks = data => createAPI(`/project/gantt/batchUpdateProjectTasks`, 'post', data);
/**
* 获取项目时间范围
* @param {Object} data - 查询参数
* @returns {Promise} API响应
*/
export const getProjectTimeRange = data => createAPI(`/project/gantt/getProjectTimeRange`, 'get', data);
/**
* 导出项目进度报告
* @param {Object} data - 导出参数
* @returns {Promise} API响应
*/
export const exportProjectProgress = data => createAPI(`/project/gantt/exportProjectProgress`, 'get', data);
/**
* 获取项目任务详情
* @param {Object} data - 查询参数
* @returns {Promise} API响应
*/
export const getProjectTaskDetail = data => createAPI(`/project/gantt/getProjectTaskDetail`, 'get', data);
/**
* 删除项目任务
* @param {Object} data - 删除参数
* @returns {Promise} API响应
*/
export const deleteProjectTask = data => createAPI(`/project/gantt/deleteProjectTask/${data.taskId}`, 'delete', data);
/**
* 获取项目统计信息
* @param {Object} data - 查询参数
* 更新甘特图图例数据
* @param {Object} data - 图例列表 [{ label, color }, ...]
* @returns {Promise} API响应
*/
export const getProjectStatistics = data => createAPI(`/project/gantt/getProjectStatistics`, 'get', data);
export const updateGanttLegend = data => createAPI(`/project/pmprojectpartmodeldetail/updateGanttLegend`, 'post', data);

57
src/views/modules/project/modules/projectModelForm.vue

@ -4,18 +4,23 @@
width="600px">
<el-form ref="saveForm" :model="model" :rules="saveRules" label-position="top" label-width="100px">
<el-row :gutter="10">
<el-col :span="24">
<el-col :span="18">
<el-form-item label="内容描述" prop="itemDesc" :show-message="false">
<el-input v-model="model.itemDesc" disabled></el-input>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="时间(天)" prop="daysNumber" :show-message="false">
<el-input v-model="model.daysNumber" :disabled="disabled" @input=" value=>model.daysNumber= value.match(/^[1-9]\d*$/) ? value.match(/^[1-9]\d*$/)[0] : ''" @change="calculatePlanEndDate"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="8">
<!-- <el-col :span="8">
<el-form-item label="时间(天)" prop="daysNumber" :show-message="false">
<el-input v-model="model.daysNumber" :disabled="disabled" @input=" value=>model.daysNumber= value.match(/^[1-9]\d*$/) ? value.match(/^[1-9]\d*$/)[0] : ''"></el-input>
</el-form-item>
</el-col>
</el-col> -->
<el-col :span="8">
<el-form-item label="完成进度" prop="completionProgress" :show-message="false">
<el-select v-model="model.completionProgress" :disabled="disabled" style="width: 100%">
@ -23,6 +28,12 @@
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="计划开始日期" prop="planStartDate" :show-message="false">
<el-date-picker v-model="model.planStartDate" type="date" value-format='yyyy-MM-dd' format='yyyy-MM-dd'
style="width: 98%;" :disabled="planStartDateDisabled" @change="calculatePlanEndDate"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="计划完成日期" prop="planEndDate" :show-message="false">
<el-date-picker v-model="model.planEndDate" type="date" value-format='yyyy-MM-dd' format='yyyy-MM-dd'
@ -81,6 +92,7 @@ import { userList } from '../../../../api/user.js'
import { getRoleByUserId } from '@/api/role.js'
import UserChooseComponent from '../../../../components/selector/user/userChooseComponent.vue'
import { updateProjectPartModel } from '@/api/project/project.js'
import moment from 'moment'
export default {
name: 'projectModelForm',
@ -111,6 +123,7 @@ export default {
objectIDs: [],
userSiteList: [],
planEndDateDisabled: false,
planStartDateDisabled: false,
progressOptions: [
{ value: 0, label: '0%' },
{ value: 50, label: '50%' },
@ -124,10 +137,18 @@ export default {
trigger: ['blur', 'change'],
},
],
planStartDate: [
{
required: true,
message: '请选择计划开始日期',
trigger: ['blur', 'change'],
},
],
planEndDate: [
{
required: true,
message: '请选择计划完成时间',
message: '请选择计划完成日期',
trigger: ['blur', 'change'],
},
],
@ -352,6 +373,7 @@ export default {
},
getRoleByUserId(){
this.planEndDateDisabled = false
this.planStartDateDisabled = false
if (this.$store.state.user.id === 1) {
return
}
@ -363,7 +385,9 @@ export default {
let hasManager = res.data.roles.includes('manager')
if(!hasManager && this.model.planEndDate) {
this.planEndDateDisabled = true
this.planStartDateDisabled = true
}else {
this.planStartDateDisabled = false
this.planEndDateDisabled = false
}
} else {
@ -374,6 +398,31 @@ export default {
})
},
calculatePlanEndDate() {
if (this.model.planStartDate && this.model.daysNumber) {
const planEndDate = this.addDays(this.model.planStartDate, this.model.daysNumber, 'add')
this.$set(this.model, 'planEndDate', planEndDate)
} else if (!this.model.planStartDate || !this.model.daysNumber) {
//
this.$set(this.model, 'planEndDate', '')
}
this.handleActualDateChange(this.model.excalCompletionDate)
},
addDays(dateString, daysToAdd, type) {
//
let date = new Date(dateString)
//
if (type == 'add') {
date.setDate(date.getDate() + parseInt(daysToAdd))
} else {
date.setDate(date.getDate() - parseInt(daysToAdd))
}
const convertedDate = moment(date).format('YYYY-MM-DD')
console.log('dfsys', convertedDate)
//
return convertedDate
},
//
handleActualDateChange(actualDate) {
if (actualDate && this.model.planEndDate) {

30
src/views/modules/project/modules/projectModelFormDetail.vue

@ -12,7 +12,7 @@
<el-col :span="8">
<el-form-item label="时间(天)" prop="detailDaysNumber" :show-message="false">
<el-input v-model="model.detailDaysNumber" :disabled="disabled"
@input=" value=>model.detailDaysNumber= value.match(/^[1-9]\d*$/) ? value.match(/^[1-9]\d*$/)[0] : ''"></el-input>
@input=" value=>{model.detailDaysNumber= value.match(/^[1-9]\d*$/) ? value.match(/^[1-9]\d*$/)[0] : '';calculatePlanEndDate}"></el-input>
</el-form-item>
</el-col>
</el-row>
@ -28,7 +28,7 @@
<el-col :span="8">
<el-form-item label="计划开始日期" prop="detailPlanStartDate" :show-message="false">
<el-date-picker v-model="model.detailPlanStartDate" type="date" value-format='yyyy-MM-dd'
format='yyyy-MM-dd' style="width: 98%;"></el-date-picker>
format='yyyy-MM-dd' style="width: 98%;" @change="calculatePlanEndDate"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="8">
@ -89,6 +89,7 @@ import { userList } from '../../../../api/user.js'
import { getRoleByUserId } from '@/api/role.js'
import UserChooseComponent from '../../../../components/selector/user/userChooseComponent.vue'
import { updateProjectModelDetail } from '@/api/project/project.js'
import moment from 'moment'
export default {
name: 'projectModelFormDetail',
@ -388,6 +389,31 @@ export default {
})
},
calculatePlanEndDate() {
if (this.model.detailPlanStartDate && this.model.detailDaysNumber) {
const planEndDate = this.addDays(this.model.detailPlanStartDate, this.model.detailDaysNumber, 'add')
this.$set(this.model, 'detailPlanEndDate', planEndDate)
} else if (!this.model.detailPlanStartDate || !this.model.detailDaysNumber) {
//
this.$set(this.model, 'detailPlanEndDate', '')
}
this.handleActualDateChange(this.model.detailExcalCompletionDate)
},
addDays(dateString, daysToAdd, type) {
//
let date = new Date(dateString)
//
if (type == 'add') {
date.setDate(date.getDate() + parseInt(daysToAdd))
} else {
date.setDate(date.getDate() - parseInt(daysToAdd))
}
const convertedDate = moment(date).format('YYYY-MM-DD')
console.log('dfsys', convertedDate)
//
return convertedDate
},
//
handleActualDateChange(actualDate) {
if (actualDate && this.model.detailPlanEndDate) {

26
src/views/modules/project/modules/projectPartModelTable.vue

@ -1,11 +1,11 @@
<template>
<div style="height: 100%;overflow: auto;margin-top: 5px">
<el-button type="primary" @click="addProjectPart()">新增</el-button>
<el-button type="primary" @click="addProjectPart()" :disabled="editBatchVisible">新增</el-button>
<el-button v-if="!editBatchVisible" @click="editBatchModel">批量编辑</el-button>
<el-button v-if="editBatchVisible" @click="batchModel" :loading="batchLoading">保存</el-button>
<el-button v-if="editBatchVisible" @click="cancelBatchEdit">取消</el-button>
<el-button type="primary" @click="exportProjectManagementItems">导出项目管理事项</el-button>
<el-button type="primary" @click="exportProjectManagementItems" :disabled="editBatchVisible">导出项目管理事项</el-button>
<el-table :data="projectPartModel" border v-loading="queryLoading" style="width: 100%;margin-top: 5px"
:height="height" class="itemListClass">
@ -108,9 +108,9 @@
</el-table-column>
<el-table-column header-align="center" align="center" width="140" label="操作">
<template slot-scope="scope">
<el-link style="cursor: pointer" @click="editPart(scope.row)">修改</el-link>
<el-link style="cursor: pointer" @click="removeProjectPart(scope.row)">删除</el-link>
<el-link style="cursor: pointer" @click="updateFile(scope.row)">上传</el-link>
<el-link style="cursor: pointer" @click="editPart(scope.row)" :disabled="editBatchVisible">修改</el-link>
<el-link style="cursor: pointer" @click="removeProjectPart(scope.row)" :disabled="editBatchVisible">删除</el-link>
<el-link style="cursor: pointer" @click="updateFile(scope.row)" :disabled="editBatchVisible">上传</el-link>
<!-- <el-link style="cursor: pointer"
@click="incomeActual(scope.row)">开销详情</el-link> -->
</template>
@ -177,6 +177,16 @@ export default {
default: false,
},
},
watch: {
editBatchVisible(val) {
this.$emit('batch-edit-change', !!val)
},
},
beforeDestroy() {
if (this.editBatchVisible) {
this.$emit('batch-edit-change', false)
}
},
data() {
return {
saveLoading: false,
@ -246,7 +256,7 @@ export default {
columnProp: 'planStartDate',
headerAlign: 'center',
align: 'center',
columnLabel: '计划开始时间',
columnLabel: '计划开始日期',
columnHidden: false,
columnImage: false,
columnSortable: false,
@ -608,6 +618,7 @@ export default {
editBatchModel() {
if (this.editBatchVisible) {
this.editBatchVisible = false
this.$emit('batch-edit-change', false)
} else {
//
if (this.userList.length === 0) {
@ -623,6 +634,7 @@ export default {
}
})
this.editBatchVisible = true
this.$emit('batch-edit-change', true)
}
},
cancelBatchEdit() {
@ -647,6 +659,7 @@ export default {
}
// 退
this.editBatchVisible = false
this.$emit('batch-edit-change', false)
//
this.originalProjectPartModel = []
},
@ -669,6 +682,7 @@ export default {
if (data && data.code === 0) {
this.$message.success(data.msg)
this.editBatchVisible = false
this.$emit('batch-edit-change', false)
//
this.originalProjectPartModel = []
this.$emit('partFinished')

36
src/views/modules/project/modules/projectPartModelTableDetail.vue

@ -28,7 +28,7 @@
</el-col> -->
<el-col :span="4">
<el-form-item label=" ">
<el-button type="primary" @click="addProjectPart()" :disabled="isAllVisiable">新增</el-button>
<el-button type="primary" @click="addProjectPart()" :disabled="isAllVisiable || editBatchVisible">新增</el-button>
<el-button v-if="!editBatchVisible" @click="editBatchModel" :disabled="isAllVisiable">批量编辑</el-button>
<el-button v-if="editBatchVisible" @click="batchModel" :loading="batchLoading" :disabled="isAllVisiable">保存</el-button>
<el-button v-if="editBatchVisible" @click="cancelBatchEdit" :disabled="isAllVisiable">取消</el-button>
@ -49,7 +49,7 @@
<template v-if="item.columnProp==='detailDaysNumber'">
<el-input :controls="false" :ref="`detailDaysNumber${scope.$index}`" v-model="scope.row.detailDaysNumber"
@keyup.enter.native="focusNextInput(scope.$index, 'detailDaysNumber')"
@input=" value=>scope.row.detailDaysNumber= value.match(/^[1-9]\d*$/) ? value.match(/^[1-9]\d*$/)[0] : ''"
@input=" value=>{scope.row.detailDaysNumber= value.match(/^[1-9]\d*$/) ? value.match(/^[1-9]\d*$/)[0] : '';calculatePlanEndDate(scope.$index)}"
style="height: 11px; width: 98%;"></el-input>
<!-- :disabled="scope.row.detailCompletionStatus !== '0' && scope.row.detailCompletionStatus !== '1'" -->
</template>
@ -69,7 +69,7 @@
</template>
<template v-else-if="item.columnProp==='detailPlanStartDate'">
<el-date-picker :ref="`detailPlanStartDate${scope.$index}`" v-model="scope.row.detailPlanStartDate" type="date"
value-format='yyyy-MM-dd' format='yyyy-MM-dd' style="width: 98%;" :clearable="false"></el-date-picker>
value-format='yyyy-MM-dd' format='yyyy-MM-dd' style="width: 98%;" @change="calculatePlanEndDate(scope.$index)" :clearable="false"></el-date-picker>
</template>
<template v-else-if="item.columnProp === 'detailCompletionProgress'">
<el-select
@ -131,9 +131,9 @@
</el-table-column>
<el-table-column fixed="right" header-align="center" align="center" width="120" label="操作">
<template slot-scope="scope">
<el-link style="cursor: pointer" @click="editPart(scope.row)">修改</el-link>
<el-link style="cursor: pointer" @click="removeProjectPart(scope.row)">删除</el-link>
<el-link style="cursor: pointer" @click="updateFile(scope.row)">上传</el-link>
<el-link style="cursor: pointer" @click="editPart(scope.row)" :disabled="editBatchVisible || isAllVisiable">修改</el-link>
<el-link style="cursor: pointer" @click="removeProjectPart(scope.row)" :disabled="editBatchVisible || isAllVisiable">删除</el-link>
<el-link style="cursor: pointer" @click="updateFile(scope.row)" :disabled="editBatchVisible || isAllVisiable">上传</el-link>
<!-- <el-link style="cursor: pointer"
@click="incomeActual(scope.row)">开销详情</el-link> -->
</template>
@ -197,6 +197,16 @@ export default {
default: false,
},
},
watch: {
editBatchVisible(val) {
this.$emit('batch-edit-change', !!val)
},
},
beforeDestroy() {
if (this.editBatchVisible) {
this.$emit('batch-edit-change', false)
}
},
data() {
return {
isAll: false,
@ -638,6 +648,7 @@ export default {
editBatchModel() {
if (this.editBatchVisible) {
this.editBatchVisible = false
this.$emit('batch-edit-change', false)
} else {
//
if (this.userList.length === 0) {
@ -653,6 +664,7 @@ export default {
}
})
this.editBatchVisible = true
this.$emit('batch-edit-change', true)
}
},
cancelBatchEdit() {
@ -677,6 +689,7 @@ export default {
}
// 退
this.editBatchVisible = false
this.$emit('batch-edit-change', false)
//
this.originalProjectPartModel = []
},
@ -707,6 +720,7 @@ export default {
if (data && data.code === 0) {
this.$message.success(data.msg)
this.editBatchVisible = false
this.$emit('batch-edit-change', false)
//
this.originalProjectPartModel = []
//this.getAllModelHeaderCode()
@ -877,6 +891,16 @@ export default {
})
},
calculatePlanEndDate(index) {
const row = this.projectPartModel[index]
if (row.detailPlanStartDate && row.detailDaysNumber) {
const planEndDate = this.addDays(row.detailPlanStartDate, row.detailDaysNumber, 'add')
this.$set(row, 'detailPlanEndDate', planEndDate)
} else if (!row.detailPlanStartDate || !row.detailDaysNumber) {
//
this.$set(row, 'detailPlanEndDate', '')
}
},
//
getPartStatusLabel(status) {
const statusDict = this.dict.type.function_project_part_model_status

118
src/views/modules/project/projectPartIndex.vue

@ -45,8 +45,8 @@
</el-col>
<el-col :span="3">
<el-form-item label=" ">
<el-button type="primary" @click="getDataListAll"> </el-button>
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
<el-button type="primary" @click="getDataListAll" :disabled="isBatchEditing"> </el-button>
<el-button icon="el-icon-refresh" @click="resetQuery" :disabled="isBatchEditing">重置</el-button>
</el-form-item>
</el-col>
</el-row>
@ -77,10 +77,10 @@
</el-table-column>
<el-table-column fixed="right" header-align="center" align="center" width="180" label="操作">
<template slot-scope="scope">
<el-link v-if="!scope.row.isModelFlag" style="cursor: pointer" @click="copyModel(scope.row)">复制</el-link>
<el-link style="cursor: pointer" @click="handleUpdate(scope.row)">编辑</el-link>
<el-link v-if="!scope.row.isModelFlag" style="cursor: pointer" @click="copyModel(scope.row)" :disabled="isBatchEditing">复制</el-link>
<el-link style="cursor: pointer" @click="handleUpdate(scope.row)" :disabled="isBatchEditing">编辑</el-link>
<!-- <el-link style="cursor: pointer" v-if="scope.row.partStatus == '0'" @click="updateProjectPartStatus(scope.row)">下达</el-link> -->
<el-link v-if="!scope.row.isModelFlag" style="cursor: pointer" @click="handleModal(scope.row)">新增模具</el-link>
<el-link v-if="!scope.row.isModelFlag" style="cursor: pointer" @click="handleModal(scope.row)" :disabled="isBatchEditing">新增模具</el-link>
<!-- <el-link style="cursor: pointer" @click="handleExport(scope.row)">导出</el-link> -->
<!-- <el-link style="cursor: pointer" @click="deleteProject(scope.row)">删除</el-link> -->
</template>
@ -90,24 +90,31 @@
<!-- 分页插件 -->
<el-pagination style="margin-top: 0px" @size-change="sizeChangeHandle" @current-change="currentChangeHandle"
:current-page="pageIndex" :page-sizes="[20, 50, 100, 200, 500]" :page-size="pageSize" :total="totalPage"
layout="total, sizes, prev, pager, next, jumper">
layout="total, sizes, prev, pager, next, jumper" :disabled="isBatchEditing">
</el-pagination>
<el-tabs style="margin-top: 0px; width: 100%; height: 100%;font-size: 14px;" v-model="activeTable"
class="customer-tab" type="border-card" @tab-click="tabClick">
<el-tab-pane label="项目管理事项" name="projectPartProperty">
class="customer-tab" type="border-card" @tab-click="tabClick" :before-leave="beforeLeaveTab">
<el-tab-pane label="项目管理事项" name="projectPartProperty"
:disabled="isBatchEditing && activeTable !== 'projectPartProperty'">
<projectPartModelTable :projectPartModel="projectPartModel" :projectPart="model"
@partFinished="getProjectPartModelList" :auth-flag="true" :height="'33vh'"></projectPartModelTable>
@partFinished="getProjectPartModelList"
@batch-edit-change="onBatchEditChange('projectPartProperty', $event)"
:auth-flag="true" :height="'33vh'"></projectPartModelTable>
</el-tab-pane>
<el-tab-pane label="模具开发进度" name="projectPartModel">
<el-tab-pane label="模具开发进度" name="projectPartModel"
:disabled="isBatchEditing && activeTable !== 'projectPartModel'">
<ProjectPartModelTableDetail ref="projectPartModelTableDetail" :projectPartModel="projectPartModel"
@partFinished="getProjectPartModelList" @change="onModelFlagChange" :auth-flag="true" :height="'33vh'"></ProjectPartModelTableDetail>
@partFinished="getProjectPartModelList" @change="onModelFlagChange"
@batch-edit-change="onBatchEditChange('projectPartModel', $event)"
:auth-flag="true" :height="'33vh'"></ProjectPartModelTableDetail>
<!-- <oss-components ref="inquiryDocument" label="申请单号" style="margin-top: 5px" height="44vh" :columns="ossColumns"
:disabled="false" :orderRef1="model.site" :orderRef2="model.objectId" :rfqNo="model.projectCode"
:orderRef5="model.projectId">
</oss-components> -->
</el-tab-pane>
<el-tab-pane label="相关文档" name="inquiryDocument">
<el-tab-pane label="相关文档" name="inquiryDocument"
:disabled="isBatchEditing && activeTable !== 'inquiryDocument'">
<div style="height: 100%;overflow: auto;">
<oss-components ref="inquiryDocument" label="申请单号" style="margin-top: 5px" height="44vh" :columns="ossColumns"
:disabled="false" :orderRef1="model.site" :orderRef2="model.projectPartId" :fileTypeCode="1" :rfqNo="model.projectCode"
@ -147,7 +154,14 @@ export default {
},
dicts: ['function_project_part_status'],
name: 'projectPartIndex',
computed: {},
computed: {
isBatchEditing() {
return !!(
(this.batchEditLocks && this.batchEditLocks.projectPartProperty) ||
(this.batchEditLocks && this.batchEditLocks.projectPartModel)
)
},
},
components: {
ProjectPartModelTable,
OssComponents,
@ -337,6 +351,13 @@ export default {
reviewFlag: false,
//
activeTable: 'projectPartProperty',
lastActiveTable: 'projectPartProperty',
tabRollbacking: false,
batchEditLocks: {
projectPartProperty: false,
projectPartModel: false,
},
batchEditLockedTab: '',
// ======== ========
modalData: {
flag: '',
@ -687,7 +708,46 @@ export default {
this.getDataList()
},
watch: {
activeTable(newVal, oldVal) {
if (this.tabRollbacking) return
// tab
if (!this.isBatchEditing) {
this.lastActiveTable = newVal
return
}
// tabtab
const target = this.batchEditLockedTab || oldVal || this.lastActiveTable
if (target && newVal !== target) {
this.tabRollbacking = true
this.$message.warning('批量编辑中,请先保存或取消后再切换页签')
this.$nextTick(() => {
this.activeTable = target
this.tabRollbacking = false
})
}
},
},
methods: {
onBatchEditChange(source, val) {
if (!this.batchEditLocks) return
this.$set(this.batchEditLocks, source, !!val)
if (!!val) {
// tab
this.batchEditLockedTab = this.activeTable
} else if (!this.isBatchEditing) {
// 退
this.batchEditLockedTab = ''
}
},
beforeLeaveTab(activeName, oldActiveName) {
if (this.isBatchEditing) {
this.$message.warning('批量编辑中,请先保存或取消后再切换页签')
return false
}
return true
},
handleColumnResize(newWidth, oldWidth, column, event) {
let inData = this.columnList.filter(
(item) => item.columnProp === column.property
@ -705,6 +765,10 @@ export default {
* @param val
*/
sizeChangeHandle(val) {
if (this.isBatchEditing) {
this.$message.warning('批量编辑中,请先保存或取消')
return
}
this.pageSize = val
this.pageIndex = 1
this.getDataList()
@ -714,6 +778,10 @@ export default {
* @param val
*/
currentChangeHandle(val) {
if (this.isBatchEditing) {
this.$message.warning('批量编辑中,请先保存或取消')
return
}
this.pageIndex = val
this.getDataList()
},
@ -725,6 +793,13 @@ export default {
* @param event
*/
tabClick(tab, event) {
if (this.isBatchEditing) {
// before-leave disabled
this.$message.warning('批量编辑中,请先保存或取消后再切换页签')
const target = this.batchEditLockedTab || this.lastActiveTable
if (target) this.activeTable = target
return
}
//
this.refreshCurrentTabTable()
},
@ -735,6 +810,10 @@ export default {
* @param row
*/
projectClickRow(row) {
if (this.isBatchEditing) {
this.$message.warning('批量编辑中,请先保存或取消')
return
}
this.projectCurrentRow = JSON.parse(JSON.stringify(row))
this.model = JSON.parse(JSON.stringify(row))
@ -747,6 +826,7 @@ export default {
* @param oldRow
*/
changeCurrentRow(row, oldRow) {
if (this.isBatchEditing) return
//
if (row) {
this.projectCurrentRow = JSON.parse(JSON.stringify(row))
@ -764,11 +844,19 @@ export default {
* 获取数据列表
*/
getDataListAll() {
if (this.isBatchEditing) {
this.$message.warning('批量编辑中,请先保存或取消')
return
}
this.searchData1 = null
this.getDataList()
},
getDataList() {
if (this.isBatchEditing) {
this.$message.warning('批量编辑中,请先保存或取消')
return
}
//console.log(this.searchData1)
this.searchData.pageSize = this.pageSize
this.searchData.pageNo = this.pageIndex
@ -1102,6 +1190,10 @@ export default {
})
},
resetQuery() {
if (this.isBatchEditing) {
this.$message.warning('批量编辑中,请先保存或取消')
return
}
this.$set(this.searchData, 'startDate', '')
this.$set(this.searchData, 'endDate', '')
this.resetForm('queryForm')

209
src/views/modules/project/projectPartProgress.vue

@ -65,14 +65,46 @@
<!-- 右侧甘特图 -->
<div class="gantt-section" :class="{ 'expanded': isProjectInfoCollapsed }">
<!-- 图例 -->
<div class="legend">
<!-- 图例整块可点击打开管理弹框 -->
<div class="legend" @click="openLegendEdit">
<div class="legend-item" v-for="(item, index) in legendItems" :key="index">
<div class="legend-color" :style="{ backgroundColor: item.color }"></div>
<span class="legend-text">{{ item.label }}</span>
</div>
</div>
<!-- 图例管理弹框表格列表可新增编辑 -->
<el-dialog title="图例管理" :visible.sync="legendEditVisible" width="620px" append-to-body class="legend-edit-dialog">
<div class="legend-dialog-toolbar">
<el-button size="small" type="primary" icon="el-icon-plus" @click="addLegendRow"> </el-button>
</div>
<div class="legend-edit-table-wrap">
<el-table :data="legendTableList" border size="small" class="legend-edit-table">
<el-table-column type="index" label="序号" width="55" align="center" />
<el-table-column label="名称" min-width="140">
<template slot-scope="scope">
<el-input v-model="scope.row.label" placeholder="请输入图例名称" size="mini" clearable />
</template>
</el-table-column>
<el-table-column label="颜色" width="160" align="center">
<template slot-scope="scope">
<el-color-picker v-model="scope.row.color" size="small" />
<span class="legend-table-color-text">{{ scope.row.color }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="80" align="center">
<template slot-scope="scope">
<el-button type="text" size="mini" style="color: #f56c6c;" @click="removeLegendRow(scope.$index)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<span slot="footer" class="dialog-footer">
<el-button size="small" @click="legendEditVisible = false"> </el-button>
<el-button size="small" type="primary" @click="saveLegendList"> </el-button>
</span>
</el-dialog>
<!-- 甘特图时间轴 -->
<div class="gantt-timeline">
<!-- 时间轴头部 -->
@ -123,7 +155,7 @@
</template>
<script>
import { getProjectGanttData, getGanttLegend } from '@/api/project/gantt.js'
import { getProjectGanttData, getGanttLegend, updateGanttLegend } from '@/api/project/gantt.js'
import moment from 'moment'
export default {
@ -218,8 +250,8 @@ export default {
},
},
//
legendItems: [
//
defaultLegendItems: [
{ label: '设计', color: '#ff0000' },
{ label: '材料采购', color: '#00ff00' },
{ label: '机加工', color: '#0000ff' },
@ -230,6 +262,10 @@ export default {
{ label: 'T1试模', color: '#000000' },
{ label: 'OTS试模', color: '#4f6228' },
],
legendItems: [],
//
legendEditVisible: false,
legendTableList: [], // legendItems
//
projectList:[],
@ -637,7 +673,9 @@ export default {
// 使
this.projectList = this.externalProjectList
if (this.externalLegendItems.length > 0) {
this.legendItems = this.externalLegendItems
this.legendItems = JSON.parse(JSON.stringify(this.externalLegendItems))
} else {
this.legendItems = JSON.parse(JSON.stringify(this.defaultLegendItems))
}
if (this.externalUpdateDate) {
this.updateDate = this.externalUpdateDate
@ -661,42 +699,98 @@ export default {
queryParams.endDate = this.dateRange[1]
}
getProjectGanttData(queryParams).then(({ data }) => {
if (data && data.code === 0) {
console.log(data);
this.projectList = data.projectGanttData.projectList
}
})
/* const [ganttData, legendData] = await Promise.all([
const [ganttRes, legendRes] = await Promise.all([
getProjectGanttData(queryParams),
getGanttLegend(),
])
const ganttData = ganttRes && ganttRes.data !== undefined ? ganttRes.data : ganttRes
if (ganttData && ganttData.code === 0) {
this.projectList = ganttData.data.projectList || this.projectList
this.updateDate = ganttData.data.updateDate || this.updateDate
// API
if (ganttData.data.projectStartDate) {
this.projectStartDate = ganttData.data.projectStartDate
}
if (ganttData.data.projectEndDate) {
this.projectEndDate = ganttData.data.projectEndDate
}
const payload = ganttData.projectGanttData || ganttData.data || ganttData
this.projectList = (payload && payload.projectList) || this.projectList || []
}
const legendData = legendRes && legendRes.data !== undefined ? legendRes.data : legendRes
if (legendData && legendData.code === 0) {
this.legendItems = legendData.data || this.legendItems
} */
const list = legendData.data || legendData.list || legendData
if (Array.isArray(list) && list.length > 0) {
this.legendItems = list.map(it => ({ label: it.label || it.name, color: it.color || '#409EFF' }))
} else {
this.legendItems = JSON.parse(JSON.stringify(this.defaultLegendItems))
}
} else {
this.legendItems = JSON.parse(JSON.stringify(this.defaultLegendItems))
}
} catch (error) {
console.error('获取甘特图数据失败:', error)
this.$message.error('获取数据失败,使用默认数据')
this.legendItems = JSON.parse(JSON.stringify(this.defaultLegendItems))
} finally {
this.loading = false
}
},
//
async fetchLegend() {
try {
const res = await getGanttLegend()
const legendData = res && res.data !== undefined ? res.data : res
if (legendData && legendData.code === 0) {
const list = legendData.data || legendData.list || legendData
if (Array.isArray(list) && list.length > 0) {
this.legendItems = list.map(it => ({ label: it.label || it.name, color: it.color || '#409EFF' }))
}
}
} catch (e) {
console.error('获取图例失败:', e)
}
},
// legendItems
openLegendEdit() {
this.legendTableList = this.legendItems.length
? JSON.parse(JSON.stringify(this.legendItems))
: JSON.parse(JSON.stringify(this.defaultLegendItems))
this.legendEditVisible = true
},
//
addLegendRow() {
this.legendTableList.push({ label: '', color: '#409EFF' })
},
//
removeLegendRow(index) {
this.legendTableList.splice(index, 1)
},
// legendItems
async saveLegendList() {
const list = this.legendTableList
.filter(it => it && (it.label || '').trim())
.map(it => ({ label: (it.label || '').trim(), color: it.color || '#409EFF' }))
if (!list.length) {
this.$message.warning('请至少保留一条图例并填写名称')
return
}
// label
const labels = list.map(it => it.label)
const labelSet = new Set(labels)
if (labelSet.size !== labels.length) {
this.$message.warning('图例名称不能重复,请修改后再保存')
return
}
this.legendItems = JSON.parse(JSON.stringify(list))
this.legendEditVisible = false
try {
await updateGanttLegend(this.legendItems)
this.$message.success('保存成功')
} catch (e) {
console.error('保存图例失败:', e)
this.$message.warning('本地已更新,保存到服务器失败,请检查后端接口')
}
},
//
initDefaultDateRange() {
if (!this.dateRange || this.dateRange.length === 0) {
@ -721,6 +815,9 @@ export default {
mounted() {
this.initDefaultDateRange()
if (this.legendItems.length === 0 && this.defaultLegendItems.length > 0) {
this.legendItems = JSON.parse(JSON.stringify(this.defaultLegendItems))
}
this.fetchGanttData()
},
}
@ -885,6 +982,12 @@ export default {
padding: 15px;
border-bottom: 1px solid #eee;
background-color: #fafafa;
cursor: pointer;
border-radius: 4px;
}
.legend:hover {
background-color: rgba(0, 0, 0, 0.06);
}
.legend-item {
@ -893,6 +996,34 @@ export default {
gap: 5px;
}
.legend-dialog-toolbar {
margin-bottom: 12px;
}
.legend-edit-table-wrap {
max-height: 420px;
overflow-y: auto;
margin: 0 -1px;
}
.legend-edit-table .legend-table-color-text {
margin-left: 8px;
font-size: 12px;
color: #606266;
vertical-align: middle;
}
/* 图例弹框:保证内容不溢出、底部按钮始终可见 */
.legend-edit-dialog .el-dialog__body {
padding: 10px 20px 15px;
max-height: 70vh;
overflow: visible;
}
.legend-edit-dialog .el-dialog {
margin-top: 8vh !important;
}
.legend-color {
width: 20px;
height: 15px;
@ -1077,3 +1208,29 @@ export default {
}
}
</style>
<!-- 图例弹框挂到 body需单独样式覆盖全局 table 行高故不加 scoped -->
<style lang="scss">
.legend-edit-dialog .legend-edit-table-wrap .el-table td,
.legend-edit-dialog .legend-edit-table-wrap .el-table th {
padding: 0px 0 !important;
height: 24px !important;
min-height: 24px !important;
}
.legend-edit-dialog .legend-edit-table-wrap .el-table .cell {
height: auto !important;
min-height: 24px !important;
line-height: 1.5 !important;
padding: 1px 1px !important;
}
.legend-edit-dialog .legend-edit-table-wrap .el-table .el-input__inner {
height: 24px !important;
line-height: 24px !important;
}
.legend-edit-dialog .legend-edit-table-wrap .el-table .el-color-picker {
vertical-align: middle;
}
</style>
Loading…
Cancel
Save