diff --git a/frontend/src/assets/style/global.less b/frontend/src/assets/style/global.less
index f700fb3876..3189ad143c 100644
--- a/frontend/src/assets/style/global.less
+++ b/frontend/src/assets/style/global.less
@@ -190,3 +190,28 @@ body {
@apply mt-0;
}
}
+
+/** 更多按钮 **/
+.ms-more-action-trigger-content {
+ @apply flex items-center;
+ .more-icon-btn {
+ padding: 2px;
+ border-radius: var(--border-radius-mini);
+ &:hover {
+ background-color: rgb(var(--primary-9)) !important;
+ .arco-icon {
+ color: rgb(var(--primary-5)) !important;
+ }
+ }
+ }
+}
+.ms-more-action-trigger-content--focus {
+ .more-icon-btn {
+ @apply !visible;
+
+ background-color: rgb(var(--primary-9));
+ .arco-icon {
+ color: rgb(var(--primary-5));
+ }
+ }
+}
diff --git a/frontend/src/components/business/ms-tree/index.vue b/frontend/src/components/business/ms-tree/index.vue
index 7900861409..b96a2b893e 100644
--- a/frontend/src/components/business/ms-tree/index.vue
+++ b/frontend/src/components/business/ms-tree/index.vue
@@ -629,6 +629,9 @@
&:hover {
background-color: transparent;
}
+ .ms-tree-node-extra {
+ background-color: transparent;
+ }
* {
color: var(--color-text-4) !important;
}
diff --git a/frontend/src/components/business/ms-tree/types.ts b/frontend/src/components/business/ms-tree/types.ts
index 18942c2980..63f4f94217 100644
--- a/frontend/src/components/business/ms-tree/types.ts
+++ b/frontend/src/components/business/ms-tree/types.ts
@@ -11,6 +11,7 @@ export type MsTreeNodeData = {
hideMoreAction?: boolean; // 隐藏更多操作
parentId?: string;
expanded?: boolean; // 是否展开
+ containChildModule?: boolean; // 包含子模块
[key: string]: any;
} & TreeNodeData;
diff --git a/frontend/src/components/pure/ms-table-more-action/index.vue b/frontend/src/components/pure/ms-table-more-action/index.vue
index d053366f2d..8f9aa0d689 100644
--- a/frontend/src/components/pure/ms-table-more-action/index.vue
+++ b/frontend/src/components/pure/ms-table-more-action/index.vue
@@ -129,27 +129,4 @@
color: rgb(var(--danger-6));
}
}
- .ms-more-action-trigger-content {
- @apply flex items-center;
- .more-icon-btn {
- padding: 2px;
- border-radius: var(--border-radius-mini);
- &:hover {
- background-color: rgb(var(--primary-9)) !important;
- .arco-icon {
- color: rgb(var(--primary-5)) !important;
- }
- }
- }
- }
- .ms-more-action-trigger-content--focus {
- .more-icon-btn {
- @apply !visible;
-
- background-color: rgb(var(--primary-9));
- .arco-icon {
- color: rgb(var(--primary-5));
- }
- }
- }
diff --git a/frontend/src/components/pure/ms-tree-select/index.vue b/frontend/src/components/pure/ms-tree-select/index.vue
index 5b71bf6315..d71fccc3ed 100644
--- a/frontend/src/components/pure/ms-tree-select/index.vue
+++ b/frontend/src/components/pure/ms-tree-select/index.vue
@@ -44,8 +44,9 @@
{{ nodeData.name }}
{{
checkedKeys.includes(nodeData.id)
@@ -78,6 +80,15 @@
: t('ms.case.associate.selectCurrent')
}}
+ handleContainChildModule(nodeData, containChildModule)
+ "
+ @close="resetFocusNodeKey"
+ @open="setFocusKey(nodeData)"
+ />
@@ -92,6 +103,7 @@
import useTreeSelection from '@/components/business/ms-associate-case/useTreeSelection';
import MsTree from '@/components/business/ms-tree/index.vue';
import type { MsTreeFieldNames, MsTreeNodeData } from '@/components/business/ms-tree/types';
+ import MoreMenuDropdown from './moreMenuDropdown.vue';
import { useI18n } from '@/hooks/useI18n';
import useSelect from '@/hooks/useSelect';
@@ -101,12 +113,12 @@
const props = withDefaults(
defineProps<{
- data: TreeNodeData[];
fieldNames?: TreeFieldNames | MsTreeFieldNames;
multiple?: boolean;
shouldCalculateMaxTag?: boolean;
treeCheckStrictly?: boolean;
treeCheckable?: boolean;
+ showContainChildModule?: boolean;
}>(),
{
shouldCalculateMaxTag: true,
@@ -126,6 +138,66 @@
const { selectedModulesMaps, checkedKeys, halfCheckedKeys, selectParent, checkNode, clearSelector } =
useTreeSelection(selectedModuleProps.value);
+ /**
+ * 设置子节点的属性值
+ * @param trees 属性数组
+ * @param targetKey 需要匹配的属性值
+ */
+ function updateChildNodesState(node: MsTreeNodeData, targetKey: keyof MsTreeNodeData, state: boolean) {
+ if (node.children) {
+ node.children.forEach((child: MsTreeNodeData) => {
+ child[targetKey] = state;
+ updateChildNodesState(child, targetKey, state);
+ });
+ }
+ }
+
+ function handleCheck(_checkedKeys: Array, checkedNodes: MsTreeNodeData) {
+ if (props.showContainChildModule) {
+ const realNode = findNodeByKey(treeData.value, checkedNodes.node.id, 'id');
+ if (!realNode) return;
+ if (checkedNodes.checked) {
+ // 父级勾选,且父级“包含新增子模块”勾选,那么下面所有子级:禁用和勾选“包含新增子模块”
+ if (realNode.containChildModule) {
+ updateChildNodesState(realNode, 'containChildModule', true);
+ updateChildNodesState(realNode, 'disabled', true);
+ }
+ } else {
+ // 父级取消勾选,父级和所有子级“包含新增子模块”取消勾选,所有子级取消禁用
+ realNode.containChildModule = false;
+ updateChildNodesState(realNode, 'containChildModule', false);
+ updateChildNodesState(realNode, 'disabled', false);
+ }
+ }
+ checkNode(_checkedKeys, checkedNodes);
+ }
+
+ function handleSelectCurrent(nodeData: MsTreeNodeData) {
+ if (props.showContainChildModule && checkedKeys.value.includes(nodeData.id)) {
+ // 取消当前,“包含新增子模块”取消勾选,下面一层的子级取消禁用
+ const realNode = findNodeByKey(treeData.value, nodeData.id, 'id');
+ if (!realNode) return;
+ realNode.containChildModule = false;
+ realNode.children?.forEach((child) => {
+ child.disabled = false;
+ });
+ }
+ selectParent(nodeData, !!checkedKeys.value.includes(nodeData.id));
+ }
+
+ function handleContainChildModule(nodeData: MsTreeNodeData, containChildModule: boolean) {
+ const realNode = findNodeByKey(treeData.value, nodeData.id, 'id');
+ if (!realNode) return;
+ realNode.containChildModule = containChildModule;
+ if (containChildModule) {
+ handleCheck(checkedKeys.value, { checked: true, node: realNode });
+ } else {
+ realNode.children?.forEach((child) => {
+ child.disabled = false;
+ });
+ }
+ }
+
const skipSelectValueWatch = ref(false);
watch(
() => selectValue.value,
@@ -170,7 +242,7 @@
}
);
watch(
- () => props.data,
+ () => treeData.value,
() => {
if (props.shouldCalculateMaxTag !== false && props.multiple) {
calculateMaxTag();
@@ -182,11 +254,11 @@
return () => {
let treeSelectTooltip = '';
const values = Array.isArray(checkedKeys.value) ? checkedKeys.value : [checkedKeys.value];
- if (props.data) {
+ if (treeData.value) {
treeSelectTooltip = values
?.map((valueItem: string | number) => {
const optItem = findNodeByKey(
- props.data as MsTreeNodeData[],
+ treeData.value as MsTreeNodeData[],
valueItem,
props?.fieldNames?.key
);
@@ -272,6 +344,14 @@
buffer: 15, // 缓冲区默认 10 的时候,虚拟滚动的底部 padding 计算有问题
};
});
+
+ const focusNodeKey = ref('');
+ function setFocusKey(node: MsTreeNodeData) {
+ focusNodeKey.value = node.id || '';
+ }
+ function resetFocusNodeKey() {
+ focusNodeKey.value = '';
+ }