优化混炼示方,新增种类配置
This commit is contained in:
@@ -0,0 +1,221 @@
|
||||
<template>
|
||||
<Popover
|
||||
v-model:open="popoverOpen"
|
||||
trigger="click"
|
||||
placement="bottomRight"
|
||||
:overlayClassName="`${prefixCls}__popover`"
|
||||
@open-change="handleOpenChange"
|
||||
>
|
||||
<template #title>
|
||||
<div :class="`${prefixCls}__title`">
|
||||
<Checkbox :indeterminate="indeterminate" :checked="checkAll" :disabled="loading || !allCategoryIds.length" @change="onCheckAllChange">
|
||||
小类展示
|
||||
</Checkbox>
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<Spin :spinning="loading">
|
||||
<div v-if="!loading && !groupedCategories.length" :class="`${prefixCls}__empty`">
|
||||
暂无物料小类,请确认分类字典 XSLMES_MATERIAL 已配置
|
||||
</div>
|
||||
<div v-else :class="`${prefixCls}__list`">
|
||||
<div v-for="group in groupedCategories" :key="group.majorId" :class="`${prefixCls}__group`">
|
||||
<div :class="`${prefixCls}__group-title`">{{ group.majorName }}</div>
|
||||
<div :class="`${prefixCls}__group-options`">
|
||||
<Checkbox
|
||||
v-for="opt in group.options"
|
||||
:key="opt.value"
|
||||
:checked="isMinorVisible(opt.value)"
|
||||
@change="(e) => onMinorVisibleChange(opt.value, e.target.checked)"
|
||||
>
|
||||
{{ opt.label }}
|
||||
</Checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Spin>
|
||||
<div :class="`${prefixCls}__footer`">
|
||||
<a-button size="small" :disabled="loading || !allCategoryIds.length" @click="handleReset">重置</a-button>
|
||||
<a-button size="small" type="primary" :disabled="loading || !allCategoryIds.length" @click="handleSave">保存</a-button>
|
||||
</div>
|
||||
</template>
|
||||
<a-tooltip title="小类展示设置">
|
||||
<a-button size="small" class="mixing-material-category-setting-btn" :disabled="loading" @click.stop>
|
||||
<Icon icon="ant-design:setting-outlined" />
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</Popover>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, watch, type PropType } from 'vue';
|
||||
import { Popover, Checkbox, Spin } from 'ant-design-vue';
|
||||
import type { CheckboxChangeEvent } from 'ant-design-vue/lib/checkbox/interface';
|
||||
import { Icon } from '/@/components/Icon';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { saveMixingMaterialPickerHiddenCategoryIds, type MixingMaterialPickerCategoryItem } from '../MesXslMixingSpec.data';
|
||||
|
||||
const prefixCls = 'mixing-material-category-setting';
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
const props = defineProps({
|
||||
categories: {
|
||||
type: Array as PropType<MixingMaterialPickerCategoryItem[]>,
|
||||
default: () => [],
|
||||
},
|
||||
hiddenCategoryIds: {
|
||||
type: Array as PropType<string[]>,
|
||||
default: () => [],
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:hiddenCategoryIds', 'change']);
|
||||
|
||||
const popoverOpen = ref(false);
|
||||
const draftVisibleIds = ref<string[]>([]);
|
||||
|
||||
const allCategoryIds = computed(() => (props.categories || []).map((item) => item.id));
|
||||
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A50】选料弹窗小类设置按大类分组展示-----------
|
||||
const groupedCategories = computed(() => {
|
||||
const groupMap = new Map<string, { majorId: string; majorName: string; options: { label: string; value: string }[] }>();
|
||||
(props.categories || []).forEach((item) => {
|
||||
const majorId = item.majorId || 'unknown';
|
||||
const majorName = item.majorName || '其他';
|
||||
const group = groupMap.get(majorId) || { majorId, majorName, options: [] };
|
||||
group.options.push({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
});
|
||||
groupMap.set(majorId, group);
|
||||
});
|
||||
return Array.from(groupMap.values());
|
||||
});
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A50】选料弹窗小类设置按大类分组展示-----------
|
||||
|
||||
const checkAll = computed(() => {
|
||||
const all = allCategoryIds.value;
|
||||
if (!all.length) {
|
||||
return false;
|
||||
}
|
||||
return draftVisibleIds.value.length === all.length;
|
||||
});
|
||||
|
||||
const indeterminate = computed(() => {
|
||||
const total = allCategoryIds.value.length;
|
||||
const checked = draftVisibleIds.value.length;
|
||||
return checked > 0 && checked < total;
|
||||
});
|
||||
|
||||
watch(
|
||||
() => [props.hiddenCategoryIds, props.categories],
|
||||
() => {
|
||||
syncDraftFromHidden();
|
||||
},
|
||||
{ deep: true, immediate: true },
|
||||
);
|
||||
|
||||
function syncDraftFromHidden() {
|
||||
const hidden = new Set((props.hiddenCategoryIds || []).map(String));
|
||||
draftVisibleIds.value = allCategoryIds.value.filter((id) => !hidden.has(String(id)));
|
||||
}
|
||||
|
||||
function handleOpenChange(open: boolean) {
|
||||
popoverOpen.value = open;
|
||||
if (open) {
|
||||
syncDraftFromHidden();
|
||||
}
|
||||
}
|
||||
|
||||
function onCheckAllChange(e: CheckboxChangeEvent) {
|
||||
draftVisibleIds.value = e.target.checked ? [...allCategoryIds.value] : [];
|
||||
}
|
||||
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A50】小类展示分组勾选互不覆盖-----------
|
||||
function isMinorVisible(id: string) {
|
||||
return draftVisibleIds.value.map(String).includes(String(id));
|
||||
}
|
||||
|
||||
function onMinorVisibleChange(id: string, checked: boolean) {
|
||||
const visibleSet = new Set(draftVisibleIds.value.map(String));
|
||||
const key = String(id);
|
||||
if (checked) {
|
||||
visibleSet.add(key);
|
||||
} else {
|
||||
visibleSet.delete(key);
|
||||
}
|
||||
draftVisibleIds.value = allCategoryIds.value.filter((itemId) => visibleSet.has(String(itemId)));
|
||||
}
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A50】小类展示分组勾选互不覆盖-----------
|
||||
|
||||
function handleReset() {
|
||||
draftVisibleIds.value = [...allCategoryIds.value];
|
||||
}
|
||||
|
||||
function handleSave() {
|
||||
const visibleSet = new Set(draftVisibleIds.value.map(String));
|
||||
const hidden = allCategoryIds.value.filter((id) => !visibleSet.has(String(id)));
|
||||
saveMixingMaterialPickerHiddenCategoryIds(hidden);
|
||||
emit('update:hiddenCategoryIds', hidden);
|
||||
emit('change', hidden);
|
||||
popoverOpen.value = false;
|
||||
createMessage.success('小类展示设置已保存');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.mixing-material-category-setting-btn {
|
||||
padding-inline: 8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
.mixing-material-category-setting__popover {
|
||||
.ant-popover-inner-content {
|
||||
width: 320px;
|
||||
max-width: 80vw;
|
||||
}
|
||||
}
|
||||
|
||||
.mixing-material-category-setting__empty {
|
||||
padding: 12px 0;
|
||||
color: var(--text-color-secondary, rgba(0, 0, 0, 0.45));
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.mixing-material-category-setting__list {
|
||||
max-height: 320px;
|
||||
overflow: auto;
|
||||
padding: 4px 0 8px;
|
||||
}
|
||||
|
||||
.mixing-material-category-setting__group + .mixing-material-category-setting__group {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.mixing-material-category-setting__group-title {
|
||||
font-weight: 600;
|
||||
margin-bottom: 6px;
|
||||
color: var(--text-color, rgba(0, 0, 0, 0.88));
|
||||
}
|
||||
|
||||
.mixing-material-category-setting__group {
|
||||
.mixing-material-category-setting__group-options {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.mixing-material-category-setting__footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
padding-top: 8px;
|
||||
border-top: 1px solid var(--border-color-base, #f0f0f0);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,406 @@
|
||||
<template>
|
||||
<BasicModal
|
||||
v-bind="$attrs"
|
||||
title="选择密炼物料"
|
||||
:width="1180"
|
||||
:getContainer="getModalContainer"
|
||||
@register="registerModal"
|
||||
@ok="handleOk"
|
||||
>
|
||||
<div class="mixing-material-picker">
|
||||
<div class="mixing-material-picker-toolbar">
|
||||
<a-input
|
||||
v-model:value="keyword"
|
||||
allow-clear
|
||||
placeholder="关键字(物料编码/名称/描述)"
|
||||
style="width: 280px"
|
||||
@pressEnter="reloadTable"
|
||||
/>
|
||||
<a-button type="primary" @click="reloadTable">搜索</a-button>
|
||||
<MesXslMixingMaterialCategorySetting
|
||||
v-model:hiddenCategoryIds="hiddenCategoryIds"
|
||||
:categories="allMinorCategories"
|
||||
:loading="treeLoading"
|
||||
@change="handleCategoryVisibilityChange"
|
||||
/>
|
||||
</div>
|
||||
<div class="mixing-material-picker-body">
|
||||
<aside class="mixing-material-picker-sider">
|
||||
<div class="mixing-material-picker-sider-title">物料小类</div>
|
||||
<Spin :spinning="treeLoading">
|
||||
<BasicTree
|
||||
:treeData="visibleCategoryTree"
|
||||
:selectedKeys="selectedCategoryKeys"
|
||||
:expandedKeys="expandedCategoryKeys"
|
||||
defaultExpandLevel="2"
|
||||
@update:selectedKeys="onCategorySelect"
|
||||
@update:expandedKeys="onExpandedKeysChange"
|
||||
/>
|
||||
</Spin>
|
||||
</aside>
|
||||
<div class="mixing-material-picker-main">
|
||||
<BasicTable @register="registerTable">
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.dataIndex === 'pickerWeighMode'">
|
||||
<div class="mixing-material-picker-weigh-mode" @click.stop>
|
||||
<JDictSelectTag
|
||||
:value="getPickerWeighMode(record.id)"
|
||||
:dictCode="MIXING_MATERIAL_PICKER_WEIGH_MODE_DICT"
|
||||
:getPopupContainer="getSelectPopupContainer"
|
||||
:showChooseOption="false"
|
||||
placeholder="请选择"
|
||||
popupClassName="mixing-material-picker-weigh-mode-dropdown"
|
||||
style="width: 100%"
|
||||
@change="(val) => setPickerWeighMode(record.id, val)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, ref, watch } from 'vue';
|
||||
import { Spin } from 'ant-design-vue';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { BasicTable, useTable } from '/@/components/Table';
|
||||
import { BasicTree } from '/@/components/Tree';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { loadMesMaterialCategoryTreeData } from '/@/views/system/category/category.constants';
|
||||
import { list as mixerList, queryById as queryMixerById } from '/@/views/mes/material/MesMixerMaterial.api';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue';
|
||||
import MesXslMixingMaterialCategorySetting from './MesXslMixingMaterialCategorySetting.vue';
|
||||
import {
|
||||
applyMixingMaterialFromSelection,
|
||||
loadMixingMaterialPickerHiddenCategoryIds,
|
||||
MIXING_MATERIAL_PICKER_WEIGH_MODE_DICT,
|
||||
mixingMaterialPickerTableColumns,
|
||||
resolveMixingMaterialKindForPicker,
|
||||
sanitizeMixingMaterialPickerHiddenCategoryIds,
|
||||
saveMixingMaterialPickerHiddenCategoryIds,
|
||||
type MixingMaterialPickerCategoryItem,
|
||||
} from '../MesXslMixingSpec.data';
|
||||
import type { KeyType } from '/@/components/Tree/src/types/tree';
|
||||
|
||||
const TREE_ALL = 'ALL';
|
||||
const emit = defineEmits(['register', 'select']);
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
const keyword = ref('');
|
||||
const treeLoading = ref(false);
|
||||
const rawCategoryTree = ref<Recordable[]>([]);
|
||||
const allMajorCategories = ref<Array<{ id: string; name: string; minors: MixingMaterialPickerCategoryItem[] }>>([]);
|
||||
const allMinorCategories = ref<MixingMaterialPickerCategoryItem[]>([]);
|
||||
const hiddenCategoryIds = ref<string[]>(loadMixingMaterialPickerHiddenCategoryIds());
|
||||
const selectedCategoryKeys = ref<KeyType[]>([TREE_ALL]);
|
||||
const expandedCategoryKeys = ref<KeyType[]>([TREE_ALL]);
|
||||
const selectedRow = ref<Recordable | null>(null);
|
||||
const categoryRubberMap = ref<Record<string, boolean>>({});
|
||||
const pickerWeighModeMap = ref<Record<string, string>>({});
|
||||
|
||||
const hiddenCategoryIdSet = computed(() => new Set(hiddenCategoryIds.value.map(String)));
|
||||
|
||||
function getModalContainer() {
|
||||
return document.body;
|
||||
}
|
||||
|
||||
function getSelectPopupContainer() {
|
||||
return document.body;
|
||||
}
|
||||
|
||||
function filterHiddenCategoryTree(nodes: Recordable[], hidden: Set<string>): Recordable[] {
|
||||
return (nodes || [])
|
||||
.map((major) => {
|
||||
const children = (major.children || [])
|
||||
.filter((minor) => !hidden.has(String(minor.key)))
|
||||
.map((minor) => ({
|
||||
key: minor.key,
|
||||
title: minor.title,
|
||||
}));
|
||||
if (!children.length) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
key: major.key,
|
||||
title: major.title,
|
||||
children,
|
||||
};
|
||||
})
|
||||
.filter(Boolean) as Recordable[];
|
||||
}
|
||||
|
||||
const visibleCategoryTree = computed(() => [
|
||||
{
|
||||
key: TREE_ALL,
|
||||
title: '全部小类',
|
||||
children: filterHiddenCategoryTree(rawCategoryTree.value, hiddenCategoryIdSet.value),
|
||||
},
|
||||
]);
|
||||
|
||||
function syncExpandedCategoryKeys() {
|
||||
const keys: KeyType[] = [TREE_ALL];
|
||||
for (const major of visibleCategoryTree.value[0]?.children || []) {
|
||||
keys.push(major.key);
|
||||
}
|
||||
expandedCategoryKeys.value = keys;
|
||||
}
|
||||
|
||||
watch(
|
||||
visibleCategoryTree,
|
||||
() => {
|
||||
syncExpandedCategoryKeys();
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
|
||||
const selectedCategoryFilter = computed(() => {
|
||||
const key = selectedCategoryKeys.value[0];
|
||||
if (!key || key === TREE_ALL) {
|
||||
return {};
|
||||
}
|
||||
const keyStr = String(key);
|
||||
const major = allMajorCategories.value.find((item) => item.id === keyStr);
|
||||
if (major) {
|
||||
return { majorCategoryId: major.id };
|
||||
}
|
||||
return { minorCategoryId: keyStr };
|
||||
});
|
||||
|
||||
const [registerTable, { reload, getSelectRowKeys, getSelectRows, clearSelectedRowKeys }] = useTable({
|
||||
api: mixerList,
|
||||
columns: mixingMaterialPickerTableColumns,
|
||||
rowKey: 'id',
|
||||
useSearchForm: false,
|
||||
pagination: { pageSize: 10 },
|
||||
canResize: false,
|
||||
showIndexColumn: true,
|
||||
immediate: true,
|
||||
beforeFetch: (params) => {
|
||||
const next = { ...params, ...selectedCategoryFilter.value };
|
||||
const kw = keyword.value?.trim();
|
||||
if (kw) {
|
||||
next.materialName = `*${kw}*`;
|
||||
}
|
||||
return next;
|
||||
},
|
||||
rowSelection: {
|
||||
type: 'radio',
|
||||
columnWidth: 48,
|
||||
onChange: (_keys, rows) => {
|
||||
selectedRow.value = rows?.[0] ?? null;
|
||||
},
|
||||
},
|
||||
clickToRowSelect: true,
|
||||
});
|
||||
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A50】选料弹窗打开时初始化(对齐其他SelectModal)-----------
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async () => {
|
||||
await initPickerModal();
|
||||
});
|
||||
|
||||
async function initPickerModal() {
|
||||
selectedRow.value = null;
|
||||
keyword.value = '';
|
||||
pickerWeighModeMap.value = {};
|
||||
clearSelectedRowKeys?.();
|
||||
hiddenCategoryIds.value = loadMixingMaterialPickerHiddenCategoryIds();
|
||||
selectedCategoryKeys.value = [TREE_ALL];
|
||||
setModalProps({ confirmLoading: false });
|
||||
await loadMaterialCategoryTree();
|
||||
reloadTable();
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadMaterialCategoryTree();
|
||||
});
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A50】选料弹窗打开时初始化(对齐其他SelectModal)-----------
|
||||
|
||||
async function loadMaterialCategoryTree() {
|
||||
treeLoading.value = true;
|
||||
try {
|
||||
const { majors, minors, treeNodes } = await loadMesMaterialCategoryTreeData();
|
||||
rawCategoryTree.value = treeNodes;
|
||||
allMajorCategories.value = majors;
|
||||
allMinorCategories.value = minors;
|
||||
|
||||
const sanitizedHidden = sanitizeMixingMaterialPickerHiddenCategoryIds(
|
||||
minors.map((item) => item.id),
|
||||
hiddenCategoryIds.value,
|
||||
);
|
||||
if (sanitizedHidden.length !== hiddenCategoryIds.value.length) {
|
||||
hiddenCategoryIds.value = sanitizedHidden;
|
||||
saveMixingMaterialPickerHiddenCategoryIds(sanitizedHidden);
|
||||
}
|
||||
|
||||
categoryRubberMap.value = {};
|
||||
syncExpandedCategoryKeys();
|
||||
|
||||
if (!minors.length) {
|
||||
createMessage.warning('未加载到物料小类,请确认分类字典根编码 XSLMES_MATERIAL 及其下级分类已配置。');
|
||||
}
|
||||
} catch {
|
||||
rawCategoryTree.value = [];
|
||||
allMajorCategories.value = [];
|
||||
allMinorCategories.value = [];
|
||||
createMessage.warning('加载物料分类树失败,请检查分类根编码 XSLMES_MATERIAL 是否存在。');
|
||||
} finally {
|
||||
treeLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function reloadTable() {
|
||||
reload();
|
||||
}
|
||||
|
||||
function getPickerWeighMode(materialId?: string) {
|
||||
if (!materialId) {
|
||||
return undefined;
|
||||
}
|
||||
return pickerWeighModeMap.value[String(materialId)];
|
||||
}
|
||||
|
||||
function setPickerWeighMode(materialId: string | undefined, value?: string) {
|
||||
if (!materialId) {
|
||||
return;
|
||||
}
|
||||
const key = String(materialId);
|
||||
const next = { ...pickerWeighModeMap.value };
|
||||
if (value == null || value === '') {
|
||||
delete next[key];
|
||||
} else {
|
||||
next[key] = String(value);
|
||||
}
|
||||
pickerWeighModeMap.value = next;
|
||||
}
|
||||
|
||||
function onCategorySelect(keys: KeyType[]) {
|
||||
selectedCategoryKeys.value = keys?.length ? keys : [TREE_ALL];
|
||||
reloadTable();
|
||||
}
|
||||
|
||||
function onExpandedKeysChange(keys: KeyType[]) {
|
||||
expandedCategoryKeys.value = keys?.length ? keys : [TREE_ALL];
|
||||
}
|
||||
|
||||
function handleCategoryVisibilityChange() {
|
||||
const key = selectedCategoryKeys.value[0];
|
||||
if (!key || key === TREE_ALL) {
|
||||
syncExpandedCategoryKeys();
|
||||
reloadTable();
|
||||
return;
|
||||
}
|
||||
const keyStr = String(key);
|
||||
const hidden = hiddenCategoryIdSet.value;
|
||||
const major = allMajorCategories.value.find((item) => item.id === keyStr);
|
||||
if (major) {
|
||||
const hasVisibleMinor = major.minors.some((minor) => !hidden.has(String(minor.id)));
|
||||
if (!hasVisibleMinor) {
|
||||
selectedCategoryKeys.value = [TREE_ALL];
|
||||
}
|
||||
} else if (hidden.has(keyStr)) {
|
||||
selectedCategoryKeys.value = [TREE_ALL];
|
||||
}
|
||||
syncExpandedCategoryKeys();
|
||||
reloadTable();
|
||||
}
|
||||
|
||||
async function resolveKindForMaterial(material: Recordable, weighMode?: string) {
|
||||
const minorId = material?.minorCategoryId ? String(material.minorCategoryId) : '';
|
||||
const minorName = material?.minorCategoryId_dictText || '';
|
||||
if (!minorId) {
|
||||
return resolveMixingMaterialKindForPicker(weighMode, false, minorName);
|
||||
}
|
||||
if (categoryRubberMap.value[minorId] === undefined) {
|
||||
try {
|
||||
const cat = await defHttp.get<Recordable>({ url: '/sys/category/queryById', params: { id: minorId } });
|
||||
categoryRubberMap.value[minorId] = cat?.isRubber === '1' || cat?.isRubber === 1;
|
||||
} catch {
|
||||
categoryRubberMap.value[minorId] = false;
|
||||
}
|
||||
}
|
||||
return resolveMixingMaterialKindForPicker(
|
||||
weighMode,
|
||||
categoryRubberMap.value[minorId] ? '1' : '0',
|
||||
minorName,
|
||||
);
|
||||
}
|
||||
|
||||
async function handleOk() {
|
||||
const keys = (getSelectRowKeys?.() || []) as string[];
|
||||
let row = selectedRow.value || ((getSelectRows?.() || []) as Recordable[])[0];
|
||||
if (!row && keys.length) {
|
||||
try {
|
||||
const raw = await queryMixerById({ id: keys[0] });
|
||||
row = (raw as any)?.id != null ? raw : (raw as any)?.result;
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
if (!row?.id) {
|
||||
createMessage.warning('请选择一条密炼物料');
|
||||
return;
|
||||
}
|
||||
const weighMode = getPickerWeighMode(row.id);
|
||||
const payload: Recordable = { ...row, pickerWeighMode: weighMode };
|
||||
const materialKind = await resolveKindForMaterial(row, weighMode);
|
||||
applyMixingMaterialFromSelection(payload, row, materialKind);
|
||||
emit('select', payload);
|
||||
closeModal();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.mixing-material-picker {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
min-height: 520px;
|
||||
}
|
||||
|
||||
.mixing-material-picker-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.mixing-material-picker-body {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
min-height: 480px;
|
||||
}
|
||||
|
||||
.mixing-material-picker-sider {
|
||||
width: 240px;
|
||||
flex-shrink: 0;
|
||||
border: 1px solid var(--border-color-base, #f0f0f0);
|
||||
border-radius: 4px;
|
||||
padding: 8px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.mixing-material-picker-sider-title {
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.mixing-material-picker-main {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.mixing-material-picker-weigh-mode {
|
||||
min-width: 108px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
/* 下拉挂到 body,避免表格 overflow 裁剪;层级高于 Modal */
|
||||
.mixing-material-picker-weigh-mode-dropdown {
|
||||
z-index: 2100 !important;
|
||||
}
|
||||
</style>
|
||||
@@ -55,7 +55,15 @@
|
||||
<tr>
|
||||
<th class="formTitle" colspan="1">换算系数</th>
|
||||
<td class="formValue" colspan="2">
|
||||
<a-input-number v-model:value="sheetForm.convertFactor" :disabled="!showFooter" :precision="6" :bordered="false" class="form-input" style="width: 100%" />
|
||||
<a-input-number
|
||||
v-model:value="sheetForm.convertFactor"
|
||||
:disabled="!showFooter"
|
||||
:precision="6"
|
||||
:bordered="false"
|
||||
class="form-input"
|
||||
style="width: 100%"
|
||||
@update:value="handleConvertFactorChange"
|
||||
/>
|
||||
</td>
|
||||
<th class="formTitle" colspan="1">填充体积</th>
|
||||
<td class="formValue" colspan="1">
|
||||
@@ -80,7 +88,7 @@
|
||||
</td>
|
||||
<th class="formTitle" colspan="1">母胶比重</th>
|
||||
<td class="formValue">
|
||||
<a-input-number v-model:value="sheetForm.motherRubberSg" :disabled="!showFooter" :precision="6" :bordered="false" class="form-input" style="width: 100%" />
|
||||
<a-input-number v-model:value="sheetForm.motherRubberSg" :disabled="!showFooter" :precision="6" :bordered="false" class="form-input" style="width: 100%" @update:value="recalcFillVolume" />
|
||||
</td>
|
||||
<th class="formTitle">段数</th>
|
||||
<td class="formValue" colspan="2">
|
||||
@@ -104,7 +112,7 @@
|
||||
<tr>
|
||||
<th class="formTitle" colspan="1">终炼胶比重</th>
|
||||
<td class="formValue">
|
||||
<a-input-number v-model:value="sheetForm.finalRubberSg" :disabled="!showFooter" :precision="6" :bordered="false" class="form-input" style="width: 100%" />
|
||||
<a-input-number v-model:value="sheetForm.finalRubberSg" :disabled="!showFooter" :precision="6" :bordered="false" class="form-input" style="width: 100%" @update:value="recalcFillVolume" />
|
||||
</td>
|
||||
<th class="formTitle" colspan="1">适用工厂</th>
|
||||
<td class="formValue" colspan="2">
|
||||
@@ -181,25 +189,60 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="material-table-wrap" :style="{ height: `${materialMainTableHeight}px` }">
|
||||
<JVxeTable
|
||||
:key="materialTableLayoutKey"
|
||||
ref="materialRef"
|
||||
row-number
|
||||
keep-source
|
||||
bordered
|
||||
:fit="false"
|
||||
:column-config="{ resizable: true }"
|
||||
:row-config="materialRowConfig"
|
||||
size="mini"
|
||||
:height="materialMainTableHeight"
|
||||
:scroll-x="{ enabled: false }"
|
||||
:scroll-y="{ enabled: true }"
|
||||
:columns="visibleMaterialColumns"
|
||||
:dataSource="materialData"
|
||||
:disabled="!showFooter"
|
||||
@resizable-change="handleMaterialColumnResize"
|
||||
@column-resizable-change="handleMaterialColumnResize"
|
||||
/>
|
||||
<!--update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A42】橡胶及配合剂明细底部固定合计行----------- -->
|
||||
<div class="material-table-stack" :style="{ width: `${materialTableWidth}px` }">
|
||||
<div class="material-table-body" :style="{ height: `${materialBodyTableHeight}px` }">
|
||||
<JVxeTable
|
||||
:key="materialTableLayoutKey"
|
||||
ref="materialRef"
|
||||
row-number
|
||||
keep-source
|
||||
bordered
|
||||
:fit="false"
|
||||
:column-config="{ resizable: true }"
|
||||
:row-config="materialRowConfig"
|
||||
size="mini"
|
||||
:height="materialBodyTableHeight"
|
||||
:scroll-x="{ enabled: false }"
|
||||
:scroll-y="{ enabled: true }"
|
||||
:columns="visibleMaterialColumns"
|
||||
:dataSource="materialData"
|
||||
:disabled="!showFooter"
|
||||
@value-change="handleMaterialValueChange"
|
||||
@resizable-change="handleMaterialColumnResize"
|
||||
@column-resizable-change="handleMaterialColumnResize"
|
||||
>
|
||||
<template #mixerMaterialNameSlot="{ row }">
|
||||
<div
|
||||
class="mixing-material-name-cell"
|
||||
:class="{ 'is-disabled': !showFooter }"
|
||||
:style="{ minHeight: `${materialHeightPref.rowHeight}px` }"
|
||||
@click.stop="openMixingMaterialPicker(row)"
|
||||
>
|
||||
<span v-if="row.mixerMaterialName" class="mixing-material-name-text">{{ row.mixerMaterialName }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</JVxeTable>
|
||||
</div>
|
||||
<div class="material-table-footer">
|
||||
<div class="material-table-footer-row">
|
||||
<div
|
||||
class="material-footer-seq"
|
||||
:style="{ width: `${MIXING_MATERIAL_ROW_NUMBER_WIDTH}px`, height: `${materialHeightPref.rowHeight}px` }"
|
||||
></div>
|
||||
<div
|
||||
v-for="cell in materialFooterCells"
|
||||
:key="cell.key"
|
||||
class="material-footer-cell"
|
||||
:class="{ 'is-label': cell.isLabel, 'is-total': cell.isTotal }"
|
||||
:style="{ width: `${cell.width}px`, height: `${materialHeightPref.rowHeight}px` }"
|
||||
>
|
||||
{{ cell.text }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A42】橡胶及配合剂明细底部固定合计行----------- -->
|
||||
</div>
|
||||
<!--update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A18】TCU温度条件表移至橡胶及配合剂下方----------- -->
|
||||
<div class="left-panel-section left-panel-section-tcu">
|
||||
@@ -368,11 +411,11 @@
|
||||
</div>
|
||||
|
||||
<BasicForm v-show="false" @register="registerForm" />
|
||||
|
||||
<MesXslEquipmentLedgerSelectModal @register="registerMachineModal" @select="onMachineSelect" />
|
||||
<MesXslMixerPsCompileSelectModal @register="registerIssueNumberModal" @select="onIssueNumberSelect" />
|
||||
</div>
|
||||
</BasicModal>
|
||||
<MesXslEquipmentLedgerSelectModal @register="registerMachineModal" @select="onMachineSelect" />
|
||||
<MesXslMixerPsCompileSelectModal @register="registerIssueNumberModal" @select="onIssueNumberSelect" />
|
||||
<MesXslMixingMaterialSelectModal @register="registerMixingMaterialModal" @select="onMixingMaterialSelect" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@@ -411,6 +454,19 @@ import {
|
||||
DEFAULT_MIXING_STEP_ROW_COUNT,
|
||||
DEFAULT_MIXING_DOWN_STEP_ROW_COUNT,
|
||||
buildDefaultMixingTcuRows,
|
||||
applyMixingMaterialFromSelection,
|
||||
fillMixingMaterialAccumWeight,
|
||||
calcMixingMaterialUnitWeightTotal,
|
||||
calcMixingMaterialAccumWeightTotal,
|
||||
buildMixingMaterialFooterCells,
|
||||
normalizeMixingConvertFactor,
|
||||
initMaterialBaseUnitWeights,
|
||||
applyConvertFactorToMaterialRows,
|
||||
syncMaterialBaseUnitWeightFromDisplay,
|
||||
calcMixingFillVolume,
|
||||
resolveMixingSpecificGravity,
|
||||
MIXING_MATERIAL_ROW_NUMBER_WIDTH,
|
||||
MIXING_MATERIAL_FOOTER_ROW_HEIGHT,
|
||||
MIXING_MATERIAL_MIN_COLUMN_WIDTH,
|
||||
MIXING_TCU_MIN_COLUMN_WIDTH,
|
||||
MIXING_STEP_MIN_COLUMN_WIDTH,
|
||||
@@ -422,7 +478,9 @@ import MesXslMixingStepSelectCell from './MesXslMixingStepSelectCell.vue';
|
||||
import { list as mixerActionList } from '/@/views/xslmes/mesXslMixerAction/MesXslMixerAction.api';
|
||||
import { list as mixerConditionList } from '/@/views/xslmes/mesXslMixerCondition/MesXslMixerCondition.api';
|
||||
import MesXslEquipmentLedgerSelectModal from '/@/views/xslmes/mesXslEquipInspectConfig/components/MesXslEquipmentLedgerSelectModal.vue';
|
||||
import { queryById as queryEquipmentById } from '/@/views/xslmes/mesXslEquipmentLedger/MesXslEquipmentLedger.api';
|
||||
import MesXslMixerPsCompileSelectModal from '/@/views/xslmes/mesXslMixerPsCompile/components/MesXslMixerPsCompileSelectModal.vue';
|
||||
import MesXslMixingMaterialSelectModal from './MesXslMixingMaterialSelectModal.vue';
|
||||
|
||||
const emit = defineEmits(['register', 'success']);
|
||||
const { createMessage } = useMessage();
|
||||
@@ -437,6 +495,7 @@ const mixerConditionOptions = ref<{ title: string; value: string }[]>([]);
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A34】混合步骤动作/组合下拉选项-----------
|
||||
|
||||
const materialRef = ref();
|
||||
const materialPickerRow = ref<Recordable | null>(null);
|
||||
const stepRef = ref();
|
||||
const downStepRef = ref();
|
||||
const tcuRef = ref();
|
||||
@@ -465,6 +524,22 @@ const stepHeightPref = ref(loadMixingTableHeightPreference('step'));
|
||||
const downStepHeightPref = ref(loadMixingTableHeightPreference('downStep'));
|
||||
|
||||
const materialMainTableHeight = computed(() => calcMixingDetailTableViewportHeight('material', materialHeightPref.value));
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A42】橡胶及配合剂明细底部固定合计行-----------
|
||||
const materialBodyTableHeight = computed(() =>
|
||||
Math.max(materialMainTableHeight.value - MIXING_MATERIAL_FOOTER_ROW_HEIGHT, 80),
|
||||
);
|
||||
const materialUnitWeightTotal = ref<number | null>(null);
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A46】换算系数/单重/机台有效体积联动填充体积-----------
|
||||
const machineEffectiveVolume = ref('');
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A46】换算系数/单重/机台有效体积联动填充体积-----------
|
||||
const materialAccumWeightTotal = ref<number | null>(null);
|
||||
const materialFooterCells = computed(() =>
|
||||
buildMixingMaterialFooterCells(visibleMaterialColumns.value, materialColumnWidths.value, {
|
||||
unitWeight: materialUnitWeightTotal.value,
|
||||
accumWeight: materialAccumWeightTotal.value,
|
||||
}),
|
||||
);
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A42】橡胶及配合剂明细底部固定合计行-----------
|
||||
const stepMainTableHeight = computed(() => calcMixingDetailTableViewportHeight('step', stepHeightPref.value));
|
||||
const tcuTableHeight = computed(() => calcMixingDetailTableViewportHeight('tcu', tcuHeightPref.value));
|
||||
const downStepTableHeight = computed(() => calcMixingDetailTableViewportHeight('downStep', downStepHeightPref.value));
|
||||
@@ -509,6 +584,105 @@ function handleMaterialColumnResize(params: Recordable) {
|
||||
};
|
||||
saveMixingMaterialColumnWidths(materialColumnWidths.value);
|
||||
}
|
||||
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A41】橡胶及配合剂明细累计按种类分组合计-----------
|
||||
/** JVxe getTableData 为浅拷贝,批量改值需用 fullData 原行并强制 refresh */
|
||||
function resolveMaterialTableRawRows(): Recordable[] {
|
||||
const fullData = materialRef.value?.getXTable?.()?.getTableData?.()?.fullData as Recordable[] | undefined;
|
||||
if (Array.isArray(fullData) && fullData.length) {
|
||||
return fullData;
|
||||
}
|
||||
return (materialRef.value?.getTableData?.() || materialData.value || []) as Recordable[];
|
||||
}
|
||||
|
||||
function refreshMaterialTableView() {
|
||||
materialRef.value?.getXTable?.()?.updateData?.();
|
||||
}
|
||||
|
||||
function applyMaterialAccumWeight(rows?: Recordable[]) {
|
||||
const targetRows = rows || resolveMaterialTableRawRows();
|
||||
fillMixingMaterialAccumWeight(targetRows);
|
||||
materialUnitWeightTotal.value = calcMixingMaterialUnitWeightTotal(targetRows);
|
||||
materialAccumWeightTotal.value = calcMixingMaterialAccumWeightTotal(targetRows);
|
||||
refreshMaterialTableView();
|
||||
recalcFillVolume();
|
||||
}
|
||||
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A46】换算系数/单重/机台有效体积联动填充体积-----------
|
||||
async function loadMachineEffectiveVolume(machineId?: string) {
|
||||
const id = machineId || sheetForm.machineId;
|
||||
if (!id) {
|
||||
machineEffectiveVolume.value = '';
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const raw = await queryEquipmentById({ id });
|
||||
const row = (raw as Recordable)?.id != null ? raw : (raw as Recordable)?.result;
|
||||
machineEffectiveVolume.value = row?.effectiveVolume || '';
|
||||
} catch {
|
||||
machineEffectiveVolume.value = '';
|
||||
}
|
||||
}
|
||||
|
||||
function recalcFillVolume() {
|
||||
if (!showFooter.value) {
|
||||
return;
|
||||
}
|
||||
const totalWeight =
|
||||
materialUnitWeightTotal.value ?? calcMixingMaterialUnitWeightTotal(resolveMaterialTableRawRows());
|
||||
const specificGravity = resolveMixingSpecificGravity(sheetForm);
|
||||
const next = calcMixingFillVolume(totalWeight, specificGravity, machineEffectiveVolume.value);
|
||||
if (next != null) {
|
||||
sheetForm.fillVolume = next;
|
||||
}
|
||||
}
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A46】换算系数/单重/机台有效体积联动填充体积-----------
|
||||
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A43】换算系数联动明细单重实时计算-----------
|
||||
const lastConvertFactor = ref<number>(1);
|
||||
const convertFactorApplying = ref(false);
|
||||
|
||||
function applyConvertFactorToMaterials(factor: unknown) {
|
||||
const rows = resolveMaterialTableRawRows();
|
||||
applyConvertFactorToMaterialRows(rows, factor, lastConvertFactor.value);
|
||||
lastConvertFactor.value = normalizeMixingConvertFactor(factor);
|
||||
applyMaterialAccumWeight(rows);
|
||||
}
|
||||
|
||||
function handleConvertFactorChange(value: unknown) {
|
||||
if (!showFooter.value || convertFactorApplying.value) {
|
||||
return;
|
||||
}
|
||||
applyConvertFactorToMaterials(value);
|
||||
recalcFillVolume();
|
||||
}
|
||||
|
||||
function stripMaterialRowForSave(row: Recordable) {
|
||||
if (!row) {
|
||||
return row;
|
||||
}
|
||||
const { baseUnitWeight: _baseUnitWeight, ...rest } = row;
|
||||
return rest;
|
||||
}
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A43】换算系数联动明细单重实时计算-----------
|
||||
|
||||
function recalcMaterialAccumWeight() {
|
||||
applyMaterialAccumWeight();
|
||||
}
|
||||
|
||||
function handleMaterialValueChange(event) {
|
||||
const key = event?.column?.key;
|
||||
const row = event?.row;
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A43】换算系数联动明细单重实时计算-----------
|
||||
if (key === 'unitWeight' && row) {
|
||||
syncMaterialBaseUnitWeightFromDisplay(row, sheetForm.convertFactor);
|
||||
}
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A43】换算系数联动明细单重实时计算-----------
|
||||
if (key === 'unitWeight' || key === 'materialKind') {
|
||||
recalcMaterialAccumWeight();
|
||||
}
|
||||
}
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A41】橡胶及配合剂明细累计按种类分组合计-----------
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A17】橡胶及配合剂明细列展示设置-----------
|
||||
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A19】TCU温度条件表列宽可调且表头换行-----------
|
||||
@@ -710,6 +884,7 @@ const [registerForm, { resetFields, setFieldsValue, validate, setProps }] = useF
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A33】混炼示方主表选择弹窗-----------
|
||||
const [registerMachineModal, { openModal: openMachineModalInner }] = useModal();
|
||||
const [registerIssueNumberModal, { openModal: openIssueNumberModalInner }] = useModal();
|
||||
const [registerMixingMaterialModal, { openModal: openMixingMaterialModalInner }] = useModal();
|
||||
|
||||
function openMachinePicker() {
|
||||
if (!showFooter.value) {
|
||||
@@ -721,6 +896,11 @@ function openMachinePicker() {
|
||||
async function onMachineSelect(payload: Recordable | null) {
|
||||
sheetForm.machineId = payload?.equipmentLedgerId || '';
|
||||
sheetForm.machineName = payload?.equipmentName || '';
|
||||
machineEffectiveVolume.value = payload?.effectiveVolume || '';
|
||||
if (sheetForm.machineId && !machineEffectiveVolume.value) {
|
||||
await loadMachineEffectiveVolume(sheetForm.machineId);
|
||||
}
|
||||
recalcFillVolume();
|
||||
await loadMixerStepOptions(sheetForm.machineId);
|
||||
}
|
||||
|
||||
@@ -738,6 +918,27 @@ function onIssueNumberSelect(payload: Recordable | null) {
|
||||
mixerPsCompilePickerId.value = payload.psCompileId || '';
|
||||
sheetForm.issueNumber = payload.psCode || '';
|
||||
}
|
||||
|
||||
function openMixingMaterialPicker(row: Recordable) {
|
||||
if (!showFooter.value || !row) {
|
||||
return;
|
||||
}
|
||||
materialPickerRow.value = row;
|
||||
openMixingMaterialModalInner(true, { picker: true, ts: Date.now() });
|
||||
}
|
||||
|
||||
function onMixingMaterialSelect(payload: Recordable | null) {
|
||||
if (!payload || !materialPickerRow.value) {
|
||||
return;
|
||||
}
|
||||
applyMixingMaterialFromSelection(
|
||||
materialPickerRow.value,
|
||||
payload,
|
||||
payload.materialKind || payload.materialMinor || '',
|
||||
);
|
||||
recalcMaterialAccumWeight();
|
||||
materialPickerRow.value = null;
|
||||
}
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A33】混炼示方主表选择弹窗-----------
|
||||
|
||||
function ensureTcuDefaultRows(rows: Recordable[] = []) {
|
||||
@@ -783,6 +984,7 @@ function resetSheetForm() {
|
||||
sheetForm.approveTime = '';
|
||||
sheetForm.changeDate = '';
|
||||
mixerPsCompilePickerId.value = '';
|
||||
machineEffectiveVolume.value = '';
|
||||
refreshSignDisplay({});
|
||||
}
|
||||
|
||||
@@ -806,6 +1008,9 @@ const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data
|
||||
await resetFields();
|
||||
resetSheetForm();
|
||||
materialData.value = [];
|
||||
materialUnitWeightTotal.value = null;
|
||||
materialAccumWeightTotal.value = null;
|
||||
lastConvertFactor.value = 1;
|
||||
stepData.value = [];
|
||||
downStepData.value = [];
|
||||
tcuData.value = ensureTcuDefaultRows([]);
|
||||
@@ -819,10 +1024,16 @@ const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data
|
||||
const row = raw?.result || raw;
|
||||
Object.assign(sheetForm, row || {});
|
||||
refreshSignDisplay(row || {});
|
||||
await loadMachineEffectiveVolume(sheetForm.machineId);
|
||||
await loadMixerStepOptions(sheetForm.machineId);
|
||||
await syncSheetToForm();
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A39】编辑页明细补齐默认空行与新增一致-----------
|
||||
materialData.value = ensureMixingDetailRows(row?.materialList || [], DEFAULT_MIXING_MATERIAL_ROW_COUNT);
|
||||
convertFactorApplying.value = true;
|
||||
initMaterialBaseUnitWeights(materialData.value, sheetForm.convertFactor, true);
|
||||
lastConvertFactor.value = normalizeMixingConvertFactor(sheetForm.convertFactor);
|
||||
applyMaterialAccumWeight(materialData.value);
|
||||
convertFactorApplying.value = false;
|
||||
stepData.value = ensureMixingDetailRows(row?.stepList || [], DEFAULT_MIXING_STEP_ROW_COUNT);
|
||||
downStepData.value = ensureMixingDetailRows(row?.downStepList || [], DEFAULT_MIXING_DOWN_STEP_ROW_COUNT);
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A39】编辑页明细补齐默认空行与新增一致-----------
|
||||
@@ -838,6 +1049,7 @@ const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data
|
||||
});
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A22】明细表默认空行数-----------
|
||||
materialData.value = createEmptyMaterialRows();
|
||||
lastConvertFactor.value = normalizeMixingConvertFactor(sheetForm.convertFactor);
|
||||
stepData.value = createEmptyStepRows();
|
||||
downStepData.value = createEmptyDownStepRows();
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A22】明细表默认空行数-----------
|
||||
@@ -850,14 +1062,15 @@ const title = computed(() => (!showFooter.value && unref(isUpdate) ? '混炼示
|
||||
async function handleSubmit() {
|
||||
await syncSheetToForm();
|
||||
const formValues = await validate();
|
||||
const materialList = materialRef.value?.getTableData?.() || materialData.value;
|
||||
const materialList = resolveMaterialTableRawRows();
|
||||
applyMaterialAccumWeight(materialList);
|
||||
const stepList = stepRef.value?.getTableData?.() || stepData.value;
|
||||
const downStepList = downStepRef.value?.getTableData?.() || downStepData.value;
|
||||
const tcuList = ensureTcuDefaultRows((tcuRef.value?.getTableData?.() || tcuData.value) as Recordable[]);
|
||||
const cleanRows = (rows: Recordable[]) => (rows || []).filter((row) => Object.values(row || {}).some((v) => v != null && v !== ''));
|
||||
const payload = {
|
||||
...formValues,
|
||||
materialList: cleanRows(materialList),
|
||||
materialList: cleanRows(materialList).map(stripMaterialRowForSave),
|
||||
stepList: cleanRows(stepList),
|
||||
downStepList: cleanRows(downStepList),
|
||||
tcuList: tcuList.map((row) => ({
|
||||
@@ -1008,6 +1221,25 @@ async function handleSubmit() {
|
||||
color: #262626;
|
||||
}
|
||||
|
||||
:deep(.mixing-material-name-cell) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 2px 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
:deep(.mixing-material-name-cell.is-disabled) {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.65;
|
||||
}
|
||||
|
||||
:deep(.mixing-material-name-text) {
|
||||
color: #262626;
|
||||
}
|
||||
|
||||
}
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A17】顶部施工表对齐旧系统13列表格-----------
|
||||
|
||||
@@ -1027,6 +1259,9 @@ async function handleSubmit() {
|
||||
|
||||
.material-table-wrap {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
:deep(.jeecg-j-vxe-table),
|
||||
:deep(.j-vxe-table-box),
|
||||
@@ -1040,6 +1275,76 @@ async function handleSubmit() {
|
||||
}
|
||||
}
|
||||
|
||||
//update-begin---author:cursor ---date:20260525 for:【XSLMES-20260525-A42】橡胶及配合剂明细底部固定合计行-----------
|
||||
.material-table-stack {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
min-width: min-content;
|
||||
}
|
||||
|
||||
.material-table-body {
|
||||
flex: 0 0 auto;
|
||||
overflow: hidden;
|
||||
|
||||
:deep(.vxe-table--footer-wrapper) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:deep(.col--mixerMaterialName .vxe-cell) {
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:deep(.col--mixerMaterialName .vxe-cell > div) {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.material-table-footer {
|
||||
flex-shrink: 0;
|
||||
border: 1px solid #e8e8e8;
|
||||
border-top: none;
|
||||
background: #fafafa;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.material-table-footer-row {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
box-sizing: border-box;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.material-footer-seq,
|
||||
.material-footer-cell {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-right: 1px solid #e8e8e8;
|
||||
box-sizing: border-box;
|
||||
padding: 0 2px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
&:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
}
|
||||
|
||||
.material-footer-seq {
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.material-footer-cell.is-label,
|
||||
.material-footer-cell.is-total {
|
||||
font-weight: 600;
|
||||
color: #262626;
|
||||
}
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A42】橡胶及配合剂明细底部固定合计行-----------
|
||||
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A26】TCU紧凑两行且胶料表向下扩展-----------
|
||||
.material-table-wrap--fill {
|
||||
flex: 1;
|
||||
|
||||
Reference in New Issue
Block a user