兰宝车间质量管理系统-前端
LiuHao
2023-05-06 bf4a8543ca9f4e9ef6d13f78385f5c0f30255dc0
Merge branch 'ts' into dev

# Conflicts:
# package.json
# src/layout/components/TagsView/index.vue
已修改23个文件
403 ■■■■■ 文件已修改
package.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/oss/index.ts 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/ossConfig/index.ts 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/styles/sidebar.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/DictTag/index.vue 90 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Editor/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/FileUpload/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/IconSelect/index.vue 45 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/ImageUpload/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/TopNav/index.vue 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/AppMain.vue 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/TagsView/ScrollPane.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/TagsView/index.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/index.vue 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/plugins/download.ts 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.ts 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/types/router.d.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/dept/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/role/authUser.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/role/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/user/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/tool/gen/editTable.vue 79 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/tool/gen/genInfoForm.vue 69 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json
@@ -70,11 +70,11 @@
    "unplugin-auto-import": "0.13.0",
    "unplugin-icons": "0.15.1",
    "unplugin-vue-components": "0.23.0",
    "vite": "4.3.1",
    "vite-plugin-compression": "0.5.1",
    "vite-plugin-svg-icons": "2.0.1",
    "vite-plugin-vue-setup-extend": "^0.4.0",
    "vitest": "^0.29.7",
    "vite": "4.3.1",
    "vue-eslint-parser": "9.1.0",
    "vue-tsc": "0.35.0"
  }
