update:树形表格组件优化

This commit is contained in:
2025-12-02 14:47:10 +08:00
parent a8eb6200ed
commit aac5333174
3 changed files with 440 additions and 220 deletions

View File

@@ -21,19 +21,34 @@ export default defineConfigWithVueTs(
skipFormatting, skipFormatting,
{ {
rules: { rules: {
'arrow-spacing': ['error', { 'before': true, 'after': true }], 'arrow-spacing': ['error', { before: true, after: true }],
'comma-dangle': ['error', { arrays: 'always-multiline', objects: 'always-multiline', imports: 'always-multiline', exports: 'always-multiline', functions: 'never' }], 'comma-dangle': [
'comma-spacing': ['error', { 'before': false, 'after': true }], 'error',
'indent': ['error', 2, { 'SwitchCase': 1 }], {
'key-spacing': ['error', { arrays: 'always-multiline',
'beforeColon': false, objects: 'always-multiline',
'afterColon': true, imports: 'always-multiline',
}], exports: 'always-multiline',
'keyword-spacing': ['error', { functions: 'never',
'before': true, },
'after': true, ],
}], 'comma-spacing': ['error', { before: false, after: true }],
'no-multiple-empty-lines': ['error', { 'max': 1 }], indent: ['error', 2, { SwitchCase: 1 }],
'key-spacing': [
'error',
{
beforeColon: false,
afterColon: true,
},
],
'keyword-spacing': [
'error',
{
before: true,
after: true,
},
],
'no-multiple-empty-lines': ['error', { max: 1 }],
'no-multi-spaces': 'error', 'no-multi-spaces': 'error',
'no-trailing-spaces': 'error', 'no-trailing-spaces': 'error',
'object-curly-spacing': ['error', 'always'], 'object-curly-spacing': ['error', 'always'],
@@ -42,18 +57,22 @@ export default defineConfigWithVueTs(
{ blankLine: 'always', prev: 'import', next: '*' }, { blankLine: 'always', prev: 'import', next: '*' },
{ blankLine: 'never', prev: 'import', next: 'import' }, { blankLine: 'never', prev: 'import', next: 'import' },
], ],
'quotes': ['error', 'single'], quotes: ['error', 'single'],
'semi': ['error', 'always'], semi: ['error', 'always'],
'space-before-blocks': ['error', 'always'], 'space-before-blocks': ['error', 'always'],
'spaced-comment': ['error', 'always', { 'spaced-comment': [
'line': { 'markers': ['/'], 'exceptions': ['/'] }, 'error',
'block': { 'exceptions': ['*'], 'balanced': true }, 'always',
}], {
'space-infix-ops': ['error', { 'int32Hint': false }], line: { markers: ['/'], exceptions: ['/'] },
'vue/html-closing-bracket-newline': ['error', { singleline: 'never', multiline: 'always' }], block: { exceptions: ['*'], balanced: true },
'vue/html-indent': ['error', 2], },
],
'space-infix-ops': ['error', { int32Hint: false }],
'vue/html-closing-bracket-newline': 'off',
'vue/html-indent': 'off',
'vue/first-attribute-linebreak': ['error', { singleline: 'ignore', multiline: 'below' }], 'vue/first-attribute-linebreak': ['error', { singleline: 'ignore', multiline: 'below' }],
'vue/max-attributes-per-line': ['error', { singleline: { max: 10 }, multiline: { max: 1 } }], 'vue/max-attributes-per-line': 'off',
'vue/multi-word-component-names': 'off', 'vue/multi-word-component-names': 'off',
'vue/mustache-interpolation-spacing': ['error', 'always'], 'vue/mustache-interpolation-spacing': ['error', 'always'],
'vue/no-multi-spaces': 'error', 'vue/no-multi-spaces': 'error',

View File

@@ -11,7 +11,7 @@
@change="changeFun" @change="changeFun"
@load="searchLoadFun" @load="searchLoadFun"
> >
<template v-for="(name) in Object.keys($slots)" :key="name" #[name]="scope"> <template v-for="name in Object.keys($slots)" :key="name" #[name]="scope">
<slot :name="name" v-bind="scope" /> <slot :name="name" v-bind="scope" />
</template> </template>
</TableSearch> </TableSearch>
@@ -22,21 +22,21 @@
<div class="item"> <div class="item">
<div class="btns"> <div class="btns">
<slot name="leftOptions" /> <slot name="leftOptions" />
<el-tooltip v-if="exportApi" :content="$t('表格.导出')" placement="top" > <el-tooltip v-if="exportApi" :content="$t('表格.导出')" placement="top">
<div v-if="exportApi" class="icon-btn" @click="exportFun"> <div v-if="exportApi" class="icon-btn" @click="exportFun">
<el-icon :size="18"> <el-icon :size="18">
<Download /> <Download />
</el-icon> </el-icon>
</div> </div>
</el-tooltip> </el-tooltip>
<el-tooltip v-if="showImport" :content="$t('表格.导入')" placement="top" > <el-tooltip v-if="showImport" :content="$t('表格.导入')" placement="top">
<div v-if="showImport" class="icon-btn" @click="formDiaVisible = true"> <div v-if="showImport" class="icon-btn" @click="formDiaVisible = true">
<el-icon :size="18"> <el-icon :size="18">
<Upload /> <Upload />
</el-icon> </el-icon>
</div> </div>
</el-tooltip> </el-tooltip>
<el-tooltip :content="$t('表格.列表字段设置')" placement="top" > <el-tooltip :content="$t('表格.列表字段设置')" placement="top">
<div class="icon-btn" @click="formDiaVisible = true"> <div class="icon-btn" @click="formDiaVisible = true">
<el-icon :size="18"> <el-icon :size="18">
<Setting /> <Setting />
@@ -54,8 +54,8 @@
height="100%" height="100%"
v-bind="$attrs" v-bind="$attrs"
keepSource keepSource
:seq-config="{startIndex: (current - 1) * size}" :seq-config="{ startIndex: (current - 1) * size }"
:virtual-y-config="{enabled: true, gt: 0}" :virtual-y-config="{ enabled: true, gt: 0 }"
:tree-config="{ :tree-config="{
transform: true, transform: true,
expandAll: true, expandAll: true,
@@ -65,7 +65,7 @@
}" }"
:checkbox-config="{ :checkbox-config="{
checkStrictly: true, checkStrictly: true,
showHeader: false showHeader: false,
}" }"
:column-config="{ :column-config="{
drag: true, drag: true,
@@ -73,13 +73,27 @@
}" }"
:column-drag-config="{ :column-drag-config="{
showIcon: false, showIcon: false,
trigger: 'cell' trigger: 'cell',
}" }"
> >
<vxe-column v-if="showCheckbox" type="checkbox" width="60" align="left" header-align="left" fixed="left"></vxe-column>
<vxe-column v-if="showIndex" type="seq" width="80" align="left" header-align="left" fixed="left" />
<vxe-column <vxe-column
v-for="(item) in tableHeadVisible" v-if="showCheckbox"
type="checkbox"
width="60"
align="left"
header-align="left"
fixed="left"
></vxe-column>
<vxe-column
v-if="showIndex"
type="seq"
width="80"
align="left"
header-align="left"
fixed="left"
/>
<vxe-column
v-for="item in tableHeadVisible"
:key="item.key" :key="item.key"
:field="item.key" :field="item.key"
:title="item.title" :title="item.title"
@@ -93,25 +107,35 @@
<template #header="{ column }"> <template #header="{ column }">
<span class="head-title"> <span class="head-title">
{{ column.title }} {{ column.title }}
<el-popover <el-popover trigger="click" :width="200">
trigger="click"
:width="200"
>
<template #default> <template #default>
<div class="head-search"> <div class="head-search">
<div class="search-item"> <div class="search-item">
<el-input v-model="filterData[column.field]" size="small" placeholder="请输入" clearable /> <el-input
v-model="filterData[column.field]"
size="small"
placeholder="请输入"
clearable
/>
</div> </div>
<div class="btns"> <div class="btns">
<el-button class="btn" size="small" @click="filterResetFun(column)">重置</el-button> <el-button class="btn" size="small" @click="filterResetFun(column)"
<el-button class="btn" type="primary" size="small" @click="filterFun(column)">确定</el-button> >重置</el-button
>
<el-button class="btn" type="primary" size="small" @click="filterFun(column)"
>确定</el-button
>
</div> </div>
</div> </div>
</template> </template>
<template #reference> <template #reference>
<el-icon class="head-icon" :class="{active: filterData[column.field]}" :size="16"> <el-icon
class="head-icon"
:class="{ active: filterData[column.field] }"
:size="16"
>
<Finished v-if="filterData[column.field]" /> <Finished v-if="filterData[column.field]" />
<Filter v-else/> <Filter v-else />
</el-icon> </el-icon>
</template> </template>
</el-popover> </el-popover>
@@ -119,12 +143,27 @@
</template> </template>
<template #default="{ row, column, $rowIndex }"> <template #default="{ row, column, $rowIndex }">
<template v-if="$slots[`${item.key}-edit`] || $slots[item.key]"> <template v-if="$slots[`${item.key}-edit`] || $slots[item.key]">
<template v-if="$slots[item.key] && !(editData[$rowIndex] && editData[$rowIndex][`${item.key}-edit`])"> <template
<span class="table-cell" :class="{edit: !!$slots[`${item.key}-edit`]}" @dblclick="dblclickFun($rowIndex, item, !!$slots[`${item.key}-edit`])"> v-if="
$slots[item.key] &&
!(editData[$rowIndex] && editData[$rowIndex][`${item.key}-edit`])
"
>
<span
class="table-cell"
:class="{ edit: !!$slots[`${item.key}-edit`] }"
@dblclick="dblclickFun($rowIndex, item, !!$slots[`${item.key}-edit`])"
>
<slot :name="item.key" :row="row" :column="column" /> <slot :name="item.key" :row="row" :column="column" />
</span> </span>
</template> </template>
<template v-if="$slots[`${item.key}-edit`] && (editData[$rowIndex] && editData[$rowIndex][`${item.key}-edit`])"> <template
v-if="
$slots[`${item.key}-edit`] &&
editData[$rowIndex] &&
editData[$rowIndex][`${item.key}-edit`]
"
>
<span @click.stop> <span @click.stop>
<slot :name="`${item.key}-edit`" :row="row" :column="column" /> <slot :name="`${item.key}-edit`" :row="row" :column="column" />
</span> </span>
@@ -146,7 +185,12 @@
<template #default="{ row }"> <template #default="{ row }">
<div v-if="!$slots.tableActions" class="actions"> <div v-if="!$slots.tableActions" class="actions">
<template v-for="(action, aIndex) in actionList" :key="aIndex"> <template v-for="(action, aIndex) in actionList" :key="aIndex">
<el-link v-if="!(action.hide && action.hide(row)) && (findVisibleIndex(row, action) <= 2)" class="action-item" :type="action.type" @click="actionClickFun(row, action)"> <el-link
v-if="!(action.hide && action.hide(row)) && findVisibleIndex(row, action) <= 2"
class="action-item"
:type="action.type"
@click="actionClickFun(row, action)"
>
{{ action.title }} {{ action.title }}
</el-link> </el-link>
</template> </template>
@@ -157,7 +201,12 @@
<template #dropdown> <template #dropdown>
<el-dropdown-menu> <el-dropdown-menu>
<template v-for="(action, aIndex) in actionList" :key="aIndex"> <template v-for="(action, aIndex) in actionList" :key="aIndex">
<el-dropdown-item v-if="!(action.hide && action.hide(row)) && (findVisibleIndex(row, action) > 2)" @click="actionClickFun(row, action)"> <el-dropdown-item
v-if="
!(action.hide && action.hide(row)) && findVisibleIndex(row, action) > 2
"
@click="actionClickFun(row, action)"
>
<el-link :type="action.type">{{ action.title }}</el-link> <el-link :type="action.type">{{ action.title }}</el-link>
</el-dropdown-item> </el-dropdown-item>
</template> </template>
@@ -172,7 +221,12 @@
</vxe-column> </vxe-column>
</vxe-table> </vxe-table>
</div> </div>
<TableFormDia v-model="formDiaVisible" :head="tableHead" :name="tableName" @update="getHeadDataFun" /> <TableFormDia
v-model="formDiaVisible"
:head="tableHead"
:name="tableName"
@update="getHeadDataFun"
/>
</div> </div>
</template> </template>
@@ -188,7 +242,13 @@ import { formOptionsFormat } from './lib';
import { uniqBy, cloneDeep } from 'lodash-es'; import { uniqBy, cloneDeep } from 'lodash-es';
import { exportFile } from '@/utils/file'; import { exportFile } from '@/utils/file';
const emit = defineEmits(['searchChange', 'load', 'settingConfirm', 'filterReset', 'filterConfirm']); const emit = defineEmits([
'searchChange',
'load',
'settingConfirm',
'filterReset',
'filterConfirm',
]);
interface Props { interface Props {
tableName: string; tableName: string;
@@ -266,49 +326,66 @@ const findVisibleIndex = (row: any, action: any) => {
return index; return index;
}; };
const visibleNum = (row: any) => { // 展示按钮数量 const visibleNum = (row: any) => {
// 展示按钮数量
return props.actionList.filter((d: any) => !(d.hide && d.hide(row))).length; return props.actionList.filter((d: any) => !(d.hide && d.hide(row))).length;
}; };
watch(() => props.actionList, (list: any) => { watch(
let width = 20; // cell内边距 () => props.actionList,
list.some((item: any, index: number) => { (list: any) => {
if (index < 2) { let width = 20; // cell内边距
width += item.title.length * 14; // 一个汉字14 list.some((item: any, index: number) => {
width += 8; // 内边距 if (index < 2) {
} else { width += item.title.length * 14; // 一个汉字14
return true; width += 8; // 内边距
} } else {
}); return true;
if (list.length > 2) {
width += 30; // 更多宽度
}
actionAutoWidth.value = width;
}, { immediate: true });
watch(() => props.data, (data) => {
data.forEach((item: any) => {
for (const key in item) {
if (key === 'extras' && item.extras) {
item[key].forEach((val: any) => {
item[val.propertyName] = val.propertyValue;
});
} }
});
if (list.length > 2) {
width += 30; // 更多宽度
} }
}); actionAutoWidth.value = width;
formatData.value = data; },
originData = cloneDeep(props.data); { immediate: true }
}, { immediate: true }); );
watch(() => props.params, (val: any, oldVal: any) => { watch(
if (JSON.stringify(val) !== JSON.stringify(oldVal)) { () => props.data,
resetFun(val); (data) => {
} data.forEach((item: any) => {
}, { deep: true }); for (const key in item) {
if (key === 'extras' && item.extras) {
item[key].forEach((val: any) => {
item[val.propertyName] = val.propertyValue;
});
}
}
});
formatData.value = data;
originData = cloneDeep(props.data);
},
{ immediate: true }
);
watch(() => props.searchItems, (val) => { watch(
searchList.value = val; () => props.params,
}, { deep: true, immediate: true }); (val: any, oldVal: any) => {
if (JSON.stringify(val) !== JSON.stringify(oldVal)) {
resetFun(val);
}
},
{ deep: true }
);
watch(
() => props.searchItems,
(val) => {
searchList.value = val;
},
{ deep: true, immediate: true }
);
onMounted(() => { onMounted(() => {
initFun(); initFun();
@@ -333,7 +410,8 @@ const getHeadDataFun = () => {
const formConfig = JSON.parse(res.data.formConfig); const formConfig = JSON.parse(res.data.formConfig);
tableHead.value = formConfig; tableHead.value = formConfig;
tableHeadVisible.value = formConfig.filter((item: any) => item.isShow); tableHeadVisible.value = formConfig.filter((item: any) => item.isShow);
if (props.searchItems.length === 0) { // 没有传入搜索配置,则默认搜索配置 if (props.searchItems.length === 0) {
// 没有传入搜索配置,则默认搜索配置
const searchBuild: any[] = []; const searchBuild: any[] = [];
formConfig.forEach((item: any) => { formConfig.forEach((item: any) => {
if (item.tableSearch) { if (item.tableSearch) {
@@ -365,13 +443,17 @@ const resetFun = (data: object) => {
searchData.value = data; searchData.value = data;
getTableDataFun(); getTableDataFun();
}; };
watch(() => props.head, (val) => { watch(
if (val) { () => props.head,
tableHead.value = val; (val) => {
tableHeadVisible.value = val.filter((item: any) => item.isShow); if (val) {
resetFun({}); tableHead.value = val;
} tableHeadVisible.value = val.filter((item: any) => item.isShow);
}, { deep: true, immediate: true }); resetFun({});
}
},
{ deep: true, immediate: true }
);
// 获取搜索参数 // 获取搜索参数
const getSearchParamsFun = () => { const getSearchParamsFun = () => {
if (tableSearchRef.value) { if (tableSearchRef.value) {
@@ -406,7 +488,7 @@ const filterResetFun = (data: any) => {
filterFun(data, true); filterFun(data, true);
}; };
// 筛选 // 筛选
const filterFun = (data: any, isReset:boolean = false) => { const filterFun = (data: any, isReset: boolean = false) => {
const idMap: any = {}; const idMap: any = {};
const matchedIds = new Set<any>(); const matchedIds = new Set<any>();
originData.forEach((item: any) => { originData.forEach((item: any) => {
@@ -501,9 +583,11 @@ const actionClickFun = (row: any, action: any) => {
if (needConfirm) { if (needConfirm) {
ElMessageBox.confirm(confirmTip || '确定操作吗?', '提示', { ElMessageBox.confirm(confirmTip || '确定操作吗?', '提示', {
type: 'warning', type: 'warning',
}).then(() => { })
click(row); .then(() => {
}).catch(() => {}); click(row);
})
.catch(() => {});
} else { } else {
click(row); click(row);
} }
@@ -511,12 +595,21 @@ const actionClickFun = (row: any, action: any) => {
}; };
const exportFun = () => { const exportFun = () => {
exportFile(props.exportApi, props.tableName, props.exportFileName, props.exportParams, props.exportDict); exportFile(
props.exportApi,
props.tableName,
props.exportFileName,
props.exportParams,
props.exportDict
);
}; };
watch(() => props.tableName, () => { watch(
initFun(); () => props.tableName,
}); () => {
initFun();
}
);
defineExpose({ defineExpose({
tableData, tableData,
@@ -531,6 +624,7 @@ defineExpose({
getCheckboxRecordsFun, getCheckboxRecordsFun,
removeFun, removeFun,
getRecordSetFun, getRecordSetFun,
cancelEditFun,
}); });
</script> </script>

View File

@@ -1,12 +1,15 @@
<template> <template>
<div class="comp-content comp-tree-case-table"> <div class="comp-content comp-tree-case-table">
<TreeTable ref="TreeTableRef" :tableName="tableName" :data="treeData" :editMode="editMode" v-bind="$attrs"> <TreeTable
ref="TreeTableRef"
:tableName="tableName"
:data="treeData"
:editMode="editMode"
v-bind="$attrs"
>
<!-- 名称 --> <!-- 名称 -->
<template #nodeName="{ row ,column}"> <template #nodeName="{ row }">
<TreeEditItem <TreeEditItem :data="row.nodeName" :editMode="editMode">
:data="row[column.field]"
:editMode="editMode"
>
<div class="node-name"> <div class="node-name">
<el-icon v-if="row.nodeType === NODE_TYPE.TASK" :size="16" class="blue"> <el-icon v-if="row.nodeType === NODE_TYPE.TASK" :size="16" class="blue">
<Document /> <Document />
@@ -21,40 +24,60 @@
</div> </div>
</TreeEditItem> </TreeEditItem>
</template> </template>
<template #nodeName-edit="{ row, column }"> <template #nodeName-edit="{ row }">
<el-input v-model="row[column.field]" size="small" placeholder="请输入" /> <el-input
v-model="row.nodeName"
size="small"
placeholder="请输入"
@input="(val: any) => inputFun(val, row, 'nodeName')"
@keyup.enter="enterFun"
/>
</template> </template>
<!-- 英文名 --> <!-- 英文名 -->
<template #englishName="{ row, column }"> <template #englishName="{ row }">
<TreeEditItem <TreeEditItem :data="row.englishName" :editMode="editMode" />
:data="row[column.field]"
:editMode="editMode"
/>
</template> </template>
<template #englishName-edit="{ row }"> <template #englishName-edit="{ row }">
<el-input v-model="row.englishName" size="small" placeholder="请输入" /> <el-input
</template> v-model="row.englishName"
<!-- 编码 --> size="small"
<template #nodeCode="{ row, column }"> placeholder="请输入"
<TreeEditItem @input="(val: any) => inputFun(val, row, 'englishName')"
:data="row[column.field]" @keyup.enter="enterFun"
:editMode="editMode"
/> />
</template> </template>
<!-- 编码 -->
<template #nodeCode="{ row }">
<TreeEditItem :data="row.nodeCode" :editMode="editMode" />
</template>
<template #nodeCode-edit="{ row }"> <template #nodeCode-edit="{ row }">
<el-input v-model="row.nodeCode" size="small" placeholder="请输入" /> <el-input
v-model="row.nodeCode"
size="small"
placeholder="请输入"
@input="(val: any) => inputFun(val, row, 'nodeCode')"
@keyup.enter="enterFun"
/>
</template> </template>
<template #pMemberIds="{ row }"> <template #pMemberIds="{ row }">
{{ disposeMemberList(row,'pMemberList') }} {{ disposeMemberList(row, 'pMemberList') }}
</template> </template>
<template #pMemberIds-edit="{ row,column }"> <template #pMemberIds-edit="{ row }">
<userSelect @change="(data) => changeUserFun(row,data,'pMemberList','pMemberIds')" :multiple="true" v-model="row[column.field]"></userSelect> <userSelect
@change="(data) => changeUserFun(row, data, 'pMemberList', 'pMemberIds')"
:multiple="true"
v-model="row.pMemberIds"
></userSelect>
</template> </template>
<template #eMemberIds="{ row }"> <template #eMemberIds="{ row }">
{{ disposeMemberList(row,'eMemberList') }} {{ disposeMemberList(row, 'eMemberList') }}
</template> </template>
<template #eMemberIds-edit="{ row,column }"> <template #eMemberIds-edit="{ row }">
<userSelect @change="(data) => changeUserFun(row,data,'eMemberList','eMemberIds')" :multiple="true" v-model="row[column.field]"></userSelect> <userSelect
@change="(data) => changeUserFun(row, data, 'eMemberList', 'eMemberIds')"
:multiple="true"
v-model="row.eMemberIds"
></userSelect>
</template> </template>
<!-- 计划开始时间 --> <!-- 计划开始时间 -->
<template #beginTime="{ row }"> <template #beginTime="{ row }">
@@ -93,186 +116,259 @@
/> />
</template> </template>
<!-- 达标方式 --> <!-- 达标方式 -->
<template #method="{ row,column }"> <template #method="{ row }">
<TreeEditItem v-if="[NODE_TYPE.PERFORMANCE].includes(row.nodeType) || isMixedNodeType(row.nodeType)" :data="row[column.field]" :editMode="editMode"> <TreeEditItem
<dictLabel v-model="row[column.field]" dictName="COMPLIANCE_METHOD" /> v-if="[NODE_TYPE.PERFORMANCE].includes(row.nodeType) || isMixedNodeType(row.nodeType)"
:data="row.method"
:editMode="editMode"
>
<dictLabel v-model="row.method" dictName="COMPLIANCE_METHOD" />
</TreeEditItem> </TreeEditItem>
</template> </template>
<template #method-edit="{ row,column }"> <template #method-edit="{ row }">
<dictLabel v-model="row[column.field]" dictName="COMPLIANCE_METHOD" :editable="true" /> <dictLabel v-model="row.method" dictName="COMPLIANCE_METHOD" :editable="true" />
</template> </template>
<!-- 目标值 --> <!-- 目标值 -->
<template #highValue="{ row,column }"> <template #highValue="{ row }">
<TreeEditItem v-if="[NODE_TYPE.PERFORMANCE].includes(row.nodeType) || isMixedNodeType(row.nodeType)" :data="row[column.field]" :editMode="editMode"> <TreeEditItem
v-if="[NODE_TYPE.PERFORMANCE].includes(row.nodeType) || isMixedNodeType(row.nodeType)"
:data="row.highValue"
:editMode="editMode"
>
</TreeEditItem> </TreeEditItem>
</template> </template>
<template #highValue-edit="{ row,column }"> <template #highValue-edit="{ row }">
<el-input-number v-if="row.performanceType==='1'" v-model="row[column.field]" size="small" placeholder="请输入" /> <el-input-number
<el-input v-else v-model="row[column.field]" size="small" placeholder="请输入" /> v-if="row.performanceType === '1'"
v-model="row.highValue"
size="small"
placeholder="请输入"
/>
<el-input
v-else
v-model="row.highValue"
size="small"
placeholder="请输入"
@input="(val: any) => inputFun(val, row, 'highValue')"
@keyup.enter="enterFun"
/>
</template> </template>
<!-- 类型 --> <!-- 类型 -->
<template #nodeType="{ row, column }"> <template #nodeType="{ row }">
<dictLabel v-model="row[column.field]" :options="allNodeTypeOptions" /> <dictLabel v-model="row.nodeType" :options="allNodeTypeOptions" />
</template> </template>
<!-- 任务模板 --> <!-- 任务模板 -->
<template #flowTemplate="{ row, column }"> <template #flowTemplate="{ row }">
<TreeEditItem <TreeEditItem
v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)" v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)"
:data="row[column.field]" :data="row.flowTemplate"
:editMode="editMode" :editMode="editMode"
> >
<flowTemplateSelect v-model="row[column.field]" :editable="false" size="small"/> <flowTemplateSelect v-model="row.flowTemplate" :editable="false" size="small" />
</TreeEditItem> </TreeEditItem>
</template> </template>
<template #flowTemplate-edit="{ row, column }"> <template #flowTemplate-edit="{ row }">
<flowTemplateSelect v-model="row[column.field]" size="small" /> <flowTemplateSelect v-model="row.flowTemplate" size="small" />
</template> </template>
<!-- 标准规范 --> <!-- 标准规范 -->
<template #standard="{ row, column }"> <template #standard="{ row }">
<TreeEditItem <TreeEditItem
v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)" v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)"
:data="row[column.field]" :data="row.standard"
:editMode="editMode" :editMode="editMode"
> >
<knowledgeSelect v-model="row[column.field]" v-model:model-name="row.standard" :editable="false" size="small"/> <knowledgeSelect
v-model="row.standard"
v-model:model-name="row.standard"
:editable="false"
size="small"
/>
</TreeEditItem> </TreeEditItem>
</template> </template>
<template #standard-edit="{ row, column }"> <template #standard-edit="{ row }">
<knowledgeSelect v-model="row[column.field]" size="small"/> <knowledgeSelect v-model="row.standard" size="small" />
</template> </template>
<!-- 分析目标 --> <!-- 分析目标 -->
<template #analyseTarget="{ row, column }"> <template #analyseTarget="{ row }">
<TreeEditItem <TreeEditItem
v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)" v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)"
:data="row[column.field]" :data="row.analyseTarget"
:editMode="editMode" :editMode="editMode"
/> />
</template> </template>
<template #analyseTarget-edit="{ row , column}"> <template #analyseTarget-edit="{ row }">
<el-input v-model="row[column.field]" size="small" placeholder="请输入" /> <el-input
v-model="row.analyseTarget"
size="small"
placeholder="请输入"
@input="(val: any) => inputFun(val, row, 'analyseTarget')"
@keyup.enter="enterFun"
/>
</template> </template>
<!-- 置信度 --> <!-- 置信度 -->
<template #confidence="{ row, column }"> <template #confidence="{ row }">
<TreeEditItem <TreeEditItem
v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)" v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)"
:data="row[column.field]" :data="row.confidence"
:editMode="editMode" :editMode="editMode"
/> />
</template> </template>
<template #confidence-edit="{ row , column}"> <template #confidence-edit="{ row }">
<el-input-number v-model="row[column.field]" size="small" placeholder="请输入" /> <el-input-number v-model="row.confidence" size="small" placeholder="请输入" />
</template> </template>
<!-- 难度系数 --> <!-- 难度系数 -->
<template #difficult="{ row, column }"> <template #difficult="{ row }">
<TreeEditItem <TreeEditItem
v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)" v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)"
:data="row[column.field]" :data="row.difficult"
:editMode="editMode" :editMode="editMode"
/> />
</template> </template>
<template #difficult-edit="{ row , column}"> <template #difficult-edit="{ row }">
<el-input-number v-model="row[column.field]" size="small" placeholder="请输入" /> <el-input-number v-model="row.difficult" size="small" placeholder="请输入" />
</template> </template>
<!-- 标准工时 --> <!-- 标准工时 -->
<template #days="{ row, column }"> <template #days="{ row }">
<TreeEditItem <TreeEditItem
v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)" v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)"
:data="row[column.field]" :data="row.days"
:editMode="editMode" :editMode="editMode"
/> />
</template> </template>
<template #days-edit="{ row , column}"> <template #days-edit="{ row }">
<el-input-number v-model="row[column.field]" size="small" placeholder="请输入" /> <el-input-number v-model="row.days" size="small" placeholder="请输入" />
</template> </template>
<!-- 指标类型 --> <!-- 指标类型 -->
<template #performanceType="{ row, column }"> <template #performanceType="{ row }">
<TreeEditItem <TreeEditItem
v-if="[NODE_TYPE.PERFORMANCE].includes(row.nodeType) || isMixedNodeType(row.nodeType)" v-if="[NODE_TYPE.PERFORMANCE].includes(row.nodeType) || isMixedNodeType(row.nodeType)"
:data="row.performanceType" :data="row.performanceType"
:editMode="editMode" :editMode="editMode"
> >
<dictLabel v-model="row[column.field]" dictName="PERFORMANCE_TYPE" /> <dictLabel v-model="row.performanceType" dictName="PERFORMANCE_TYPE" />
</TreeEditItem> </TreeEditItem>
</template> </template>
<template #performanceType-edit="{ row, column }"> <template #performanceType-edit="{ row }">
<dictLabel v-model="row[column.field]" dictName="PERFORMANCE_TYPE" :editable="true" /> <dictLabel v-model="row.performanceType" dictName="PERFORMANCE_TYPE" :editable="true" />
</template> </template>
<!-- 指标单位 --> <!-- 指标单位 -->
<template #unit="{ row, column }"> <template #unit="{ row }">
<TreeEditItem v-if="[NODE_TYPE.PERFORMANCE].includes(row.nodeType) || isMixedNodeType(row.nodeType)" :data="row.unit" :editMode="editMode"> <TreeEditItem
<dictLabel v-model="row[column.field]" dictName="PERFORMANCE_UNIT" /> v-if="[NODE_TYPE.PERFORMANCE].includes(row.nodeType) || isMixedNodeType(row.nodeType)"
:data="row.unit"
:editMode="editMode"
>
<dictLabel v-model="row.unit" dictName="PERFORMANCE_UNIT" />
</TreeEditItem> </TreeEditItem>
</template> </template>
<template #unit-edit="{ row, column }"> <template #unit-edit="{ row }">
<dictLabel v-model="row[column.field]" dictName="PERFORMANCE_UNIT" :editable="true" /> <dictLabel v-model="row.unit" dictName="PERFORMANCE_UNIT" :editable="true" />
</template> </template>
<!-- 分析软件 --> <!-- 分析软件 -->
<template #analyseSoftware="{ row, column }"> <template #analyseSoftware="{ row }">
<TreeEditItem v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)" :data="row.analyseSoftware" :editMode="editMode"> <TreeEditItem
<dictLabel v-model="row[column.field]" dictName="ANALYSIS_SOFTWARE" /> v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)"
:data="row.analyseSoftware"
:editMode="editMode"
>
<dictLabel v-model="row.analyseSoftware" dictName="ANALYSIS_SOFTWARE" />
</TreeEditItem> </TreeEditItem>
</template> </template>
<template #analyseSoftware-edit="{ row, column }"> <template #analyseSoftware-edit="{ row }">
<dictLabel v-model="row[column.field]" dictName="ANALYSIS_SOFTWARE" :editable="true" :multiple="true" /> <dictLabel
v-model="row.analyseSoftware"
dictName="ANALYSIS_SOFTWARE"
:editable="true"
:multiple="true"
/>
</template> </template>
<!-- 3d图示 --> <!-- 3d图示 -->
<template #imageFileId="{ row, column }"> <template #imageFileId="{ row }">
<TreeEditItem v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)" :data="row[column.field]" :editMode="editMode"> <TreeEditItem
<uploadImg v-model="row[column.field]" /> v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)"
:data="row.imageFileId"
:editMode="editMode"
>
<uploadImg v-model="row.imageFileId" />
</TreeEditItem> </TreeEditItem>
</template> </template>
<template #imageFileId-edit="{ row, column }"> <template #imageFileId-edit="{ row }">
<uploadImg v-model="row[column.field]" /> <uploadImg v-model="row.imageFileId" />
</template> </template>
<!-- 仿真能力 --> <!-- 仿真能力 -->
<template #bCapacity="{ row, column }"> <template #bCapacity="{ row }">
<TreeEditItem v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)" :data="row[column.field]" :editMode="editMode"> <TreeEditItem
<dictLabel v-model="row[column.field]" dictName="SIMULATION_CAPACITY" /> v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)"
:data="row.bCapacity"
:editMode="editMode"
>
<dictLabel v-model="row.bCapacity" dictName="SIMULATION_CAPACITY" />
</TreeEditItem> </TreeEditItem>
</template> </template>
<template #bCapacity-edit="{ row, column }"> <template #bCapacity-edit="{ row }">
<dictLabel v-model="row[column.field]" dictName="SIMULATION_CAPACITY" :editable="true" /> <dictLabel v-model="row.bCapacity" dictName="SIMULATION_CAPACITY" :editable="true" />
</template> </template>
<!-- --> <!-- -->
<template #department="{ row, column }"> <template #department="{ row }">
<TreeEditItem v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)" :data="row.department" :editMode="editMode"> <TreeEditItem
<dictLabel v-model="row[column.field]" dictName="DEPARTMENT_LIST" /> v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)"
:data="row.department"
:editMode="editMode"
>
<dictLabel v-model="row.department" dictName="DEPARTMENT_LIST" />
</TreeEditItem> </TreeEditItem>
</template> </template>
<template #department-edit="{ row, column }"> <template #department-edit="{ row }">
<dictLabel v-model="row[column.field]" dictName="DEPARTMENT_LIST" :editable="true" /> <dictLabel v-model="row.department" dictName="DEPARTMENT_LIST" :editable="true" />
</template> </template>
<!-- --> <!-- -->
<template #section="{ row, column }"> <template #section="{ row }">
<TreeEditItem v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)" :data="row.section" :editMode="editMode"> <TreeEditItem
<dictLabel v-model="row[column.field]" dictName="SECTION_LIST" /> v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)"
:data="row.section"
:editMode="editMode"
>
<dictLabel v-model="row.section" dictName="SECTION_LIST" />
</TreeEditItem> </TreeEditItem>
</template> </template>
<template #section-edit="{ row, column }"> <template #section-edit="{ row }">
<dictLabel v-model="row[column.field]" dictName="SECTION_LIST" :editable="true" /> <dictLabel v-model="row.section" dictName="SECTION_LIST" :editable="true" />
</template> </template>
<!-- --> <!-- -->
<template #group="{ row, column }"> <template #group="{ row }">
<TreeEditItem v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)" :data="row[column.field]" :editMode="editMode"> <TreeEditItem
<dictLabel v-model="row[column.field]" dictName="GROUP_LIST" /> v-if="[NODE_TYPE.TASK].includes(row.nodeType) || isMixedNodeType(row.nodeType)"
:data="row.group"
:editMode="editMode"
>
<dictLabel v-model="row.group" dictName="GROUP_LIST" />
</TreeEditItem> </TreeEditItem>
</template> </template>
<template #group-edit="{ row, column }"> <template #group-edit="{ row }">
<dictLabel v-model="row[column.field]" dictName="GROUP_LIST" :editable="true" /> <dictLabel v-model="row.group" dictName="GROUP_LIST" :editable="true" />
</template> </template>
<!-- 描述 --> <!-- 描述 -->
<template #description="{ row }"> <template #description="{ row }">
<TreeEditItem <TreeEditItem
v-if="[NODE_TYPE.TASK, NODE_TYPE.PERFORMANCE].includes(row.nodeType) || isMixedNodeType(row.nodeType)" v-if="
[NODE_TYPE.TASK, NODE_TYPE.PERFORMANCE].includes(row.nodeType) ||
isMixedNodeType(row.nodeType)
"
:data="row.description" :data="row.description"
:editMode="editMode" :editMode="editMode"
/> />
</template> </template>
<template #description-edit="{ row }"> <template #description-edit="{ row }">
<el-input v-model="row.description" size="small" placeholder="请输入" /> <el-input
v-model="row.description"
size="small"
placeholder="请输入"
@input="(val: any) => inputFun(val, row, 'description')"
@keyup.enter="enterFun"
/>
</template> </template>
<!-- 插槽 --> <!-- 插槽 -->
<template v-for="(name) in Object.keys($slots)" :key="name" #[name]="scope"> <template v-for="name in Object.keys($slots)" :key="name" #[name]="scope">
<slot :name="name" v-bind="scope" /> <slot :name="name" v-bind="scope" />
</template> </template>
</TreeTable> </TreeTable>
@@ -297,6 +393,7 @@ import userSelect from '../userSelect/index.vue';
import { disposeMemberList } from '@/views/task/projectDetail/components/project'; import { disposeMemberList } from '@/views/task/projectDetail/components/project';
import { getMemberListIds } from '@/utils/task'; import { getMemberListIds } from '@/utils/task';
const ALLOWED_PATTERN = /[^a-zA-Z0-9\u4e00-\u9fa5\s]/g;
const TreeTableRef = ref<any>(); const TreeTableRef = ref<any>();
interface Props { interface Props {
@@ -327,36 +424,46 @@ const treeDataFormatFun = (data: any, build: any, pId: any) => {
return build; return build;
}; };
const changeUserFun = (row:any, data:any, listKey:string, idKey:string) => { const changeUserFun = (row: any, data: any, listKey: string, idKey: string) => {
console.log('changeUserFun', row, data); console.log('changeUserFun', row, data);
row[listKey] = data; row[listKey] = data;
row[idKey] = getMemberListIds(data); row[idKey] = getMemberListIds(data);
}; };
watch(() => props.data, (val: any) => { watch(
treeData.value = treeDataFormatFun(val, [], '0'); () => props.data,
}, { immediate: true }); (val: any) => {
treeData.value = treeDataFormatFun(val, [], '0');
},
{ immediate: true }
);
const getCheckboxRecordsFun = (isFull: boolean) => { const getCheckboxRecordsFun = (isFull: boolean) => {
if (TreeTableRef.value) { return TreeTableRef.value?.getCheckboxRecordsFun(isFull);
return TreeTableRef.value.getCheckboxRecordsFun(isFull);
}
}; };
const removeFun = (data: any) => { const removeFun = (data: any) => {
if (TreeTableRef.value) { return TreeTableRef.value?.removeFun(data);
return TreeTableRef.value.removeFun(data);
}
}; };
const allNodeTypeOptions = computed(() => { const allNodeTypeOptions = computed(() => {
const options: any = poolCategoryTypeOptions.value; const options: any = poolCategoryTypeOptions.value;
return nodeTypeList.concat(options); return nodeTypeList.concat(options);
}); });
const inputFun = (val: any, data: any, key: any) => {
// 过滤特殊字符
data[key] = val.replace(ALLOWED_PATTERN, '');
};
const enterFun = () => {
TreeTableRef.value?.cancelEditFun();
};
onMounted(() => { onMounted(() => {
taskStore.fetchTemplates(); taskStore.fetchTemplates();
}); });
defineExpose({ defineExpose({
getCheckboxRecordsFun, getCheckboxRecordsFun,
removeFun, removeFun,