From f96eddc20355ac14c6aa917eb2a7cdd1d4dab7d3 Mon Sep 17 00:00:00 2001
From: zhengyiming <540361168@qq.com>
Date: 星期二, 11 十一月 2025 16:45:55 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master' into dev-1.3.0.2

---
 src/views/Permission/components/dialogAuthorizeV2.vue |  356 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 356 insertions(+), 0 deletions(-)

diff --git a/src/views/Permission/components/dialogAuthorizeV2.vue b/src/views/Permission/components/dialogAuthorizeV2.vue
new file mode 100644
index 0000000..71bfb25
--- /dev/null
+++ b/src/views/Permission/components/dialogAuthorizeV2.vue
@@ -0,0 +1,356 @@
+<template>
+  <ProDialog
+    class="custom-dialog"
+    width="55%"
+    :title="dialogTitle"
+    v-model="visible"
+    :top="'10vh'"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+  >
+    <div class="authorize-wrapper">
+      <div class="container-wrapper left-wrapper">
+        <el-scrollbar>
+          <el-tree
+            class="companyTree"
+            :data="menusTree"
+            :props="{
+              children: 'children',
+              label: 'name',
+            }"
+            node-key="id"
+            :expand-on-click-node="false"
+            :highlight-current="true"
+            default-expand-all
+            show-checkbox
+            ref="moduleTree"
+            :default-checked-keys="defaultCheckedKeys"
+            @check="handleModuleCheck"
+          >
+            <template #default="{ node }">
+              <div class="custom-tree-node">
+                <type-tip :isMenu="node.data.type === EnumMenuType.Menu" />
+                <div class="node-text" @click="handleSelectModule(node.data)">
+                  {{ node.label }}
+                </div>
+              </div>
+            </template>
+          </el-tree>
+        </el-scrollbar>
+      </div>
+
+      <div class="container-wrapper">
+        <div class="type-wrapper">
+          {{ SubModuleTitle[SubModuleType.PageButton] }}
+        </div>
+        <el-scrollbar>
+          <el-tree
+            v-show="!!state.currentMenuId"
+            :data="[
+              {
+                name: '鍏ㄩ��',
+                id: 'pageButtonAll',
+                children: menuPageButtons,
+              },
+            ]"
+            :props="{
+              children: 'children',
+              label: 'name',
+            }"
+            node-key="id"
+            :expand-on-click-node="false"
+            :highlight-current="true"
+            default-expand-all
+            show-checkbox
+            ref="pageButtonTree"
+            :default-checked-keys="defaultCheckedKeys"
+            @check="handlePageButtonCheck"
+          >
+            <template #default="{ node }">
+              <div class="custom-tree-node">
+                <span>{{ node.label }}</span>
+              </div>
+            </template>
+          </el-tree>
+        </el-scrollbar>
+      </div>
+
+      <div class="container-wrapper">
+        <div class="type-wrapper">
+          {{ SubModuleTitle[SubModuleType.DataButton] }}
+        </div>
+        <el-scrollbar>
+          <el-tree
+            v-show="!!state.currentMenuId"
+            :data="[
+              {
+                name: '鍏ㄩ��',
+                id: 'dataButtonAll',
+                children: menuDataButtons,
+              },
+            ]"
+            :props="{
+              children: 'children',
+              label: 'name',
+            }"
+            node-key="id"
+            :expand-on-click-node="false"
+            :highlight-current="true"
+            default-expand-all
+            show-checkbox
+            ref="dataButtonTree"
+            :default-checked-keys="defaultCheckedKeys"
+            @check="handleDataButtonCheck"
+          >
+            <template #default="{ node }">
+              <div class="custom-tree-node">
+                <span>{{ node.label }}</span>
+              </div>
+            </template>
+          </el-tree>
+        </el-scrollbar>
+      </div>
+
+      <div class="container-wrapper">
+        <div class="type-wrapper">
+          {{ SubModuleTitle[SubModuleType.Column] }}
+        </div>
+        <el-scrollbar>
+          <el-tree
+            v-show="!!state.currentMenuId"
+            :data="[
+              {
+                name: '鍏ㄩ��',
+                id: 'dataColumnAll',
+                children: menuFields,
+              },
+            ]"
+            :props="{
+              children: 'children',
+              label: 'name',
+            }"
+            node-key="id"
+            :expand-on-click-node="false"
+            :highlight-current="true"
+            default-expand-all
+            show-checkbox
+            ref="dataColumnTree"
+            :default-checked-keys="defaultCheckedKeys"
+            @check="handleDataColumnCheck"
+          >
+            <template #default="{ node }">
+              <div class="custom-tree-node">
+                <span>{{ node.label }}</span>
+              </div>
+            </template>
+          </el-tree>
+        </el-scrollbar>
+      </div>
+    </div>
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button @click="visible = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="handleConfirm" class="btn-submit"> 纭畾 </el-button>
+      </span>
+    </template>
+  </ProDialog>
+</template>
+
+<script setup lang="ts">
+import { Message } from '@bole-core/core';
+import { SubModuleType, SubModuleTitle, EnumMenuType } from '@/constants';
+import { getTree, treeEach } from '@/utils';
+import { TreeInstance } from 'element-plus';
+import { ProDialog } from '@bole-core/components';
+import { useMenus, useMenu } from '@/hooks';
+import data from '@iconify-icons/ep/tickets';
+
+const TypeTip = defineComponent({
+  name: 'TypeTip',
+  props: ['isMenu'],
+  render() {
+    const { isMenu } = this;
+    const tipText = isMenu ? `鑿滃崟` : '椤甸潰';
+    return h(
+      'span',
+      {
+        class: 'tip-text',
+        style: {
+          color: '#EB6100',
+        },
+      },
+      '[' + tipText + ']'
+    );
+  },
+});
+
+type Props = {
+  authorizeType: 'Role' | 'User';
+};
+
+const props = withDefaults(defineProps<Props>(), {});
+
+const visible = defineModel({ type: Boolean });
+
+type Form = {
+  title?: string;
+  detail: API.GetRoleQueryResult;
+};
+
+const form = defineModel<Form>('form');
+
+const emit = defineEmits<{
+  (e: 'onConfirm', selectedMenuIds: string[]): void;
+  (e: 'onCancel'): void;
+}>();
+
+type CheckedResourceItem = {
+  resourceId: string;
+  menuId: string;
+  resourceType: SubModuleType;
+};
+
+const state = reactive({
+  currentMenuId: '',
+  selectedMenuIds: [] as string[],
+});
+
+const defaultCheckedKeys = computed(() => Array.from(state.selectedMenuIds));
+
+watch(visible, (newVal) => {
+  if (newVal) {
+    state.currentMenuId = '';
+    const menuIds = form.value.detail?.menuIds ?? [];
+    // menuIds.forEach((id) => state.selectedMenuIds.add(id));
+    state.selectedMenuIds = [...menuIds];
+  }
+});
+
+const dialogTitle = computed(() =>
+  props.authorizeType === 'Role' ? '瑙掕壊鍔熻兘鎺堟潈' : '璐﹀彿鍔熻兘鎺堟潈'
+);
+
+const moduleTree = useTemplateRef<TreeInstance>('moduleTree');
+const pageButtonTree = useTemplateRef<TreeInstance>('pageButtonTree');
+const dataButtonTree = useTemplateRef<TreeInstance>('dataButtonTree');
+const dataColumnTree = useTemplateRef<TreeInstance>('dataColumnTree');
+
+type TreeRef = ReturnType<typeof useTemplateRef<TreeInstance>>;
+
+const { menusTree, getMenuById } = useMenus({
+  params: computed(() => ({
+    userType: form.value.detail?.userType,
+    clientType: form.value.detail?.clientType,
+    enterpriseType: form.value.detail?.enterpriseType,
+    roleId: form.value.detail?.id,
+  })),
+  enabled: computed(() => !!form.value.detail?.id),
+});
+
+const { menuFields, menuPageButtons, menuDataButtons } = useMenu({
+  params: computed(() => ({
+    id: state.currentMenuId,
+    roleId: form.value.detail?.id,
+  })),
+  enabled: computed(() => !!state.currentMenuId),
+});
+
+function handleSelectModule(menu: API.GetMenusQueryResultItem) {
+  state.currentMenuId = menu.id;
+}
+
+function handleModuleCheck(data, params) {
+  handleCheck(data, params, moduleTree);
+}
+
+function handlePageButtonCheck(data, params) {
+  handleCheck(data, params, pageButtonTree);
+}
+
+function handleDataButtonCheck(data, params) {
+  handleCheck(data, params, dataButtonTree);
+}
+
+function handleDataColumnCheck(data, params) {
+  handleCheck(data, params, dataColumnTree);
+}
+
+function handleCheck(data, params, treeRef: TreeRef) {
+  const dataMap = {};
+  treeEach(
+    [treeRef.value.store.root],
+    (node) => (dataMap[node.key] = node),
+    (node) => node.childNodes
+  );
+
+  const uncachedCheckedKeys = params.checkedKeys.filter(
+    (item) => !['pageButtonAll', 'dataButtonAll', 'dataColumnAll'].includes(item)
+  );
+  const cachedKeys = state.selectedMenuIds.filter(
+    (item) => !(item in dataMap) && !uncachedCheckedKeys.includes(item)
+  );
+  state.selectedMenuIds = cachedKeys.concat(uncachedCheckedKeys);
+}
+
+function handleConfirm() {
+  emit('onConfirm', state.selectedMenuIds);
+}
+</script>
+
+<style lang="scss" scoped>
+:deep(.custom-dialog) {
+  min-width: 900px;
+}
+
+.authorize-wrapper {
+  display: flex;
+
+  height: 500px;
+  border-bottom: 2px solid #f5f5f5;
+  background: #dddddd;
+
+  .container-wrapper {
+    width: calc(25%);
+    border-right: 2px solid #f5f5f5;
+    // margin-right: 7px;
+    background: #ffffff;
+
+    .type-wrapper {
+      display: flex;
+      justify-content: flex-start;
+      align-items: center;
+      padding: 10px 16px;
+      border-bottom: 2px solid #f5f5f5;
+      color: #333333;
+    }
+
+    &:last-of-type {
+      margin-right: 0px;
+    }
+
+    &.left-wrapper {
+      margin-right: 7px;
+      padding-top: 10px;
+      width: calc(35% - 7px);
+
+      :deep(.el-scrollbar) {
+        width: 100%;
+        height: 98%;
+      }
+    }
+
+    :deep(.el-scrollbar) {
+      width: 100%;
+      height: calc(98% - 43px);
+
+      .el-scrollbar__wrap {
+        overflow: auto;
+
+        .custom-tree-node {
+          display: flex;
+        }
+      }
+    }
+  }
+}
+</style>

--
Gitblit v1.9.1