src/api/system/oss/index.ts
@@ -5,7 +5,7 @@
// 查询OSS对象存储列表
export function listOss(query: OssQuery): AxiosPromise<OssVO[]> {
  return request({
    url: '/system/oss/list',
    url: '/resource/oss/list',
    method: 'get',
    params: query
  });
@@ -14,7 +14,7 @@
// 查询OSS对象基于id串
export function listByIds(ossId: string | number): AxiosPromise<OssVO[]> {
  return request({
    url: '/system/oss/listByIds/' + ossId,
    url: '/resource/oss/listByIds/' + ossId,
    method: 'get'
  });
}
@@ -22,7 +22,7 @@
// 删除OSS对象存储
export function delOss(ossId: string | number | Array<string | number>) {
  return request({
    url: '/system/oss/' + ossId,
    url: '/resource/oss/' + ossId,
    method: 'delete'
  });
}
src/api/system/ossConfig/index.ts
@@ -5,7 +5,7 @@
// 查询对象存储配置列表
export function listOssConfig(query: OssConfigQuery): AxiosPromise<OssConfigVO[]> {
  return request({
    url: '/system/oss/config/list',
    url: '/resource/oss/config/list',
    method: 'get',
    params: query
  });
@@ -14,7 +14,7 @@
// 查询对象存储配置详细
export function getOssConfig(ossConfigId: string | number): AxiosPromise<OssConfigVO> {
  return request({
    url: '/system/oss/config/' + ossConfigId,
    url: '/resource/oss/config/' + ossConfigId,
    method: 'get'
  });
}
@@ -22,7 +22,7 @@
// 新增对象存储配置
export function addOssConfig(data: OssConfigForm) {
  return request({
    url: '/system/oss/config',
    url: '/resource/oss/config',
    method: 'post',
    data: data
  });
@@ -31,7 +31,7 @@
// 修改对象存储配置
export function updateOssConfig(data: OssConfigForm) {
  return request({
    url: '/system/oss/config',
    url: '/resource/oss/config',
    method: 'put',
    data: data
  });
@@ -40,7 +40,7 @@
// 删除对象存储配置
export function delOssConfig(ossConfigId: string | number | Array<string | number>) {
  return request({
    url: '/system/oss/config/' + ossConfigId,
    url: '/resource/oss/config/' + ossConfigId,
    method: 'delete'
  });
}
@@ -53,7 +53,7 @@
    configKey
  };
  return request({
    url: '/system/oss/config/changeStatus',
    url: '/resource/oss/config/changeStatus',
    method: 'put',
    data: data
  });
src/assets/styles/sidebar.scss
@@ -1,6 +1,6 @@
#app {
  .main-container {
    min-height: 100%;
    height: 100%;
    transition: margin-left 0.28s;
    margin-left: $base-sidebar-width;
    position: relative;
src/components/DictTag/index.vue
@@ -2,13 +2,9 @@
  <div>
    <template v-for="(item, index) in options">
      <template v-if="values.includes(item.value)">
        <span
          v-if="item.elTagType == 'default' || item.elTagType == ''"
          :key="item.value"
          :index="index"
          :class="item.elTagClass"
          >{{ item.label }}</span
        >
        <span v-if="item.elTagType == 'default' || item.elTagType == ''" :key="item.value" :index="index" :class="item.elTagClass">
          {{ item.label + " " }}
        </span>
        <el-tag
          v-else
          :disable-transitions="true"
@@ -16,9 +12,13 @@
          :index="index"
          :type="item.elTagType === 'primary' ? '' : item.elTagType"
          :class="item.elTagClass"
          >{{ item.label }}</el-tag
        >
          {{ item.label + " " }}
        </el-tag>
      </template>
    </template>
    <template v-if="unmatch && showValue">
      {{ unmatchArray }}
    </template>
  </div>
</template>
@@ -26,23 +26,71 @@
<script setup lang="ts">
import { PropType } from 'vue';
const props = defineProps({
    // 数据
    options: {
        type: Array as PropType<DictDataOption[]>,
        default: null,
    },
    // 当前的值
    value: [Number, String, Array],
})
  // 数据
  options: {
    type: Array as PropType<DictDataOption[]>,
    default: null,
  },
  // 当前的值
  value: [Number, String, Array] as PropType<number | string | Array<number | string>>,
  // 当未找到匹配的数据时,显示value
  showValue: {
    type: Boolean as PropType<boolean>,
    default: true,
  },
});
const values = computed(() => {
    if (props.value !== null && typeof props.value !== 'undefined') {
        return Array.isArray(props.value) ? props.value : [String(props.value)];
    } else {
        return [];
  if (props.value !== null && typeof props.value !== "undefined") {
    return Array.isArray(props.value) ? props.value : [String(props.value)];
  } else {
    return [];
  }
});
const unmatch = computed(() => {
  if (props.value !== null && typeof props.value !== "undefined") {
    // 传入值为非数组
    if (!Array.isArray(props.value)) {
      if (props.options.some((v) => v.value == props.value)) {
        return false;
      }
      return true;
    }
})
    return true;
  }
  // 没有value不显示
  return false;
});
const unmatchArray = computed(() => {
// 记录未匹配的项
  const itemUnmatchArray: Array<string | number> = [];
  if (props.value !== null && typeof props.value !== "undefined") {
    // 传入值为非数组
    if (!Array.isArray(props.value)) {
      itemUnmatchArray.push(props.value);
    } else {
      // 传入值为Array
      props.value.forEach((item) => {
        if (!props.options.some((v) => v.value == item)) {
          itemUnmatchArray.push(item);
        }
      });
    }
  }
  // 没有value不显示
  return handleArray(itemUnmatchArray);
});
const handleArray = (array: Array<string | number>) => {
  if (array.length === 0) return "";
  return array.reduce((pre, cur) => {
    return pre + " " + cur;
  });
}
</script>
<style scoped>
src/components/Editor/index.vue
@@ -68,7 +68,7 @@
const upload = reactive<UploadOption>({
    headers: { Authorization: "Bearer " + getToken() },
    url: import.meta.env.VITE_APP_BASE_API + '/system/oss/upload'
    url: import.meta.env.VITE_APP_BASE_API + '/resource/oss/upload'
})
const myQuillEditor = ref();
src/components/FileUpload/index.vue
@@ -78,7 +78,7 @@
const uploadList = ref<any[]>([]);
const baseUrl = import.meta.env.VITE_APP_BASE_API;
const uploadFileUrl = ref(baseUrl + "/system/oss/upload"); // 上传文件服务器地址
const uploadFileUrl = ref(baseUrl + "/resource/oss/upload"); // 上传文件服务器地址
const headers = ref({ Authorization: "Bearer " + getToken() });
const fileList = ref<any[]>([]);
src/components/IconSelect/index.vue
@@ -2,7 +2,7 @@
  <div class="relative" :style="{ width: width }">
    <el-input v-model="modelValue" readonly @click="visible = !visible" placeholder="点击选择图标">
      <template #prepend>
        <svg-icon :icon-class="modelValue as string"></svg-icon>
        <svg-icon :icon-class="modelValue as string" />
      </template>
    </el-input>
@@ -19,7 +19,7 @@
      <el-scrollbar height="w-[200px]">
        <ul class="icon-list">
          <el-tooltip v-for="(iconName, index) in iconNames" :key="index" :content="iconName" placement="bottom" effect="light">
            <li class="icon-item" @click="selectedIcon(iconName)">
            <li :class="['icon-item', {active: modelValue == iconName}]" @click="selectedIcon(iconName)">
              <svg-icon color="var(--el-text-color-regular)" :icon-class="iconName" />
            </li>
          </el-tooltip>
@@ -33,15 +33,15 @@
import icons from '@/components/IconSelect/requireIcons';
const props = defineProps({
    modelValue: {
        type: String,
        require: true
    },
    width: {
        type: String,
        require: false,
        default: '400px'
    }
  modelValue: {
    type: String,
    require: true
  },
  width: {
    type: String,
    require: false,
    default: '400px'
  }
});
const emit = defineEmits(['update:modelValue']);
@@ -55,22 +55,21 @@
 * 筛选图标
 */
const filterIcons = () => {
    if (filterValue.value) {
        iconNames.value = icons.filter(iconName =>
            iconName.includes(filterValue.value)
        );
    } else {
        iconNames.value = icons;
    }
  if (filterValue.value) {
    iconNames.value = icons.filter(iconName =>
      iconName.includes(filterValue.value)
    );
  } else {
    iconNames.value = icons;
  }
}
/**
 * 选择图标
 * @param iconName 选择的图标名称
 */
const selectedIcon = (iconName: string) => {
    emit('update:modelValue', iconName);
    visible.value = false;
  emit('update:modelValue', iconName);
  visible.value = false;
}
</script>
@@ -101,5 +100,9 @@
      transform: scaleX(1.1);
    }
  }
  .active {
      border-color: var(--el-color-primary);
      color: var(--el-color-primary);
    }
}
</style>
src/components/ImageUpload/index.vue
@@ -76,7 +76,7 @@
const dialogVisible = ref(false);
const baseUrl = import.meta.env.VITE_APP_BASE_API;
const uploadImgUrl = ref(baseUrl + "/system/oss/upload"); // 上传的图片服务器地址
const uploadImgUrl = ref(baseUrl + "/resource/oss/upload"); // 上传的图片服务器地址
const headers = ref({ Authorization: "Bearer " + getToken() });
const fileList = ref<any[]>([]);
src/components/TopNav/index.vue
@@ -104,7 +104,7 @@
  visibleNumber.value = parseInt(String(width / 85));
}
const handleSelect = (key: string, keyPath: string[]) => {
const handleSelect = (key: string) => {
  currentIndex.value = key;
  const route = routers.value.find(item => item.path === key);
  if (isHttp(key)) {
@@ -112,7 +112,13 @@
    window.open(key, "_blank");
  } else if (!route || !route.children) {
    // 没有子路由路径内部打开
    router.push({ path: key, fullPath: '' });
    const routeMenu = childrenMenus.value.find(item => item.path === key);
    if (routeMenu && routeMenu.query) {
      let query = JSON.parse(routeMenu.query);
      router.push({ path: key, query: query });
    } else {
      router.push({ path: key });
    }
    appStore.toggleSideBarHide(true);
  } else {
    // 显示左侧联动菜单
src/layout/components/AppMain.vue
@@ -56,3 +56,25 @@
  }
}
</style>
<style lang="scss">
// fix css style bug in open el-dialog
.el-popup-parent--hidden {
  .fixed-header {
    padding-right: 6px;
  }
}
::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
::-webkit-scrollbar-track {
  background-color: #f1f1f1;
}
::-webkit-scrollbar-thumb {
  background-color: #c0c0c0;
  border-radius: 3px;
}
</style>
src/layout/components/TagsView/ScrollPane.vue
@@ -96,7 +96,7 @@
    bottom: 0px;
  }
  :deep(.el-scrollbar__wrap) {
    height: 49px;
    height: 39px;
  }
}
</style>
src/layout/components/TagsView/index.vue
@@ -246,9 +246,10 @@
      position: relative;
      cursor: pointer;
      height: 26px;
      line-height: 26px;
      line-height: 23px;
      background-color: var(--el-bg-color);
      border: 1px solid var(--el-border-color-light);
      color: #495060;
      padding: 0 8px;
      font-size: 12px;
      margin-left: 5px;
