feat: 工位时间维护

This commit is contained in:
JiangSheng
2026-01-30 10:45:15 +08:00
parent 01bfee68b9
commit 1ee8bca049
5 changed files with 429 additions and 6 deletions

View File

@@ -0,0 +1,130 @@
<template>
<Dialog
v-model="dialogVisible"
:diaTitle="$t('工位时间维护.批量修改工位时间')"
width="500"
showFooter
>
<TableForm
ref="tableFormRef"
v-model:data="formData"
:tableName="TABLE_NAME.BATCH_UPDATE_WORKSPACE_TIME"
@change="tableFormChangeFun"
/>
<template #footer>
<div>
<el-button @click="dialogVisible = false">{{ $t('通用.取消') }}</el-button>
<el-button type="primary" :loading="loading" @click="confirmFun">{{ $t('通用.确定') }}</el-button>
</div>
</template>
</Dialog>
</template>
<script lang="ts" setup>
import { ref, computed, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import Dialog from '@/components/common/dialog/index.vue';
import TableForm from '@/components/common/table/tableForm.vue';
import { TABLE_NAME } from '@/utils/enum/tableName';
import { batchUpdateWorkspaceExtraApi } from '@/api/project/node';
import { ElMessage } from 'element-plus';
const { t } = useI18n();
interface Props {
visible: boolean;
selectedRows: any[];
currentPhase: any;
}
const props = withDefaults(defineProps<Props>(), {
visible: false,
selectedRows: () => [],
currentPhase: () => null,
});
const emit = defineEmits(['update:visible', 'confirm']);
const dialogVisible = computed({
get: () => props.visible,
set: (val) => emit('update:visible', val),
});
const tableFormRef = ref();
const formData = ref<any>({});
const loading = ref(false);
const tableFormChangeFun = (_data: any) => {};
watch(
() => props.visible,
(val) => {
if (val) {
formData.value = {};
}
}
);
const confirmFun = async () => {
if (props.selectedRows.length === 0) {
ElMessage.warning(t('工位时间维护.请先选择要修改的工位'));
return;
}
const data = formData.value;
const workspaceExtras = props.selectedRows.map((row: any) => {
const extras = [];
if (data.structureRefinementCompletionTime) {
extras.push({
propertyName: 'structureRefinementCompletionTime',
propertyValue: data.structureRefinementCompletionTime,
});
}
if (data.stationUpgradeTime) {
extras.push({
propertyName: 'stationUpgradeTime',
propertyValue: data.stationUpgradeTime,
});
}
if (data.listReleaseTime) {
extras.push({
propertyName: 'listReleaseTime',
propertyValue: data.listReleaseTime,
});
}
return {
workspaceUuid: row.workspaceUuid || row.uuid,
extras,
};
});
if (workspaceExtras.every((item: any) => item.extras.length === 0)) {
ElMessage.warning(t('工位时间维护.请至少填写一个时间字段'));
return;
}
const isDesignPhase = props.currentPhase?.label?.includes('设计') || false;
const syncToTask = !isDesignPhase;
loading.value = true;
try {
const res: any = await batchUpdateWorkspaceExtraApi({
workspaceExtras,
syncToTask,
});
if (res && res.code === 200) {
ElMessage.success(t('工位时间维护.批量修改成功'));
dialogVisible.value = false;
emit('confirm');
}
} catch (error) {
console.error('批量修改失败', error);
} finally {
loading.value = false;
}
};
</script>
<style scoped></style>

View File

@@ -0,0 +1,242 @@
<template>
<BaseTable
ref="baseTableRef"
showIndex
showCheckbox
:tableName="TABLE_NAME.WORKSPACE_TIME"
:params="tableParams"
:api="getDedicatedTimeApi"
@checkboxChange="checkboxChangeFun"
@checkboxAll="checkboxAllFun"
@dataChange="dataChangeFun"
>
<template #leftOptions>
<el-button
type="primary"
icon="edit"
:disabled="selectedRows.length === 0"
@click="openBatchEditDialogFun"
>
{{ $t('工位时间维护.批量修改') }}
</el-button>
<el-form :inline="true">
<el-form-item :label="$t('工位时间维护.阶段') + ''" class="phase-content">
<el-select
v-model="phaseUuid"
class="phase-select"
:placeholder="$t('工位时间维护.请选择阶段')"
@change="phaseChangeFun"
>
<el-option
v-for="item in phaseListOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-form>
</template>
<template #fullName="{ row }"> {{ row.projectCode }}-{{ row.nodeCode }} </template>
<template #structureRefinementCompletionTime="{ row }">
<el-date-picker
v-model="row.structureRefinementCompletionTime"
type="datetime"
format="YYYY-MM-DD HH:mm:ss"
valueFormat="YYYY-MM-DD HH:mm:ss"
:placeholder="$t('通用.请选择时间')"
@change="updateSingleWorkspaceTimeFun(row, 'structureRefinementCompletionTime')"
/>
</template>
<template #stationUpgradeTime="{ row }">
<el-date-picker
v-model="row.stationUpgradeTime"
type="datetime"
format="YYYY-MM-DD HH:mm:ss"
valueFormat="YYYY-MM-DD HH:mm:ss"
:placeholder="$t('通用.请选择时间')"
@change="updateSingleWorkspaceTimeFun(row, 'stationUpgradeTime')"
/>
</template>
<template #listReleaseTime="{ row }">
<el-date-picker
v-model="row.listReleaseTime"
type="datetime"
format="YYYY-MM-DD HH:mm:ss"
valueFormat="YYYY-MM-DD HH:mm:ss"
:placeholder="$t('通用.请选择时间')"
@change="updateSingleWorkspaceTimeFun(row, 'listReleaseTime')"
/>
</template>
</BaseTable>
<BatchUpdateWorkspaceTime
v-model:visible="showBatchEditDialog"
:selectedRows="selectedRows"
:currentPhase="currentPhase"
@confirm="batchEditConfirmFun"
/>
</template>
<script lang="ts" setup>
import { ref, computed, onMounted } from 'vue';
import { useI18n } from 'vue-i18n';
import BaseTable from '@/components/common/table/baseTable.vue';
import { getDedicatedTimeApi, getChildrenNodeListApi, batchUpdateWorkspaceExtraApi } from '@/api/project/node';
import { NODE_TYPE } from '@/utils/enum/node';
import { TABLE_NAME } from '@/utils/enum/tableName';
import { ElMessage } from 'element-plus';
import BatchUpdateWorkspaceTime from './components/batchUpdateWorkspaceTime.vue';
const { t } = useI18n();
interface Props {
projectUuid: string;
}
const props = withDefaults(defineProps<Props>(), {
projectUuid: '',
});
const baseTableRef = ref();
const phaseUuid = ref('');
const phaseListOptions = ref<any[]>([]);
const getPhaseListFun = async () => {
if (!props.projectUuid) {
return;
}
const res: any = await getChildrenNodeListApi({
current: 1,
size: 999,
nodeType: NODE_TYPE.PHASE,
nodeId: props.projectUuid,
});
if (res && res.code === 200) {
phaseListOptions.value = res.data.map((item: { nodeName: string; uuid: string }) => ({
label: item.nodeName,
value: item.uuid,
}));
if (phaseListOptions.value.length && !phaseUuid.value) {
phaseUuid.value = phaseListOptions.value[0].value;
}
} else {
phaseListOptions.value = [];
}
};
const phaseChangeFun = () => {
baseTableRef.value?.resetFun();
};
const tableParams = computed(() => ({
projectUuid: props.projectUuid,
nodeUuid: phaseUuid.value,
}));
const showBatchEditDialog = ref(false);
const selectedRows = ref<any[]>([]);
const currentPhase = computed(() => {
return phaseListOptions.value.find((item) => item.value === phaseUuid.value);
});
const checkboxChangeFun = () => {
const rows = baseTableRef.value?.tableRef?.getCheckboxRecords?.() || [];
selectedRows.value = rows;
};
const checkboxAllFun = () => {
const rows = baseTableRef.value?.tableRef?.getCheckboxRecords?.() || [];
selectedRows.value = rows;
};
const openBatchEditDialogFun = () => {
if (selectedRows.value.length === 0) {
ElMessage.warning(t('工位时间维护.请先选择要修改的工位'));
return;
}
showBatchEditDialog.value = true;
};
const batchEditConfirmFun = () => {
selectedRows.value = [];
baseTableRef.value?.resetFun();
};
const dataChangeFun = () => {
const tableData = baseTableRef.value?.tableData || [];
tableData.forEach((row: any) => {
if (row._timeFieldsProcessed) {
return;
}
if (row.extras && Array.isArray(row.extras)) {
row.extras.forEach((extra: any) => {
if (extra.propertyName === 'structureRefinementCompletionTime') {
row.structureRefinementCompletionTime = extra.propertyValue;
} else if (extra.propertyName === 'stationUpgradeTime') {
row.stationUpgradeTime = extra.propertyValue;
} else if (extra.propertyName === 'listReleaseTime') {
row.listReleaseTime = extra.propertyValue;
}
});
row._timeFieldsProcessed = true;
}
});
};
const updateSingleWorkspaceTimeFun = async (row: any, propertyName: string) => {
const propertyValue = row[propertyName];
if (!propertyValue) {
return;
}
const isDesignPhase = currentPhase.value?.label?.includes('设计') || false;
const syncToTask = !isDesignPhase;
try {
const res: any = await batchUpdateWorkspaceExtraApi({
workspaceExtras: [
{
workspaceUuid: row.uuid,
extras: [
{
propertyName,
propertyValue,
},
],
},
],
syncToTask,
});
if (res && res.code === 200) {
ElMessage.success(t('通用.操作成功'));
baseTableRef.value?.resetFun();
}
} catch (error) {
console.error('更新失败', error);
baseTableRef.value?.resetFun();
}
};
onMounted(() => {
getPhaseListFun();
});
</script>
<style scoped>
.phase-content {
margin-bottom: 0;
margin-left: 12px;
}
.phase-select {
width: 180px;
}
</style>

View File

@@ -25,6 +25,7 @@ const lang = {
: 'Task',
: 'Please Enter ',
: 'Please Select ',
: 'Please select time',
: 'Operation Successful',
: 'Operation Failed',
: 'Time Range',
@@ -305,6 +306,25 @@ const lang = {
: 'Workspace Review Statistics',
: 'Project Task Completion Statistics',
},
: {
: 'Phase',
: 'Please select phase',
: 'Batch Edit',
: 'Batch Update Workspace Time',
: 'Please select workspaces to modify',
: 'Please fill in at least one time field',
: 'Batch update successful',
: 'Workspace Time',
},
: {
: 'Project Detail',
: 'Basic Information',
: 'Scheme Maintenance',
: 'Batch Information',
线: 'Production Line Information',
PDT: 'Project PDT',
: 'Workspace Time',
},
};
export default lang;

View File

@@ -25,6 +25,7 @@ const lang = {
: '任务',
: '请输入',
: '请选择',
: '请选择时间',
: '操作成功',
: '操作失败',
: '时间范围',
@@ -300,6 +301,25 @@ const lang = {
: '工位评审通过统计',
: '项目任务完成情况统计',
},
: {
: '阶段',
: '请选择阶段',
: '批量修改',
: '批量修改工位时间',
: '请先选择要修改的工位',
: '请至少填写一个时间字段',
: '批量修改成功',
: '工位时间维护',
},
: {
: '项目详情',
: '基本信息',
: '方案维护',
: '批次信息',
线: '产线信息',
PDT: '项目PDT',
: '工位时间维护',
},
};
export default lang;

View File

@@ -85,10 +85,10 @@
:freeze="currentProjectInfo.exeStatus === PROJECT_EXE_STATUS_CODE.CLOSED"
/>
</el-tab-pane>
<el-tab-pane label="项目详情" name="projectDetail">
<el-tab-pane :label="$t('项目详情页.项目详情')" name="projectDetail">
<div class="project-detail-content">
<div class="section-block">
<div class="section-title">基本信息</div>
<div class="section-title">{{ $t('项目详情页.基本信息') }}</div>
<baseInfo
ref="basePageRef"
@update:projectInfo="updateProjectInfo"
@@ -98,27 +98,37 @@
</div>
<template v-if="enableConfigByTenant([TENANT_ENUM.LYRIC])">
<div class="section-block">
<div class="section-title">方案维护</div>
<div class="section-title">{{ $t('项目详情页.方案维护') }}</div>
<SchemeMaintain ref="schemeMaintainRef" :nodeId="projectUuid" />
</div>
<div class="section-block">
<div class="section-title">批次信息</div>
<div class="section-title">{{ $t('项目详情页.批次信息') }}</div>
<BatchInfo ref="batchInfoRef" :nodeId="projectUuid" />
</div>
<div class="section-block">
<div class="section-title">产线信息</div>
<div class="section-title">{{ $t('项目详情页.产线信息') }}</div>
<productionLine ref="productionLineRef" :nodeCode="currentProjectInfo.nodeCode" />
</div>
</template>
</div>
</el-tab-pane>
<el-tab-pane v-if="enableConfigByTenant([TENANT_ENUM.LYRIC])" label="项目PDT" name="PDT">
<el-tab-pane v-if="enableConfigByTenant([TENANT_ENUM.LYRIC])" :label="$t('项目详情页.项目PDT')" name="PDT">
<PDT
ref="productionLineRef"
v-if="displayedTabs.includes('PDT') && projectUuid"
:nodeId="projectUuid"
/>
</el-tab-pane>
<el-tab-pane
v-if="enableConfigByTenant([TENANT_ENUM.LYRIC])"
:label="$t('项目详情页.工位时间维护')"
name="workspaceTime"
>
<WorkspaceTime
v-if="displayedTabs.includes('workspaceTime') && projectUuid"
:projectUuid="projectUuid"
/>
</el-tab-pane>
<el-tab-pane label="文件数据" name="projectData">
<DataOverView
v-if="displayedTabs.includes('projectData') && projectUuid"
@@ -179,6 +189,7 @@ import SchemeMaintain from '@/tenants/lyric/views/project/schemeMaintain.vue';
import BatchInfo from '@/tenants/lyric/views/project/batchInfo.vue';
import productionLine from '@/tenants/lyric/views/project/productionLine.vue';
import PDT from '@/tenants/lyric/views/project/PDT.vue';
import WorkspaceTime from '@/tenants/lyric/views/project/workspaceTime.vue';
import { enableConfigByTenant, TENANT_ENUM } from '@/tenants/tenant';
import { disposeAsyncPhase } from '@/tenants/lyric/views/project/project';
import DataOverView from '@/views/data/overview/components/index.vue';