src/layout/index.vue
@@ -1,17 +1,23 @@
<template>
  <div :class="classObj" class="app-wrapper" :style="{ '--current-color': theme }">
    <el-scrollbar>
      <div v-if="device === 'mobile' && sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
      <side-bar v-if="!sidebar.hide" class="sidebar-container" />
      <div :class="{ hasTagsView: needTagsView, sidebarHide: sidebar.hide }" class="main-container">
    <div v-if="device === 'mobile' && sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
    <side-bar v-if="!sidebar.hide" class="sidebar-container" />
    <div :class="{ hasTagsView: needTagsView, sidebarHide: sidebar.hide }" class="main-container">
      <!-- <el-scrollbar>
        <div :class="{ 'fixed-header': fixedHeader }">
            <navbar ref="navbarRef" @setLayout="setLayout" />
            <tags-view v-if="needTagsView" />
          <navbar ref="navbarRef" @setLayout="setLayout" />
          <tags-view v-if="needTagsView" />
        </div>
        <app-main />
        <settings ref="settingRef" />
      </el-scrollbar> -->
      <div :class="{ 'fixed-header': fixedHeader }">
        <navbar ref="navbarRef" @setLayout="setLayout" />
        <tags-view v-if="needTagsView" />
      </div>
    </el-scrollbar>
      <app-main />
      <settings ref="settingRef" />
    </div>
  </div>
</template>
@@ -54,17 +60,17 @@
const settingRef = ref(Settings);
onMounted(() => {
    nextTick(() => {
        navbarRef.value.initTenantList();
    })
  nextTick(() => {
    navbarRef.value.initTenantList();
  })
})
const handleClickOutside = () => {
    useAppStore().closeSideBar({ withoutAnimation: false })
  useAppStore().closeSideBar({ withoutAnimation: false })
}
const setLayout = () => {
    settingRef.value.openSetting();
  settingRef.value.openSetting();
}
</script>
@@ -77,18 +83,6 @@
  position: relative;
  height: 100%;
  width: 100%;
  .el-scrollbar {
    height: 100%;
  }
  :deep(.el-scrollbar__bar).is-vertical {
    z-index: 10;
  }
  :deep(.el-scrollbar__wrap) {
    overflow-x: hidden;
  }
  &.mobile.openSidebar {
    position: fixed;
src/plugins/download.ts
@@ -9,7 +9,7 @@
let downloadLoadingInstance: LoadingInstance;
export default {
  async oss(ossId: string | number) {
    const url = baseURL + '/system/oss/download/' + ossId;
    const url = baseURL + '/resource/oss/download/' + ossId;
    downloadLoadingInstance = ElLoading.service({ text: '正在下载数据,请稍候', background: 'rgba(0, 0, 0, 0.7)' });
    try {
      const res = await axios({
src/router/index.ts
@@ -134,7 +134,7 @@
    path: '/system/oss-config',
    component: Layout,
    hidden: true,
    permissions: ['monitor:job:list'],
    permissions: ['system:oss:list'],
    children: [
      {
        path: 'index',
src/types/router.d.ts
@@ -13,6 +13,7 @@
      title: string;
      icon: string;
    };
    query?: string;
  } & RouteRecordRaw;
  interface _RouteLocationBase {
src/views/system/dept/index.vue
@@ -232,7 +232,7 @@
            nextTick(() => {
                reset();
                if (row && row.deptId) {
                    form.value.parentId = row?.parentId;
                    form.value.parentId = row?.deptId;
                }
            })
        }
src/views/system/role/authUser.vue
@@ -63,7 +63,7 @@
        :total="total"
        v-model:page="queryParams.pageNum"
        v-model:limit="queryParams.pageSize"
        @pagination="handleQuery"
        @pagination="getList"
      />
      <select-user ref="selectRef" :roleId="queryParams.roleId" @ok="handleQuery" />
    </el-card>
src/views/system/role/index.vue
@@ -95,7 +95,7 @@
        v-model:total="total"
        v-model:page="queryParams.pageNum"
        v-model:limit="queryParams.pageSize"
        @pagination="handleQuery"
        @pagination="getList"
      />
    </el-card>
src/views/system/user/index.vue
@@ -146,7 +146,7 @@
            :total="total"
            v-model:page="queryParams.pageNum"
            v-model:limit="queryParams.pageSize"
            @pagination="handleQuery"
            @pagination="getList"
          />
        </el-card>
      </el-col>
src/views/tool/gen/editTable.vue
@@ -136,54 +136,53 @@
/** 提交按钮 */
const submitForm = () => {
    const basicForm = basicInfo.value.$refs.basicInfoForm;
    const genForm = genInfo.value.$refs.genInfoForm;
  const basicForm = basicInfo.value.$refs.basicInfoForm;
  const genForm = genInfo.value.$refs.genInfoForm;
    Promise.all([basicForm, genForm].map(getFormPromise)).then(async res => {
        const validateResult = res.every(item => !!item);
        if (validateResult) {
            const genTable: any = Object.assign({}, info.value);
            genTable.columns = columns.value;
            genTable.params = {
                treeCode: info.value?.treeCode,
                treeName: info.value.treeName,
                treeParentCode: info.value.treeParentCode,
                parentMenuId: info.value.parentMenuId
            };
            const response = await updateGenTable(genTable);
            proxy?.$modal.msgSuccess(response.msg);
            if (response.code === 200) {
                close();
            }
        } else {
            proxy?.$modal.msgError("表单校验未通过,请重新检查提交内容");
        }
    });
  Promise.all([basicForm, genForm].map(getFormPromise)).then(async res => {
    const validateResult = res.every(item => !!item);
    if (validateResult) {
      const genTable: any = Object.assign({}, info.value);
      genTable.columns = columns.value;
      genTable.params = {
        treeCode: info.value?.treeCode,
        treeName: info.value.treeName,
        treeParentCode: info.value.treeParentCode,
        parentMenuId: info.value.parentMenuId
      };
      const response = await updateGenTable(genTable);
      proxy?.$modal.msgSuccess(response.msg);
      if (response.code === 200) {
        close();
      }
    } else {
      proxy?.$modal.msgError("表单校验未通过,请重新检查提交内容");
    }
  });
}
const getFormPromise = (form: any) => {
    return new Promise(resolve => {
        form.validate((res: any) => {
            resolve(res);
        });
  return new Promise(resolve => {
    form.validate((res: any) => {
      resolve(res);
    });
  });
}
const close = () => {
    const obj = { path: "/tool/gen", query: { t: Date.now(), pageNum: route.query.pageNum } };
    proxy?.$tab.closeOpenPage(obj);
  const obj = {path: "/tool/gen", query: {t: Date.now(), pageNum: route.query.pageNum}};
  proxy?.$tab.closeOpenPage(obj);
}
(async () => {
    const tableId = route.params && route.params.tableId as string;
    if (tableId) {
        // 获取表详细信息
      const res = await getGenTable(tableId);
        res.data.info.parentMenuId = Number(res.data.info.parentMenuId);
        columns.value = res.data.rows;
        info.value = res.data.info;
        tables.value = res.data.tables;
        /** 查询字典下拉列表 */
        const response = await getDictOptionselect();
        dictOptions.value = response.data;
    }
  const tableId = route.params && route.params.tableId as string;
  if (tableId) {
    // 获取表详细信息
    const res = await getGenTable(tableId);
    columns.value = res.data.rows;
    info.value = res.data.info;
    tables.value = res.data.tables;
    /** 查询字典下拉列表 */
    const response = await getDictOptionselect();
    dictOptions.value = response.data;
  }
})();
</script>
src/views/tool/gen/genInfoForm.vue
@@ -226,9 +226,9 @@
import { ComponentInternalInstance, PropType } from 'vue';
interface MenuOptionsType {
    menuId: number;
    menuName: string;
    children: MenuOptionsType[] | undefined;
  menuId: number | string;
  menuName: string;
  children: MenuOptionsType[] | undefined;
}
const subColumns = ref<any>([]);
@@ -236,14 +236,14 @@
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const props = defineProps({
    info: {
        type: Object as PropType<any>,
        default: null
    },
    tables: {
        type: Array as PropType<any[]>,
        default: null
    }
  info: {
    type: Object as PropType<any>,
    default: null
  },
  tables: {
    type: Array as PropType<any[]>,
    default: null
  }
});
const infoForm = computed(() => props.info);
@@ -252,45 +252,46 @@
// 表单校验
const rules = ref({
    tplCategory: [{ required: true, message: "请选择生成模板", trigger: "blur" }],
    packageName: [{ required: true, message: "请输入生成包路径", trigger: "blur" }],
    moduleName: [{ required: true, message: "请输入生成模块名", trigger: "blur" }],
    businessName: [{ required: true, message: "请输入生成业务名", trigger: "blur" }],
    functionName: [{ required: true, message: "请输入生成功能名", trigger: "blur" }]
  tplCategory: [{required: true, message: "请选择生成模板", trigger: "blur"}],
  packageName: [{required: true, message: "请输入生成包路径", trigger: "blur"}],
  moduleName: [{required: true, message: "请输入生成模块名", trigger: "blur"}],
  businessName: [{required: true, message: "请输入生成业务名", trigger: "blur"}],
  functionName: [{required: true, message: "请输入生成功能名", trigger: "blur"}]
});
const subSelectChange = () => {
    infoForm.value.subTableFkName = "";
  infoForm.value.subTableFkName = "";
}
const tplSelectChange = (value: string) => {
    if (value !== "sub") {
        infoForm.value.subTableName = "";
        infoForm.value.subTableFkName = "";
    }
  if (value !== "sub") {
    infoForm.value.subTableName = "";
    infoForm.value.subTableFkName = "";
  }
}
const setSubTableColumns = (value: string) => {
    table.value.forEach(item => {
        const name = item.tableName;
        if (value === name) {
            subColumns.value = item.columns;
            return;
        }
    })
  table.value.forEach(item => {
    const name = item.tableName;
    if (value === name) {
      subColumns.value = item.columns;
      return;
    }
  })
}
/** 查询菜单下拉树结构 */
const getMenuTreeselect = async () => {
    const res = await listMenu();
    const data = proxy?.handleTree<MenuOptionsType>(res.data, "menuId");
  const res = await listMenu();
  res.data.forEach(m => m.menuId = m.menuId.toString());
  const data = proxy?.handleTree<MenuOptionsType>(res.data, "menuId");
  if (data) {
        menuOptions.value = data
    }
    menuOptions.value = data
  }
}
watch(() => props.info.subTableName, val => {
    setSubTableColumns(val);
  setSubTableColumns(val);
});
onMounted(() => {
    getMenuTreeselect();
  getMenuTreeselect();
})
</script>