weixin_52219567 4 сар өмнө
parent
commit
eb42c26c76
65 өөрчлөгдсөн 0 нэмэгдсэн , 13897 устгасан
  1. 0 28
      src/layout/components/IframeToggle/index.vue
  2. 0 15
      src/layout/components/InnerLink/index.vue
  3. 0 308
      src/layout/components/Navbar.vue
  4. 0 246
      src/layout/components/Settings/index.vue
  5. 0 40
      src/layout/components/Sidebar/Link.vue
  6. 0 95
      src/layout/components/Sidebar/Logo.vue
  7. 0 101
      src/layout/components/Sidebar/SidebarItem.vue
  8. 0 56
      src/layout/components/Sidebar/index.vue
  9. 0 95
      src/layout/components/SocialCallback/index.vue
  10. 0 102
      src/layout/components/TagsView/ScrollPane.vue
  11. 0 347
      src/layout/components/TagsView/index.vue
  12. 0 158
      src/layout/components/TopBar/search.vue
  13. 0 5
      src/layout/components/index.ts
  14. 0 130
      src/layout/components/notice/index.vue
  15. 0 19
      src/router/index.ts
  16. 0 245
      src/views/demo/demo/index.vue
  17. 0 259
      src/views/demo/tree/index.vue
  18. 0 314
      src/views/login copy.vue
  19. 0 9
      src/views/monitor/admin/index.vue
  20. 0 192
      src/views/monitor/cache/index.vue
  21. 0 209
      src/views/monitor/logininfor/index.vue
  22. 0 117
      src/views/monitor/online/index.vue
  23. 0 261
      src/views/monitor/operlog/index.vue
  24. 0 111
      src/views/monitor/operlog/oper-info-dialog.vue
  25. 0 9
      src/views/monitor/snailjob/index.vue
  26. 0 316
      src/views/system/client/index.vue
  27. 0 261
      src/views/system/config/index.vue
  28. 0 320
      src/views/system/dept/index.vue
  29. 0 309
      src/views/system/dict/data.vue
  30. 0 246
      src/views/system/dict/index.vue
  31. 0 540
      src/views/system/menu/index.vue
  32. 0 243
      src/views/system/notice/index.vue
  33. 0 344
      src/views/system/oss/config.vue
  34. 0 333
      src/views/system/oss/index.vue
  35. 0 361
      src/views/system/post/index.vue
  36. 0 158
      src/views/system/role/authUser.vue
  37. 0 503
      src/views/system/role/index.vue
  38. 0 130
      src/views/system/role/selectUser.vue
  39. 0 382
      src/views/system/tenant/index.vue
  40. 0 329
      src/views/system/tenantPackage/index.vue
  41. 0 146
      src/views/system/user/authRole.vue
  42. 0 679
      src/views/system/user/index.vue
  43. 0 122
      src/views/system/user/profile/index.vue
  44. 0 57
      src/views/system/user/profile/onlineDevice.vue
  45. 0 73
      src/views/system/user/profile/resetPwd.vue
  46. 0 145
      src/views/system/user/profile/thirdParty.vue
  47. 0 182
      src/views/system/user/profile/userAvatar.vue
  48. 0 69
      src/views/system/user/profile/userInfo.vue
  49. 0 49
      src/views/tool/gen/basicInfoForm.vue
  50. 0 198
      src/views/tool/gen/editTable.vue
  51. 0 294
      src/views/tool/gen/genInfoForm.vue
  52. 0 122
      src/views/tool/gen/importTable.vue
  53. 0 259
      src/views/tool/gen/index.vue
  54. 0 254
      src/views/workflow/category/index.vue
  55. 0 236
      src/views/workflow/leave/index.vue
  56. 0 286
      src/views/workflow/leave/leaveEdit.vue
  57. 0 46
      src/views/workflow/processDefinition/design.vue
  58. 0 562
      src/views/workflow/processDefinition/index.vue
  59. 0 478
      src/views/workflow/processInstance/index.vue
  60. 0 360
      src/views/workflow/spel/index.vue
  61. 0 279
      src/views/workflow/task/allTaskWaiting.vue
  62. 0 246
      src/views/workflow/task/myDocument.vue
  63. 0 138
      src/views/workflow/task/taskCopyList.vue
  64. 0 186
      src/views/workflow/task/taskFinish.vue
  65. 0 185
      src/views/workflow/task/taskWaiting.vue

+ 0 - 28
src/layout/components/IframeToggle/index.vue

@@ -1,28 +0,0 @@
-<template>
-  <inner-link
-    v-for="(item, index) in tagsViewStore.iframeViews"
-    v-show="route.path === item.path"
-    :key="item.path"
-    :iframe-id="'iframe' + index"
-    :src="iframeUrl(item.meta ? item.meta.link : '', item.query)"
-  ></inner-link>
-</template>
-
-<script setup lang="ts">
-import InnerLink from '../InnerLink/index.vue';
-
-import { useTagsViewStore } from '@/store/modules/tagsView';
-
-const route = useRoute();
-const tagsViewStore = useTagsViewStore();
-
-function iframeUrl(url: string | undefined, query: any) {
-  if (Object.keys(query).length > 0) {
-    const params = Object.keys(query)
-      .map((key) => key + '=' + query[key])
-      .join('&');
-    return url + '?' + params;
-  }
-  return url;
-}
-</script>

+ 0 - 15
src/layout/components/InnerLink/index.vue

@@ -1,15 +0,0 @@
-<template>
-  <div :style="'height:' + height">
-    <iframe :id="iframeId" style="width: 100%; height: 100%; border: 0" :src="src"></iframe>
-  </div>
-</template>
-
-<script setup lang="ts">
-import { propTypes } from '@/utils/propTypes';
-
-const props = defineProps({
-  src: propTypes.string.def('/'),
-  iframeId: propTypes.string.isRequired
-});
-const height = ref(document.documentElement.clientHeight - 94.5 + 'px');
-</script>

+ 0 - 308
src/layout/components/Navbar.vue

@@ -1,308 +0,0 @@
-<template>
-  <div class="navbar">
-    <hamburger id="hamburger-container" :is-active="appStore.sidebar.opened" class="hamburger-container" @toggle-click="toggleSideBar" />
-    <breadcrumb v-if="!settingsStore.topNav" id="breadcrumb-container" class="breadcrumb-container" />
-    <top-nav v-if="settingsStore.topNav" id="topmenu-container" class="topmenu-container" />
-
-    <div class="right-menu flex align-center">
-      <template v-if="appStore.device !== 'mobile'">
-        <el-select
-          v-if="userId === 1 && tenantEnabled"
-          v-model="companyName"
-          class="min-w-244px"
-          clearable
-          filterable
-          reserve-keyword
-          :placeholder="proxy.$t('navbar.selectTenant')"
-          @change="dynamicTenantEvent"
-          @clear="dynamicClearEvent"
-        >
-          <el-option v-for="item in tenantList" :key="item.tenantId" :label="item.companyName" :value="item.tenantId"> </el-option>
-          <template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template>
-        </el-select>
-
-        <search-menu ref="searchMenuRef" />
-        <el-tooltip content="搜索" effect="dark" placement="bottom">
-          <div class="right-menu-item hover-effect" @click="openSearchMenu">
-            <svg-icon class-name="search-icon" icon-class="search" />
-          </div>
-        </el-tooltip>
-        <!-- 消息 -->
-        <el-tooltip :content="proxy.$t('navbar.message')" effect="dark" placement="bottom">
-          <div>
-            <el-popover placement="bottom" trigger="click" transition="el-zoom-in-top" :width="300" :persistent="false">
-              <template #reference>
-                <el-badge :value="newNotice > 0 ? newNotice : ''" :max="99">
-                  <div class="right-menu-item hover-effect" style="display: block"><svg-icon icon-class="message" /></div>
-                </el-badge>
-              </template>
-              <template #default>
-                <notice></notice>
-              </template>
-            </el-popover>
-          </div>
-        </el-tooltip>
-        <el-tooltip content="Github" effect="dark" placement="bottom">
-          <ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />
-        </el-tooltip>
-
-        <el-tooltip :content="proxy.$t('navbar.document')" effect="dark" placement="bottom">
-          <ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" />
-        </el-tooltip>
-
-        <el-tooltip :content="proxy.$t('navbar.full')" effect="dark" placement="bottom">
-          <screenfull id="screenfull" class="right-menu-item hover-effect" />
-        </el-tooltip>
-
-        <el-tooltip :content="proxy.$t('navbar.language')" effect="dark" placement="bottom">
-          <lang-select id="lang-select" class="right-menu-item hover-effect" />
-        </el-tooltip>
-
-        <el-tooltip :content="proxy.$t('navbar.layoutSize')" effect="dark" placement="bottom">
-          <size-select id="size-select" class="right-menu-item hover-effect" />
-        </el-tooltip>
-      </template>
-      <div class="avatar-container">
-        <el-dropdown class="right-menu-item hover-effect" trigger="click" @command="handleCommand">
-          <div class="avatar-wrapper">
-            <img :src="userStore.avatar" class="user-avatar" />
-            <el-icon><caret-bottom /></el-icon>
-          </div>
-          <template #dropdown>
-            <el-dropdown-menu>
-              <router-link v-if="!dynamic" to="/user/profile">
-                <el-dropdown-item>{{ proxy.$t('navbar.personalCenter') }}</el-dropdown-item>
-              </router-link>
-              <el-dropdown-item v-if="settingsStore.showSettings" command="setLayout">
-                <span>{{ proxy.$t('navbar.layoutSetting') }}</span>
-              </el-dropdown-item>
-              <el-dropdown-item divided command="logout">
-                <span>{{ proxy.$t('navbar.logout') }}</span>
-              </el-dropdown-item>
-            </el-dropdown-menu>
-          </template>
-        </el-dropdown>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-import SearchMenu from './TopBar/search.vue';
-import { useAppStore } from '@/store/modules/app';
-import { useUserStore } from '@/store/modules/user';
-import { useSettingsStore } from '@/store/modules/settings';
-import { useNoticeStore } from '@/store/modules/notice';
-import { getTenantList } from '@/api/login';
-import { dynamicClear, dynamicTenant } from '@/api/system/tenant';
-import { TenantVO } from '@/api/types';
-import notice from './notice/index.vue';
-import router from '@/router';
-import { ElMessageBoxOptions } from 'element-plus/es/components/message-box/src/message-box.type';
-
-const appStore = useAppStore();
-const userStore = useUserStore();
-const settingsStore = useSettingsStore();
-const noticeStore = storeToRefs(useNoticeStore());
-const newNotice = ref(<number>0);
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const userId = ref(userStore.userId);
-const companyName = ref(undefined);
-const tenantList = ref<TenantVO[]>([]);
-// 是否切换了租户
-const dynamic = ref(false);
-// 租户开关
-const tenantEnabled = ref(true);
-// 搜索菜单
-const searchMenuRef = ref<InstanceType<typeof SearchMenu>>();
-
-const openSearchMenu = () => {
-  searchMenuRef.value?.openSearch();
-};
-
-// 动态切换
-const dynamicTenantEvent = async (tenantId: string) => {
-  if (companyName.value != null && companyName.value !== '') {
-    await dynamicTenant(tenantId);
-    dynamic.value = true;
-    await proxy?.$router.push('/');
-    await proxy?.$tab.closeAllPage();
-    await proxy?.$tab.refreshPage();
-  }
-};
-
-const dynamicClearEvent = async () => {
-  await dynamicClear();
-  dynamic.value = false;
-  await proxy?.$router.push('/');
-  await proxy?.$tab.closeAllPage();
-  await proxy?.$tab.refreshPage();
-};
-
-/** 租户列表 */
-const initTenantList = async () => {
-  const { data } = await getTenantList(true);
-  tenantEnabled.value = data.tenantEnabled === undefined ? true : data.tenantEnabled;
-  if (tenantEnabled.value) {
-    tenantList.value = data.voList;
-  }
-};
-
-defineExpose({
-  initTenantList
-});
-
-const toggleSideBar = () => {
-  appStore.toggleSideBar(false);
-};
-
-const logout = async () => {
-  await ElMessageBox.confirm('确定注销并退出系统吗?', '提示', {
-    confirmButtonText: '确定',
-    cancelButtonText: '取消',
-    type: 'warning'
-  } as ElMessageBoxOptions);
-  userStore.logout().then(() => {
-    router.replace({
-      path: '/login',
-      query: {
-        redirect: encodeURIComponent(router.currentRoute.value.fullPath || '/')
-      }
-    });
-    proxy?.$tab.closeAllPage();
-  });
-};
-
-const emits = defineEmits(['setLayout']);
-const setLayout = () => {
-  emits('setLayout');
-};
-// 定义Command方法对象 通过key直接调用方法
-const commandMap: { [key: string]: any } = {
-  setLayout,
-  logout
-};
-const handleCommand = (command: string) => {
-  // 判断是否存在该方法
-  if (commandMap[command]) {
-    commandMap[command]();
-  }
-};
-//用深度监听 消息
-watch(
-  () => noticeStore.state.value.notices,
-  (newVal) => {
-    newNotice.value = newVal.filter((item: any) => !item.read).length;
-  },
-  { deep: true }
-);
-</script>
-
-<style lang="scss" scoped>
-:deep(.el-select .el-input__wrapper) {
-  height: 30px;
-}
-
-:deep(.el-badge__content.is-fixed) {
-  top: 12px;
-}
-
-.flex {
-  display: flex;
-}
-
-.align-center {
-  align-items: center;
-}
-
-.navbar {
-  height: 50px;
-  overflow: hidden;
-  position: relative;
-  //background: #fff;
-  box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
-
-  .hamburger-container {
-    line-height: 46px;
-    height: 100%;
-    float: left;
-    cursor: pointer;
-    transition: background 0.3s;
-    -webkit-tap-highlight-color: transparent;
-
-    &:hover {
-      background: rgba(0, 0, 0, 0.025);
-    }
-  }
-
-  .breadcrumb-container {
-    float: left;
-  }
-
-  .topmenu-container {
-    position: absolute;
-    left: 50px;
-  }
-
-  .errLog-container {
-    display: inline-block;
-    vertical-align: top;
-  }
-
-  .right-menu {
-    float: right;
-    height: 100%;
-    line-height: 50px;
-    display: flex;
-
-    &:focus {
-      outline: none;
-    }
-
-    .right-menu-item {
-      display: inline-block;
-      padding: 0 8px;
-      height: 100%;
-      font-size: 18px;
-      color: #5a5e66;
-      vertical-align: text-bottom;
-
-      &.hover-effect {
-        cursor: pointer;
-        transition: background 0.3s;
-
-        &:hover {
-          background: rgba(0, 0, 0, 0.025);
-        }
-      }
-    }
-
-    .avatar-container {
-      margin-right: 40px;
-
-      .avatar-wrapper {
-        margin-top: 5px;
-        position: relative;
-
-        .user-avatar {
-          cursor: pointer;
-          width: 40px;
-          height: 40px;
-          border-radius: 10px;
-          margin-top: 10px;
-        }
-
-        i {
-          cursor: pointer;
-          position: absolute;
-          right: -20px;
-          top: 25px;
-          font-size: 12px;
-        }
-      }
-    }
-  }
-}
-</style>

+ 0 - 246
src/layout/components/Settings/index.vue

@@ -1,246 +0,0 @@
-<template>
-  <el-drawer v-model="showSettings" :with-header="false" direction="rtl" size="300px" close-on-click-modal>
-    <h3 class="drawer-title">主题风格设置</h3>
-
-    <div class="setting-drawer-block-checbox">
-      <div class="setting-drawer-block-checbox-item" @click="handleTheme(SideThemeEnum.DARK)">
-        <img src="@/assets/images/dark.svg" alt="dark" />
-        <div v-if="sideTheme === 'theme-dark'" class="setting-drawer-block-checbox-selectIcon" style="display: block">
-          <i aria-label="图标: check" class="anticon anticon-check">
-            <svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true" focusable="false" class>
-              <path
-                d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"
-              />
-            </svg>
-          </i>
-        </div>
-      </div>
-      <div class="setting-drawer-block-checbox-item" @click="handleTheme(SideThemeEnum.LIGHT)">
-        <img src="@/assets/images/light.svg" alt="light" />
-        <div v-if="sideTheme === 'theme-light'" class="setting-drawer-block-checbox-selectIcon" style="display: block">
-          <i aria-label="图标: check" class="anticon anticon-check">
-            <svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true" focusable="false" class>
-              <path
-                d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"
-              />
-            </svg>
-          </i>
-        </div>
-      </div>
-    </div>
-    <div class="drawer-item">
-      <span>主题颜色</span>
-      <span class="comp-style">
-        <el-color-picker v-model="theme" :predefine="predefineColors" @change="themeChange" />
-      </span>
-    </div>
-    <div class="drawer-item">
-      <span>深色模式</span>
-      <span class="comp-style">
-        <el-switch v-model="isDark" class="drawer-switch" @change="toggleDark" />
-      </span>
-    </div>
-
-    <el-divider />
-
-    <h3 class="drawer-title">系统布局配置</h3>
-
-    <div class="drawer-item">
-      <span>开启 TopNav</span>
-      <span class="comp-style">
-        <el-switch v-model="settingsStore.topNav" class="drawer-switch" @change="topNavChange" />
-      </span>
-    </div>
-
-    <div class="drawer-item">
-      <span>开启 Tags-Views</span>
-      <span class="comp-style">
-        <el-switch v-model="settingsStore.tagsView" class="drawer-switch" />
-      </span>
-    </div>
-
-    <div class="drawer-item">
-      <span>显示页签图标</span>
-      <span class="comp-style">
-        <el-switch v-model="settingsStore.tagsIcon" :disabled="!settingsStore.tagsView" class="drawer-switch" />
-      </span>
-    </div>
-
-    <div class="drawer-item">
-      <span>固定 Header</span>
-      <span class="comp-style">
-        <el-switch v-model="settingsStore.fixedHeader" class="drawer-switch" />
-      </span>
-    </div>
-
-    <div class="drawer-item">
-      <span>显示 Logo</span>
-      <span class="comp-style">
-        <el-switch v-model="settingsStore.sidebarLogo" class="drawer-switch" />
-      </span>
-    </div>
-
-    <div class="drawer-item">
-      <span>动态标题</span>
-      <span class="comp-style">
-        <el-switch v-model="settingsStore.dynamicTitle" class="drawer-switch" @change="dynamicTitleChange" />
-      </span>
-    </div>
-
-    <el-divider />
-
-    <el-button type="primary" plain icon="DocumentAdd" @click="saveSetting">保存配置</el-button>
-    <el-button plain icon="Refresh" @click="resetSetting">重置配置</el-button>
-  </el-drawer>
-</template>
-
-<script setup lang="ts">
-import { useDynamicTitle } from '@/utils/dynamicTitle';
-import { useAppStore } from '@/store/modules/app';
-import { useSettingsStore } from '@/store/modules/settings';
-import { usePermissionStore } from '@/store/modules/permission';
-import { handleThemeStyle } from '@/utils/theme';
-import { SideThemeEnum } from '@/enums/SideThemeEnum';
-import defaultSettings from '@/settings';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const appStore = useAppStore();
-const settingsStore = useSettingsStore();
-const permissionStore = usePermissionStore();
-
-const showSettings = ref(false);
-const theme = ref(settingsStore.theme);
-const sideTheme = ref(settingsStore.sideTheme);
-const storeSettings = computed(() => settingsStore);
-const predefineColors = ref(['#e7000b', '#ff4500', '#ff8c00', '#ffd700', '#90ee90', '#00ced1', '#1e90ff', '#c71585']);
-
-// 是否暗黑模式
-const isDark = useDark({
-  storageKey: 'useDarkKey',
-  valueDark: 'dark',
-  valueLight: 'light'
-});
-// 匹配菜单颜色
-watch(isDark, () => {
-  if (isDark.value) {
-    settingsStore.sideTheme = SideThemeEnum.DARK;
-  } else {
-    settingsStore.sideTheme = sideTheme.value;
-  }
-});
-const toggleDark = () => useToggle(isDark);
-
-const topNavChange = (val: any) => {
-  if (!val) {
-    appStore.toggleSideBarHide(false);
-    permissionStore.setSidebarRouters(permissionStore.defaultRoutes as any);
-  }
-};
-
-const dynamicTitleChange = () => {
-  // 动态设置网页标题
-  useDynamicTitle();
-};
-
-const themeChange = (val: string) => {
-  settingsStore.theme = val;
-  handleThemeStyle(val);
-};
-const handleTheme = (val: string) => {
-  sideTheme.value = val;
-  if (isDark.value && val === SideThemeEnum.LIGHT) {
-    // 暗黑模式颜色不变
-    settingsStore.sideTheme = SideThemeEnum.DARK;
-    return;
-  }
-  settingsStore.sideTheme = val;
-};
-const saveSetting = () => {
-  proxy?.$modal.loading('正在保存到本地,请稍候...');
-  const settings = useStorage<LayoutSetting>('layout-setting', defaultSettings);
-  settings.value.topNav = storeSettings.value.topNav;
-  settings.value.tagsView = storeSettings.value.tagsView;
-  settings.value.tagsIcon = storeSettings.value.tagsIcon;
-  settings.value.fixedHeader = storeSettings.value.fixedHeader;
-  settings.value.sidebarLogo = storeSettings.value.sidebarLogo;
-  settings.value.dynamicTitle = storeSettings.value.dynamicTitle;
-  settings.value.sideTheme = storeSettings.value.sideTheme;
-  settings.value.theme = storeSettings.value.theme;
-  setTimeout(() => {
-    proxy?.$modal.closeLoading();
-  }, 1000);
-};
-const resetSetting = () => {
-  proxy?.$modal.loading('正在清除设置缓存并刷新,请稍候...');
-  useStorage<any>('layout-setting', null).value = null;
-  setTimeout('window.location.reload()', 1000);
-};
-const openSetting = () => {
-  showSettings.value = true;
-};
-
-defineExpose({
-  openSetting
-});
-</script>
-
-<style lang="scss" scoped>
-.setting-drawer-title {
-  margin-bottom: 12px;
-  color: rgba(0, 0, 0, 0.85);
-  line-height: 22px;
-  font-weight: bold;
-  .drawer-title {
-    font-size: 14px;
-  }
-}
-.setting-drawer-block-checbox {
-  display: flex;
-  justify-content: flex-start;
-  align-items: center;
-  margin-top: 10px;
-  margin-bottom: 20px;
-
-  .setting-drawer-block-checbox-item {
-    position: relative;
-    margin-right: 16px;
-    border-radius: 2px;
-    cursor: pointer;
-
-    img {
-      width: 48px;
-      height: 48px;
-    }
-
-    .custom-img {
-      width: 48px;
-      height: 38px;
-      border-radius: 5px;
-      box-shadow: 1px 1px 2px #898484;
-    }
-
-    .setting-drawer-block-checbox-selectIcon {
-      position: absolute;
-      top: 0;
-      right: 0;
-      width: 100%;
-      height: 100%;
-      padding-top: 15px;
-      padding-left: 24px;
-      color: #1890ff;
-      font-weight: 700;
-      font-size: 14px;
-    }
-  }
-}
-
-.drawer-item {
-  padding: 12px 0;
-  font-size: 14px;
-
-  .comp-style {
-    float: right;
-    margin: -3px 8px 0px 0px;
-  }
-}
-</style>

+ 0 - 40
src/layout/components/Sidebar/Link.vue

@@ -1,40 +0,0 @@
-<template>
-  <component :is="type" v-bind="linkProps()">
-    <slot />
-  </component>
-</template>
-
-<script setup lang="ts">
-import { isExternal } from '@/utils/validate';
-
-const props = defineProps({
-  to: {
-    type: [String, Object],
-    required: true
-  }
-});
-
-const isExt = computed(() => {
-  return isExternal(props.to as string);
-});
-
-const type = computed(() => {
-  if (isExt.value) {
-    return 'a';
-  }
-  return 'router-link';
-});
-
-function linkProps() {
-  if (isExt.value) {
-    return {
-      href: props.to,
-      target: '_blank',
-      rel: 'noopener'
-    };
-  }
-  return {
-    to: props.to
-  };
-}
-</script>

+ 0 - 95
src/layout/components/Sidebar/Logo.vue

@@ -1,95 +0,0 @@
-<template>
-  <div
-    class="sidebar-logo-container"
-    :class="{ collapse: collapse }"
-    :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }"
-  >
-    <transition :enter-active-class="proxy?.animate.logoAnimate.enter" mode="out-in">
-      <router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
-        <img v-if="logo" :src="logo" class="sidebar-logo" />
-        <h1 v-else class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">
-          {{ title }}
-        </h1>
-      </router-link>
-      <router-link v-else key="expand" class="sidebar-logo-link" to="/">
-        <img v-if="logo" :src="logo" class="sidebar-logo" />
-        <h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">
-          {{ title }}
-        </h1>
-      </router-link>
-    </transition>
-  </div>
-</template>
-
-<script setup lang="ts">
-import variables from '@/assets/styles/variables.module.scss';
-import logo from '@/assets/logo/logo.png';
-import { useSettingsStore } from '@/store/modules/settings';
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-defineProps({
-  collapse: {
-    type: Boolean,
-    required: true
-  }
-});
-
-const title = import.meta.env.VITE_APP_LOGO_TITLE;
-const settingsStore = useSettingsStore();
-const sideTheme = computed(() => settingsStore.sideTheme);
-</script>
-
-<style lang="scss" scoped>
-.sidebarLogoFade-enter-active {
-  transition: opacity 1.5s;
-}
-
-.sidebarLogoFade-enter,
-.sidebarLogoFade-leave-to {
-  opacity: 0;
-}
-
-.sidebar-logo-container {
-  position: relative;
-  width: 100%;
-  height: 50px;
-  line-height: 50px;
-  background: #2b2f3a;
-  text-align: center;
-  overflow: hidden;
-
-  & .sidebar-logo-link {
-    height: 100%;
-    width: 100%;
-
-    & .sidebar-logo {
-      width: 32px;
-      height: 32px;
-      vertical-align: middle;
-      margin-right: 12px;
-    }
-
-    & .sidebar-title {
-      display: inline-block;
-      margin: 0;
-      color: #fff;
-      font-weight: 600;
-      line-height: 50px;
-      font-size: 14px;
-      font-family:
-        Avenir,
-        Helvetica Neue,
-        Arial,
-        Helvetica,
-        sans-serif;
-      vertical-align: middle;
-    }
-  }
-
-  &.collapse {
-    .sidebar-logo {
-      margin-right: 0px;
-    }
-  }
-}
-</style>

+ 0 - 101
src/layout/components/Sidebar/SidebarItem.vue

@@ -1,101 +0,0 @@
-<template>
-  <div v-if="!item.hidden">
-    <template v-if="hasOneShowingChild(item, item.children) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.alwaysShow">
-      <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path, onlyOneChild.query)">
-        <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{ 'submenu-title-noDropdown': !isNest }">
-          <svg-icon :icon-class="onlyOneChild.meta.icon || (item.meta && item.meta.icon)" />
-          <template #title>
-            <span class="menu-title" :title="hasTitle(onlyOneChild.meta.title)">{{ onlyOneChild.meta.title }}</span>
-          </template>
-        </el-menu-item>
-      </app-link>
-    </template>
-
-    <el-sub-menu v-else ref="subMenu" :index="resolvePath(item.path)" teleported>
-      <template v-if="item.meta" #title>
-        <svg-icon :icon-class="item.meta ? item.meta.icon : ''" />
-        <span class="menu-title" :title="hasTitle(item.meta?.title)">{{ item.meta?.title }}</span>
-      </template>
-
-      <sidebar-item
-        v-for="(child, index) in item.children"
-        :key="child.path + index"
-        :is-nest="true"
-        :item="child"
-        :base-path="resolvePath(child.path)"
-        class="nest-menu"
-      />
-    </el-sub-menu>
-  </div>
-</template>
-
-<script setup lang="ts">
-import { isExternal } from '@/utils/validate';
-import AppLink from './Link.vue';
-import { getNormalPath } from '@/utils/ruoyi';
-import { RouteRecordRaw } from 'vue-router';
-
-const props = defineProps({
-  item: {
-    type: Object as PropType<RouteRecordRaw>,
-    required: true
-  },
-  isNest: {
-    type: Boolean,
-    default: false
-  },
-  basePath: {
-    type: String,
-    default: ''
-  }
-});
-
-const onlyOneChild = ref<any>({});
-
-const hasOneShowingChild = (parent: RouteRecordRaw, children?: RouteRecordRaw[]) => {
-  if (!children) {
-    children = [];
-  }
-  const showingChildren = children.filter((item) => {
-    if (item.hidden) {
-      return false;
-    }
-    onlyOneChild.value = item;
-    return true;
-  });
-
-  // When there is only one child router, the child router is displayed by default
-  if (showingChildren.length === 1) {
-    return true;
-  }
-
-  // Show parent if there are no child router to display
-  if (showingChildren.length === 0) {
-    onlyOneChild.value = { ...parent, path: '', noShowingChildren: true };
-    return true;
-  }
-
-  return false;
-};
-
-const resolvePath = (routePath: string, routeQuery?: string): any => {
-  if (isExternal(routePath)) {
-    return routePath;
-  }
-  if (isExternal(props.basePath as string)) {
-    return props.basePath;
-  }
-  if (routeQuery) {
-    const query = JSON.parse(routeQuery);
-    return { path: getNormalPath(props.basePath + '/' + routePath), query: query };
-  }
-  return getNormalPath(props.basePath + '/' + routePath);
-};
-
-const hasTitle = (title: string | undefined): string => {
-  if (!title || title.length <= 5) {
-    return '';
-  }
-  return title;
-};
-</script>

+ 0 - 56
src/layout/components/Sidebar/index.vue

@@ -1,56 +0,0 @@
-<template>
-  <div :class="{ 'has-logo': showLogo }" :style="{ backgroundColor: bgColor }">
-    <logo v-if="showLogo" :collapse="isCollapse" />
-    <el-scrollbar :class="sideTheme" wrap-class="scrollbar-wrapper">
-      <transition :enter-active-class="proxy?.animate.menuSearchAnimate.enter" mode="out-in">
-        <el-menu
-          :default-active="activeMenu"
-          :collapse="isCollapse"
-          :background-color="bgColor"
-          :text-color="textColor"
-          :unique-opened="true"
-          :active-text-color="theme"
-          :collapse-transition="false"
-          :popper-offset="12"
-          mode="vertical"
-        >
-          <sidebar-item v-for="(r, index) in sidebarRouters" :key="r.path + index" :item="r" :base-path="r.path" />
-        </el-menu>
-      </transition>
-    </el-scrollbar>
-  </div>
-</template>
-
-<script setup lang="ts">
-import Logo from './Logo.vue';
-import SidebarItem from './SidebarItem.vue';
-import variables from '@/assets/styles/variables.module.scss';
-import { useAppStore } from '@/store/modules/app';
-import { useSettingsStore } from '@/store/modules/settings';
-import { usePermissionStore } from '@/store/modules/permission';
-import { RouteRecordRaw } from 'vue-router';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const route = useRoute();
-const appStore = useAppStore();
-const settingsStore = useSettingsStore();
-const permissionStore = usePermissionStore();
-const sidebarRouters = computed<RouteRecordRaw[]>(() => permissionStore.getSidebarRoutes());
-const showLogo = computed(() => settingsStore.sidebarLogo);
-const sideTheme = computed(() => settingsStore.sideTheme);
-const theme = computed(() => settingsStore.theme);
-const isCollapse = computed(() => !appStore.sidebar.opened);
-
-const activeMenu = computed(() => {
-  const { meta, path } = route;
-  // if set path, the sidebar will highlight the path you set
-  if (meta.activeMenu) {
-    return meta.activeMenu;
-  }
-  return path;
-});
-
-const bgColor = computed(() => (sideTheme.value === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground));
-const textColor = computed(() => (sideTheme.value === 'theme-dark' ? variables.menuColor : variables.menuLightColor));
-</script>

+ 0 - 95
src/layout/components/SocialCallback/index.vue

@@ -1,95 +0,0 @@
-<template>
-  <div v-loading="loading" class="social-callback"></div>
-</template>
-
-<script setup lang="ts">
-import { login, callback } from '@/api/login';
-import { setToken, getToken } from '@/utils/auth';
-import { LoginData } from '@/api/types';
-
-const route = useRoute();
-const loading = ref(true);
-
-/**
- * 接收Route传递的参数
- * @param {Object} route.query.
- */
-const code = route.query.code as string;
-const state = route.query.state as string;
-const source = route.query.source as string;
-const stateJson = JSON.parse(atob(state));
-const tenantId = (stateJson.tenantId as string) ? (stateJson.tenantId as string) : '000000';
-const domain = stateJson.domain as string;
-
-const processResponse = async (res: any) => {
-  if (res.code !== 200) {
-    throw new Error(res.msg);
-  }
-  if (res.data !== null) {
-    setToken(res.data.access_token);
-  }
-  ElMessage.success(res.msg);
-  setTimeout(() => {
-    location.href = import.meta.env.VITE_APP_CONTEXT_PATH + 'index';
-  }, 2000);
-};
-
-const handleError = (error: any) => {
-  ElMessage.error(error.message);
-  setTimeout(() => {
-    location.href = import.meta.env.VITE_APP_CONTEXT_PATH + 'index';
-  }, 2000);
-};
-
-const callbackByCode = async (data: LoginData) => {
-  try {
-    const res = await callback(data);
-    await processResponse(res);
-    loading.value = false;
-  } catch (error) {
-    handleError(error);
-  }
-};
-
-const loginByCode = async (data: LoginData) => {
-  try {
-    const res = await login(data);
-    await processResponse(res);
-    loading.value = false;
-  } catch (error) {
-    handleError(error);
-  }
-};
-
-const init = async () => {
-  // 如果域名不相等 则重定向处理
-  const host = window.location.host;
-  if (domain !== host) {
-    const urlFull = new URL(window.location.href);
-    urlFull.host = domain;
-    window.location.href = urlFull.toString();
-    return;
-  }
-
-  const data: LoginData = {
-    socialCode: code,
-    socialState: state,
-    tenantId: tenantId,
-    source: source,
-    clientId: import.meta.env.VITE_APP_CLIENT_ID,
-    grantType: 'social'
-  };
-
-  if (!getToken()) {
-    await loginByCode(data);
-  } else {
-    await callbackByCode(data);
-  }
-};
-
-onMounted(() => {
-  nextTick(() => {
-    init();
-  });
-});
-</script>

+ 0 - 102
src/layout/components/TagsView/ScrollPane.vue

@@ -1,102 +0,0 @@
-<template>
-  <el-scrollbar ref="scrollContainerRef" :vertical="false" class="scroll-container" @wheel.prevent="handleScroll">
-    <slot />
-  </el-scrollbar>
-</template>
-
-<script setup lang="ts">
-import { RouteLocationNormalized } from 'vue-router';
-import { useTagsViewStore } from '@/store/modules/tagsView';
-
-const tagAndTagSpacing = ref(4);
-
-const scrollContainerRef = ref<ElScrollbarInstance>();
-const scrollWrapper = computed(() => scrollContainerRef.value?.$refs.wrapRef);
-
-onMounted(() => {
-  scrollWrapper.value?.addEventListener('scroll', emitScroll, true);
-});
-onBeforeUnmount(() => {
-  scrollWrapper.value?.removeEventListener('scroll', emitScroll);
-});
-
-const handleScroll = (e: WheelEvent) => {
-  const eventDelta = (e as any).wheelDelta || -e.deltaY * 40;
-  const $scrollWrapper = scrollWrapper.value;
-  $scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4;
-};
-const emits = defineEmits(['scroll']);
-const emitScroll = () => {
-  emits('scroll');
-};
-
-const tagsViewStore = useTagsViewStore();
-const visitedViews = computed(() => tagsViewStore.visitedViews);
-
-const moveToTarget = (currentTag: RouteLocationNormalized) => {
-  const $container = scrollContainerRef.value?.$el;
-  const $containerWidth = $container.offsetWidth;
-  const $scrollWrapper = scrollWrapper.value;
-
-  let firstTag = null;
-  let lastTag = null;
-
-  // find first tag and last tag
-  if (visitedViews.value.length > 0) {
-    firstTag = visitedViews.value[0];
-    lastTag = visitedViews.value[visitedViews.value.length - 1];
-  }
-
-  if (firstTag === currentTag) {
-    $scrollWrapper.scrollLeft = 0;
-  } else if (lastTag === currentTag) {
-    $scrollWrapper.scrollLeft = $scrollWrapper.scrollWidth - $containerWidth;
-  } else {
-    const tagListDom: any = document.getElementsByClassName('tags-view-item');
-    const currentIndex = visitedViews.value.findIndex((item) => item === currentTag);
-    let prevTag = null;
-    let nextTag = null;
-
-    for (const k in tagListDom) {
-      if (k !== 'length' && Object.hasOwnProperty.call(tagListDom, k)) {
-        if (tagListDom[k].dataset.path === visitedViews.value[currentIndex - 1].path) {
-          prevTag = tagListDom[k];
-        }
-        if (tagListDom[k].dataset.path === visitedViews.value[currentIndex + 1].path) {
-          nextTag = tagListDom[k];
-        }
-      }
-    }
-
-    // the tag's offsetLeft after of nextTag
-    const afterNextTagOffsetLeft = nextTag.offsetLeft + nextTag.offsetWidth + tagAndTagSpacing.value;
-
-    // the tag's offsetLeft before of prevTag
-    const beforePrevTagOffsetLeft = prevTag.offsetLeft - tagAndTagSpacing.value;
-    if (afterNextTagOffsetLeft > $scrollWrapper.scrollLeft + $containerWidth) {
-      $scrollWrapper.scrollLeft = afterNextTagOffsetLeft - $containerWidth;
-    } else if (beforePrevTagOffsetLeft < $scrollWrapper.scrollLeft) {
-      $scrollWrapper.scrollLeft = beforePrevTagOffsetLeft;
-    }
-  }
-};
-
-defineExpose({
-  moveToTarget
-});
-</script>
-
-<style lang="scss" scoped>
-.scroll-container {
-  white-space: nowrap;
-  position: relative;
-  overflow: hidden;
-  width: 100%;
-  :deep(.el-scrollbar__bar) {
-    bottom: 0px;
-  }
-  :deep(.el-scrollbar__wrap) {
-    height: 49px;
-  }
-}
-</style>

+ 0 - 347
src/layout/components/TagsView/index.vue

@@ -1,347 +0,0 @@
-<template>
-  <div id="tags-view-container" class="tags-view-container">
-    <scroll-pane ref="scrollPaneRef" class="tags-view-wrapper" @scroll="handleScroll">
-      <router-link
-        v-for="tag in visitedViews"
-        :key="tag.path"
-        :data-path="tag.path"
-        :class="{ 'active': isActive(tag), 'has-icon': tagsIcon }"
-        :to="{ path: tag.path ? tag.path : '', query: tag.query, fullPath: tag.fullPath ? tag.fullPath : '' }"
-        class="tags-view-item"
-        :style="activeStyle(tag)"
-        @click.middle="!isAffix(tag) ? closeSelectedTag(tag) : ''"
-        @contextmenu.prevent="openMenu(tag, $event)"
-      >
-        <svg-icon v-if="tagsIcon && tag.meta && tag.meta.icon && tag.meta.icon !== '#'" :icon-class="tag.meta.icon"/>
-        <span class="tags-view-item-title">{{ tag.title }}</span>
-        <span v-if="!isAffix(tag)" @click.prevent.stop="closeSelectedTag(tag)">
-          <close class="el-icon-close" style="width: 1em; height: 1em; vertical-align: middle" />
-        </span>
-      </router-link>
-    </scroll-pane>
-    <ul v-show="visible" :style="{ left: left + 'px', top: top + 'px' }" class="contextmenu">
-      <li @click="refreshSelectedTag(selectedTag)"><refresh-right style="width: 1em; height: 1em" /> 刷新页面</li>
-      <li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)"><close style="width: 1em; height: 1em" /> 关闭当前</li>
-      <li @click="closeOthersTags"><circle-close style="width: 1em; height: 1em" /> 关闭其他</li>
-      <li v-if="!isFirstView()" @click="closeLeftTags"><back style="width: 1em; height: 1em" /> 关闭左侧</li>
-      <li v-if="!isLastView()" @click="closeRightTags"><right style="width: 1em; height: 1em" /> 关闭右侧</li>
-      <li @click="closeAllTags(selectedTag)"><circle-close style="width: 1em; height: 1em" /> 全部关闭</li>
-    </ul>
-  </div>
-</template>
-
-<script setup lang="ts">
-import ScrollPane from './ScrollPane.vue';
-import { getNormalPath } from '@/utils/ruoyi';
-import { useSettingsStore } from '@/store/modules/settings';
-import { usePermissionStore } from '@/store/modules/permission';
-import { useTagsViewStore } from '@/store/modules/tagsView';
-import { RouteRecordRaw, RouteLocationNormalized } from 'vue-router';
-
-const visible = ref(false);
-const top = ref(0);
-const left = ref(0);
-const selectedTag = ref<RouteLocationNormalized>();
-const affixTags = ref<RouteLocationNormalized[]>([]);
-const scrollPaneRef = ref<InstanceType<typeof ScrollPane>>();
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const route = useRoute();
-const router = useRouter();
-
-const visitedViews = computed(() => useTagsViewStore().getVisitedViews());
-const routes = computed(() => usePermissionStore().getRoutes());
-const theme = computed(() => useSettingsStore().theme);
-const tagsIcon = computed(() => useSettingsStore().tagsIcon)
-
-watch(route, () => {
-  addTags();
-  moveToCurrentTag();
-});
-watch(visible, (value) => {
-  if (value) {
-    document.body.addEventListener('click', closeMenu);
-  } else {
-    document.body.removeEventListener('click', closeMenu);
-  }
-});
-
-const isActive = (r: RouteLocationNormalized): boolean => {
-  return r.path === route.path;
-};
-const activeStyle = (tag: RouteLocationNormalized) => {
-  if (!isActive(tag)) return {};
-  return {
-    'background-color': 'var(--tags-view-active-bg)',
-    'border-color': 'var(--tags-view-active-border-color)'
-  };
-};
-const isAffix = (tag: RouteLocationNormalized) => {
-  return tag?.meta && tag?.meta?.affix;
-};
-const isFirstView = () => {
-  try {
-    return selectedTag.value.fullPath === '/index' || selectedTag.value.fullPath === visitedViews.value[1].fullPath;
-  } catch (err) {
-    return false;
-  }
-};
-const isLastView = () => {
-  try {
-    return selectedTag.value.fullPath === visitedViews.value[visitedViews.value.length - 1].fullPath;
-  } catch (err) {
-    return false;
-  }
-};
-const filterAffixTags = (routes: RouteRecordRaw[], basePath = '') => {
-  let tags: RouteLocationNormalized[] = [];
-
-  routes.forEach((route) => {
-    if (route.meta && route.meta.affix) {
-      const tagPath = getNormalPath(basePath + '/' + route.path);
-      tags.push({
-        hash: '',
-        matched: [],
-        params: undefined,
-        query: undefined,
-        redirectedFrom: undefined,
-        fullPath: tagPath,
-        path: tagPath,
-        name: route.name as string,
-        meta: { ...route.meta }
-      });
-    }
-    if (route.children) {
-      const tempTags = filterAffixTags(route.children, route.path);
-      if (tempTags.length >= 1) {
-        tags = [...tags, ...tempTags];
-      }
-    }
-  });
-  return tags;
-};
-const initTags = () => {
-  const res = filterAffixTags(routes.value);
-  affixTags.value = res;
-  for (const tag of res) {
-    // Must have tag name
-    if (tag.name) {
-      useTagsViewStore().addVisitedView(tag);
-    }
-  }
-};
-const addTags = () => {
-  const { name } = route;
-  if (route.query.title) {
-    route.meta.title = route.query.title as string;
-  }
-  if (name) {
-    useTagsViewStore().addView(route as any);
-  }
-};
-const moveToCurrentTag = () => {
-  nextTick(() => {
-    for (const r of visitedViews.value) {
-      if (r.path === route.path) {
-        scrollPaneRef.value?.moveToTarget(r);
-        // when query is different then update
-        if (r.fullPath !== route.fullPath) {
-          useTagsViewStore().updateVisitedView(route);
-        }
-      }
-    }
-  });
-};
-const refreshSelectedTag = (view: RouteLocationNormalized) => {
-  proxy?.$tab.refreshPage(view);
-  if (route.meta.link) {
-    useTagsViewStore().delIframeView(route);
-  }
-};
-const closeSelectedTag = (view: RouteLocationNormalized) => {
-  proxy?.$tab.closePage(view).then(({ visitedViews }: any) => {
-    if (isActive(view)) {
-      toLastView(visitedViews, view);
-    }
-  });
-};
-const closeRightTags = () => {
-  proxy?.$tab.closeRightPage(selectedTag.value).then((visitedViews: RouteLocationNormalized[]) => {
-    if (!visitedViews.find((i: RouteLocationNormalized) => i.fullPath === route.fullPath)) {
-      toLastView(visitedViews);
-    }
-  });
-};
-const closeLeftTags = () => {
-  proxy?.$tab.closeLeftPage(selectedTag.value).then((visitedViews: RouteLocationNormalized[]) => {
-    if (!visitedViews.find((i: RouteLocationNormalized) => i.fullPath === route.fullPath)) {
-      toLastView(visitedViews);
-    }
-  });
-};
-const closeOthersTags = () => {
-  router.push(selectedTag.value).catch(() => {});
-  proxy?.$tab.closeOtherPage(selectedTag.value).then(() => {
-    moveToCurrentTag();
-  });
-};
-const closeAllTags = (view: RouteLocationNormalized) => {
-  proxy?.$tab.closeAllPage().then(({ visitedViews }) => {
-    if (affixTags.value.some((tag) => tag.path === route.path)) {
-      return;
-    }
-    toLastView(visitedViews, view);
-  });
-};
-const toLastView = (visitedViews: RouteLocationNormalized[], view?: RouteLocationNormalized) => {
-  const latestView = visitedViews.slice(-1)[0];
-  if (latestView) {
-    router.push(latestView.fullPath as string);
-  } else {
-    // now the default is to redirect to the home page if there is no tags-view,
-    // you can adjust it according to your needs.
-    if (view?.name === 'Dashboard') {
-      // to reload home page
-      router.replace({ path: '/redirect' + view?.fullPath });
-    } else {
-      router.push('/');
-    }
-  }
-};
-const openMenu = (tag: RouteLocationNormalized, e: MouseEvent) => {
-  const menuMinWidth = 105;
-  const offsetLeft = proxy?.$el.getBoundingClientRect().left; // container margin left
-  const offsetWidth = proxy?.$el.offsetWidth; // container width
-  const maxLeft = offsetWidth - menuMinWidth; // left boundary
-  const l = e.clientX - offsetLeft + 15; // 15: margin right
-
-  if (l > maxLeft) {
-    left.value = maxLeft;
-  } else {
-    left.value = l;
-  }
-
-  top.value = e.clientY;
-  visible.value = true;
-  selectedTag.value = tag;
-};
-const closeMenu = () => {
-  visible.value = false;
-};
-const handleScroll = () => {
-  closeMenu();
-};
-
-onMounted(() => {
-  initTags();
-  addTags();
-});
-</script>
-
-<style lang="scss" scoped>
-.tags-view-container {
-  height: 34px;
-  width: 100%;
-  background-color: var(--el-bg-color);
-  border: 1px solid var(--el-border-color-light);
-  box-shadow:
-    0 1px 3px 0 rgba(0, 0, 0, 0.12),
-    0 0 3px 0 rgba(0, 0, 0, 0.04);
-  .tags-view-wrapper {
-    .tags-view-item {
-      display: inline-block;
-      position: relative;
-      cursor: pointer;
-      height: 26px;
-      line-height: 25px;
-      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;
-      margin-top: 4px;
-      border-radius: 4px;
-      &:hover {
-        color: var(--el-color-primary);
-      }
-      &:first-of-type {
-        margin-left: 15px;
-      }
-      &:last-of-type {
-        margin-right: 15px;
-      }
-      &.active {
-        background-color: #42b983;
-        color: #fff;
-        border-color: #42b983;
-        &::before {
-          content: '';
-          background: #fff;
-          display: inline-block;
-          width: 8px;
-          height: 8px;
-          border-radius: 50%;
-          position: relative;
-          margin-right: 5px;
-        }
-      }
-    }
-  }
-  .tags-view-item.active.has-icon::before {
-    content: none !important;
-  }
-  .tags-view-item-title {
-    margin-left: 4px;
-    margin-right: 3px;
-  }
-  .contextmenu {
-    margin: 0;
-    background: var(--el-bg-color);
-    z-index: 3000;
-    position: absolute;
-    list-style-type: none;
-    padding: 5px 0;
-    border-radius: 4px;
-    font-size: 12px;
-    font-weight: 400;
-    box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.3);
-    li {
-      margin: 0;
-      padding: 7px 16px;
-      cursor: pointer;
-      &:hover {
-        background: #eee;
-      }
-    }
-  }
-}
-</style>
-
-<style lang="scss">
-//reset element css of el-icon-close
-.tags-view-wrapper {
-  .tags-view-item {
-    .el-icon-close {
-      width: 16px;
-      height: 16px;
-      vertical-align: 2px;
-      border-radius: 50%;
-      text-align: center;
-      transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
-      transform-origin: 100% 50%;
-      &:before {
-        transform: scale(0.6);
-        display: inline-block;
-        vertical-align: -3px;
-      }
-      &:hover {
-        background-color: #b4bccc;
-        color: #fff;
-        width: 12px !important;
-        height: 12px !important;
-      }
-    }
-  }
-}
-</style>

+ 0 - 158
src/layout/components/TopBar/search.vue

@@ -1,158 +0,0 @@
-<template>
-  <div class="layout-search-dialog">
-    <el-dialog v-model="state.isShowSearch" destroy-on-close :show-close="false">
-      <template #footer>
-        <el-autocomplete
-          ref="layoutMenuAutocompleteRef"
-          v-model="state.menuQuery"
-          :fetch-suggestions="menuSearch"
-          placeholder="搜索"
-          :fit-input-width="true"
-          @select="onHandleSelect"
-        >
-          <template #prefix>
-            <svg-icon class-name="search-icon" icon-class="search" />
-          </template>
-          <template #default="{ item }">
-            <div>
-              <svg-icon :icon-class="item.icon" class="mr5" />
-              {{ item.title }}
-            </div>
-          </template>
-        </el-autocomplete>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup lang="ts" name="layoutBreadcrumbSearch">
-import { getNormalPath } from '@/utils/ruoyi';
-import { isHttp } from '@/utils/validate';
-import { usePermissionStore } from '@/store/modules/permission';
-import { RouteRecordRaw } from 'vue-router';
-type Router = Array<{
-  path: string;
-  icon: string;
-  title: string[];
-}>;
-type SearchState<T = any> = {
-  isShowSearch: boolean;
-  menuQuery: string;
-  menuList: T[];
-};
-// 定义变量内容
-const layoutMenuAutocompleteRef = ref();
-const router = useRouter();
-const routes = computed(() => usePermissionStore().routes);
-const state = reactive<SearchState>({
-  isShowSearch: false,
-  menuQuery: '',
-  menuList: []
-});
-
-// 搜索弹窗打开
-const openSearch = () => {
-  state.menuQuery = '';
-  state.isShowSearch = true;
-  state.menuList = generateRoutes(routes.value as any);
-  nextTick(() => {
-    setTimeout(() => {
-      layoutMenuAutocompleteRef.value.focus();
-    });
-  });
-};
-// 搜索弹窗关闭
-const closeSearch = () => {
-  state.isShowSearch = false;
-};
-// 菜单搜索数据过滤
-const menuSearch = (queryString: string, cb: (options: any[]) => void) => {
-  const options = state.menuList.filter((item) => {
-    return item.title.indexOf(queryString) > -1;
-  });
-  cb(options);
-};
-
-// Filter out the routes that can be displayed in the sidebar
-// And generate the internationalized title
-const generateRoutes = (routes: RouteRecordRaw[], basePath = '', prefixTitle: string[] = []) => {
-  let res: Router = [];
-  routes.forEach((r) => {
-    // skip hidden router
-    if (!r.hidden) {
-      const p = r.path.length > 0 && r.path[0] === '/' ? r.path : '/' + r.path;
-      const data: any = {
-        path: !isHttp(r.path) ? getNormalPath(basePath + p) : r.path,
-        icon: r.meta?.icon,
-        title: [...prefixTitle]
-      };
-      if (r.meta && r.meta.title) {
-        data.title = [...data.title, r.meta.title];
-        if (r.redirect !== 'noRedirect') {
-          // only push the routes with title
-          // special case: need to exclude parent router without redirect
-          res.push(data);
-        }
-      }
-      // recursive child routes
-      if (r.children) {
-        const tempRoutes = generateRoutes(r.children, data.path, data.title);
-        if (tempRoutes.length >= 1) {
-          res = [...res, ...tempRoutes];
-        }
-      }
-    }
-  });
-  res.forEach((item: any) => {
-    if (item.title instanceof Array) {
-      item.title = item.title.join('/');
-    }
-  });
-  return res;
-};
-// 当前菜单选中时
-const onHandleSelect = (val: any) => {
-  const paths = val.path;
-  if (isHttp(paths)) {
-    // http(s):// 路径新窗口打开
-    const pindex = paths.indexOf('http');
-    window.open(paths.substring(pindex, paths.length), '_blank');
-  } else {
-    router.push(paths);
-  }
-  state.menuQuery = '';
-  closeSearch();
-};
-
-// 暴露变量
-defineExpose({
-  openSearch
-});
-</script>
-
-<style lang="scss" scoped>
-.layout-search-dialog {
-  position: relative;
-  :deep(.el-dialog) {
-    padding: 0;
-    .el-dialog__header,
-    .el-dialog__body {
-      display: none;
-    }
-    .el-dialog__footer {
-      width: 100%;
-      position: absolute;
-      left: 50%;
-      transform: translateX(-50%);
-      top: -53vh;
-    }
-  }
-  :deep(.el-autocomplete) {
-    width: 560px;
-    position: absolute;
-    top: 150px;
-    left: 50%;
-    transform: translateX(-50%);
-  }
-}
-</style>

+ 0 - 5
src/layout/components/index.ts

@@ -1,8 +1,3 @@
-export { default as AppMain } from './AppMain.vue';
-export { default as Navbar } from './Navbar.vue';
-export { default as Settings } from './Settings/index.vue';
-export { default as TagsView } from './TagsView/index.vue';
-
 export { default as Header } from './header.vue';
 export { default as Search } from './search.vue';
 export { default as Nav } from './nav.vue';

+ 0 - 130
src/layout/components/notice/index.vue

@@ -1,130 +0,0 @@
-<template>
-  <div v-loading="state.loading" class="layout-navbars-breadcrumb-user-news">
-    <div class="head-box">
-      <div class="head-box-title">通知公告</div>
-      <div class="head-box-btn" @click="readAll">全部已读</div>
-    </div>
-    <div v-loading="state.loading" class="content-box">
-      <template v-if="newsList.length > 0">
-        <div v-for="(v, k) in newsList" :key="k" class="content-box-item" @click="onNewsClick(k)">
-          <div class="item-conten">
-            <div>{{ v.message }}</div>
-            <div class="content-box-msg"></div>
-            <div class="content-box-time">{{ v.time }}</div>
-          </div>
-          <!-- 已读/未读 -->
-          <span v-if="v.read" class="el-tag el-tag--success el-tag--mini read">已读</span>
-          <span v-else class="el-tag el-tag--danger el-tag--mini read">未读</span>
-        </div>
-      </template>
-      <el-empty v-else :description="'消息为空'"></el-empty>
-    </div>
-    <div v-if="newsList.length > 0" class="foot-box" @click="onGoToGiteeClick">前往gitee</div>
-  </div>
-</template>
-
-<script setup lang="ts" name="layoutBreadcrumbUserNews">
-import { useNoticeStore } from '@/store/modules/notice';
-
-const noticeStore = useNoticeStore();
-const { readAll } = useNoticeStore();
-
-// 定义变量内容
-const state = reactive({
-  loading: false
-});
-const newsList = ref([]) as any;
-
-/**
- * 初始化数据
- * @returns
- */
-const getTableData = async () => {
-  state.loading = true;
-  newsList.value = noticeStore.state.notices;
-  state.loading = false;
-};
-
-//点击消息,写入已读
-const onNewsClick = (item: any) => {
-  newsList.value[item].read = true;
-  //并且写入pinia
-  noticeStore.state.notices = newsList.value;
-};
-
-// 前往通知中心点击
-const onGoToGiteeClick = () => {
-  window.open('https://gitee.com/dromara/RuoYi-Vue-Plus/tree/5.X/');
-};
-
-onMounted(() => {
-  nextTick(() => {
-    getTableData();
-  });
-});
-</script>
-
-<style lang="scss" scoped>
-.layout-navbars-breadcrumb-user-news {
-  .head-box {
-    display: flex;
-    border-bottom: 1px solid var(--el-border-color-lighter);
-    box-sizing: border-box;
-    color: var(--el-text-color-primary);
-    justify-content: space-between;
-    height: 35px;
-    align-items: center;
-    .head-box-btn {
-      color: var(--el-color-primary);
-      font-size: 13px;
-      cursor: pointer;
-      opacity: 0.8;
-      &:hover {
-        opacity: 1;
-      }
-    }
-  }
-  .content-box {
-    height: 300px;
-    overflow: auto;
-    font-size: 13px;
-    .content-box-item {
-      padding-top: 12px;
-      display: flex;
-      &:last-of-type {
-        padding-bottom: 12px;
-      }
-      .content-box-msg {
-        color: var(--el-text-color-secondary);
-        margin-top: 5px;
-        margin-bottom: 5px;
-      }
-      .content-box-time {
-        color: var(--el-text-color-secondary);
-      }
-      .item-conten {
-        width: 100%;
-        display: flex;
-        flex-direction: column;
-      }
-    }
-  }
-  .foot-box {
-    height: 35px;
-    color: var(--el-color-primary);
-    font-size: 13px;
-    cursor: pointer;
-    opacity: 0.8;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    border-top: 1px solid var(--el-border-color-lighter);
-    &:hover {
-      opacity: 1;
-    }
-  }
-  :deep(.el-empty__description p) {
-    font-size: 13px;
-  }
-}
-</style>

+ 0 - 19
src/router/index.ts

@@ -37,11 +37,6 @@ export const constantRoutes: RouteRecordRaw[] = [
       }
     ]
   },
-  {
-    path: '/social-callback',
-    hidden: true,
-    component: () => import('@/layout/components/SocialCallback/index.vue')
-  },
   {
     path: '/login',
     component: () => import('@/views/login.vue'),
@@ -122,20 +117,6 @@ export const constantRoutes: RouteRecordRaw[] = [
         meta: { title: '企业注册' }
       }
     ]
-  },
-  {
-    path: '/user',
-    component: Layout,
-    hidden: true,
-    redirect: 'noredirect',
-    children: [
-      {
-        path: 'profile',
-        component: () => import('@/views/system/user/profile/index.vue'),
-        name: 'Profile',
-        meta: { title: '个人中心', icon: 'user' }
-      }
-    ]
   }
 ];
 

+ 0 - 245
src/views/demo/demo/index.vue

@@ -1,245 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
-        <el-card shadow="hover">
-          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="key键" prop="testKey">
-              <el-input v-model="queryParams.testKey" placeholder="请输入key键" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="值" prop="value">
-              <el-input v-model="queryParams.value" placeholder="请输入值" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
-      </div>
-    </transition>
-
-    <el-card shadow="hover">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['demo:demo:add']" type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['demo:demo:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()">修改</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['demo:demo:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()"
-              >删除</el-button
-            >
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['demo:demo:export']" type="warning" plain icon="Download" @click="handleExport">导出</el-button>
-          </el-col>
-          <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
-        </el-row>
-      </template>
-
-      <el-table v-loading="loading" border :data="demoList" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column v-if="true" label="主键" align="center" prop="id" />
-        <el-table-column label="部门id" align="center" prop="deptId" />
-        <el-table-column label="用户id" align="center" prop="userId" />
-        <el-table-column label="排序号" align="center" prop="orderNum" />
-        <el-table-column label="key键" align="center" prop="testKey" />
-        <el-table-column label="值" align="center" prop="value" />
-        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
-          <template #default="scope">
-            <el-tooltip content="修改" placement="top">
-              <el-button v-hasPermi="['demo:demo:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>
-            </el-tooltip>
-            <el-tooltip content="删除" placement="top">
-              <el-button v-hasPermi="['demo:demo:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
-            </el-tooltip>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
-    </el-card>
-    <!-- 添加或修改测试单对话框 -->
-    <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body>
-      <el-form ref="demoFormRef" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="部门id" prop="deptId">
-          <el-input v-model="form.deptId" placeholder="请输入部门id" />
-        </el-form-item>
-        <el-form-item label="用户id" prop="userId">
-          <el-input v-model="form.userId" placeholder="请输入用户id" />
-        </el-form-item>
-        <el-form-item label="排序号" prop="orderNum">
-          <el-input v-model="form.orderNum" placeholder="请输入排序号" />
-        </el-form-item>
-        <el-form-item label="key键" prop="testKey">
-          <el-input v-model="form.testKey" placeholder="请输入key键" />
-        </el-form-item>
-        <el-form-item label="值" prop="value">
-          <el-input v-model="form.value" placeholder="请输入值" />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
-          <el-button @click="cancel">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup name="Demo" lang="ts">
-import { listDemo, getDemo, delDemo, addDemo, updateDemo } from '@/api/demo/demo';
-import { DemoVO, DemoQuery, DemoForm } from '@/api/demo/demo/types';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const demoList = ref<DemoVO[]>([]);
-const buttonLoading = ref(false);
-const loading = ref(true);
-const showSearch = ref(true);
-const ids = ref<Array<string | number>>([]);
-const single = ref(true);
-const multiple = ref(true);
-const total = ref(0);
-
-const queryFormRef = ref<ElFormInstance>();
-const demoFormRef = ref<ElFormInstance>();
-
-const dialog = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-const initFormData: DemoForm = {
-  id: undefined,
-  deptId: undefined,
-  userId: undefined,
-  orderNum: undefined,
-  testKey: undefined,
-  value: undefined
-};
-const data = reactive<PageData<DemoForm, DemoQuery>>({
-  form: { ...initFormData },
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    deptId: undefined,
-    userId: undefined,
-    orderNum: undefined,
-    testKey: undefined,
-    value: undefined
-  },
-  rules: {
-    id: [{ required: true, message: '主键不能为空', trigger: 'blur' }],
-    deptId: [{ required: true, message: '部门id不能为空', trigger: 'blur' }],
-    userId: [{ required: true, message: '用户id不能为空', trigger: 'blur' }],
-    orderNum: [{ required: true, message: '排序号不能为空', trigger: 'blur' }],
-    testKey: [{ required: true, message: 'key键不能为空', trigger: 'blur' }],
-    value: [{ required: true, message: '值不能为空', trigger: 'blur' }]
-  }
-});
-
-const { queryParams, form, rules } = toRefs(data);
-
-/** 查询测试单列表 */
-const getList = async () => {
-  loading.value = true;
-  const res = await listDemo(queryParams.value);
-  demoList.value = res.rows;
-  total.value = res.total;
-  loading.value = false;
-};
-
-/** 取消按钮 */
-const cancel = () => {
-  reset();
-  dialog.visible = false;
-};
-
-/** 表单重置 */
-const reset = () => {
-  form.value = { ...initFormData };
-  demoFormRef.value?.resetFields();
-};
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.value.pageNum = 1;
-  getList();
-};
-
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  handleQuery();
-};
-
-/** 多选框选中数据 */
-const handleSelectionChange = (selection: DemoVO[]) => {
-  ids.value = selection.map((item) => item.id);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
-};
-
-/** 新增按钮操作 */
-const handleAdd = () => {
-  reset();
-  dialog.visible = true;
-  dialog.title = '添加测试单';
-};
-
-/** 修改按钮操作 */
-const handleUpdate = async (row?: DemoVO) => {
-  reset();
-  const _id = row?.id || ids.value[0];
-  const res = await getDemo(_id);
-  Object.assign(form.value, res.data);
-  dialog.visible = true;
-  dialog.title = '修改测试单';
-};
-
-/** 提交按钮 */
-const submitForm = () => {
-  demoFormRef.value?.validate(async (valid: boolean) => {
-    if (valid) {
-      buttonLoading.value = true;
-      if (form.value.id) {
-        await updateDemo(form.value).finally(() => (buttonLoading.value = false));
-      } else {
-        await addDemo(form.value).finally(() => (buttonLoading.value = false));
-      }
-      proxy?.$modal.msgSuccess('修改成功');
-      dialog.visible = false;
-      await getList();
-    }
-  });
-};
-
-/** 删除按钮操作 */
-const handleDelete = async (row?: DemoVO) => {
-  const _ids = row?.id || ids.value;
-  await proxy?.$modal.confirm('是否确认删除测试单编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
-  await delDemo(_ids);
-  proxy?.$modal.msgSuccess('删除成功');
-  await getList();
-};
-
-/** 导出按钮操作 */
-const handleExport = () => {
-  proxy?.download(
-    'demo/demo/export',
-    {
-      ...queryParams.value
-    },
-    `demo_${new Date().getTime()}.xlsx`
-  );
-};
-
-onMounted(() => {
-  getList();
-});
-</script>

+ 0 - 259
src/views/demo/tree/index.vue

@@ -1,259 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
-        <el-card shadow="hover">
-          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="树节点名" prop="treeName">
-              <el-input v-model="queryParams.treeName" placeholder="请输入树节点名" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
-      </div>
-    </transition>
-
-    <el-card shadow="hover">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['demo:tree:add']" type="primary" plain icon="Plus" @click="handleAdd()">新增</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="info" plain icon="Sort" @click="handleToggleExpandAll">展开/折叠</el-button>
-          </el-col>
-          <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
-        </el-row>
-      </template>
-      <el-table
-        ref="treeTableRef"
-        v-loading="loading"
-        :data="treeList"
-        row-key="id"
-        border
-        :default-expand-all="isExpandAll"
-        :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
-      >
-        <el-table-column label="父id" align="center" prop="parentId" />
-        <el-table-column label="部门id" align="center" prop="deptId" />
-        <el-table-column label="用户id" align="center" prop="userId" />
-        <el-table-column label="树节点名" align="center" prop="treeName" />
-        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
-          <template #default="scope">
-            <el-tooltip content="修改" placement="top">
-              <el-button v-hasPermi="['demo:tree:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)" />
-            </el-tooltip>
-            <el-tooltip content="新增" placement="top">
-              <el-button v-hasPermi="['demo:tree:add']" link type="primary" icon="Plus" @click="handleAdd(scope.row)" />
-            </el-tooltip>
-            <el-tooltip content="删除" placement="top">
-              <el-button v-hasPermi="['demo:tree:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)" />
-            </el-tooltip>
-          </template>
-        </el-table-column>
-      </el-table>
-    </el-card>
-    <!-- 添加或修改测试树对话框 -->
-    <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body>
-      <el-form ref="treeFormRef" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="父id" prop="parentId">
-          <el-tree-select
-            v-model="form.parentId"
-            :data="treeOptions"
-            :props="{ value: 'id', label: 'treeName', children: 'children' } as any"
-            value-key="id"
-            placeholder="请选择父id"
-            check-strictly
-          />
-        </el-form-item>
-        <el-form-item label="部门id" prop="deptId">
-          <el-input v-model="form.deptId" placeholder="请输入部门id" />
-        </el-form-item>
-        <el-form-item label="用户id" prop="userId">
-          <el-input v-model="form.userId" placeholder="请输入用户id" />
-        </el-form-item>
-        <el-form-item label="值" prop="treeName">
-          <el-input v-model="form.treeName" placeholder="请输入值" />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
-          <el-button @click="cancel">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup name="Tree" lang="ts">
-import { listTree, getTree, delTree, addTree, updateTree } from '@/api/demo/tree';
-import { TreeVO, TreeQuery, TreeForm } from '@/api/demo/tree/types';
-
-type TreeOption = {
-  id: number;
-  treeName: string;
-  children?: TreeOption[];
-};
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const treeList = ref<TreeVO[]>([]);
-const treeOptions = ref<TreeOption[]>([]);
-const buttonLoading = ref(false);
-const showSearch = ref(true);
-const isExpandAll = ref(true);
-const loading = ref(false);
-
-const queryFormRef = ref<ElFormInstance>();
-const treeFormRef = ref<ElFormInstance>();
-const treeTableRef = ref<ElTableInstance>();
-
-const dialog = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-const initFormData: TreeForm = {
-  id: undefined,
-  parentId: undefined,
-  deptId: undefined,
-  userId: undefined,
-  treeName: undefined
-};
-
-const data = reactive<PageData<TreeForm, TreeQuery>>({
-  form: { ...initFormData },
-  queryParams: {
-    parentId: undefined,
-    deptId: undefined,
-    userId: undefined,
-    treeName: undefined
-  },
-  rules: {
-    id: [{ required: true, message: '主键不能为空', trigger: 'blur' }],
-    parentId: [{ required: true, message: '父id不能为空', trigger: 'blur' }],
-    deptId: [{ required: true, message: '部门id不能为空', trigger: 'blur' }],
-    userId: [{ required: true, message: '用户id不能为空', trigger: 'blur' }],
-    treeName: [{ required: true, message: '值不能为空', trigger: 'blur' }]
-  }
-});
-
-const { queryParams, form, rules } = toRefs(data);
-
-/** 查询测试树列表 */
-const getList = async () => {
-  loading.value = true;
-  const res = await listTree(queryParams.value);
-  const data = proxy?.handleTree<TreeVO>(res.data, 'id', 'parentId');
-  if (data) {
-    treeList.value = data;
-    loading.value = false;
-  }
-};
-
-/** 查询测试树下拉树结构 */
-const getTreeselect = async () => {
-  const res = await listTree();
-  treeOptions.value = [];
-  const data: TreeOption = { id: 0, treeName: '顶级节点', children: [] };
-  data.children = proxy?.handleTree<TreeOption>(res.data, 'id', 'parentId');
-  treeOptions.value.push(data);
-};
-
-// 取消按钮
-const cancel = () => {
-  reset();
-  dialog.visible = false;
-};
-
-// 表单重置
-const reset = () => {
-  form.value = { ...initFormData };
-  treeFormRef.value?.resetFields();
-};
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  getList();
-};
-
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  handleQuery();
-};
-
-/** 新增按钮操作 */
-const handleAdd = (row?: TreeVO) => {
-  reset();
-  getTreeselect();
-  if (row && row.id) {
-    form.value.parentId = row.id;
-  } else {
-    form.value.parentId = 0;
-  }
-  dialog.visible = true;
-  dialog.title = '添加测试树';
-};
-
-/** 展开/折叠操作 */
-const handleToggleExpandAll = () => {
-  isExpandAll.value = !isExpandAll.value;
-  toggleExpandAll(treeList.value, isExpandAll.value);
-};
-
-/** 展开/折叠操作 */
-const toggleExpandAll = (data: TreeVO[], status: boolean) => {
-  data.forEach((item) => {
-    treeTableRef.value?.toggleRowExpansion(item, status);
-    if (item.children && item.children.length > 0) toggleExpandAll(item.children, status);
-  });
-};
-
-/** 修改按钮操作 */
-const handleUpdate = async (row: TreeVO) => {
-  reset();
-  await getTreeselect();
-  if (row) {
-    form.value.parentId = row.id;
-  }
-  const res = await getTree(row.id);
-  Object.assign(form.value, res.data);
-  dialog.visible = true;
-  dialog.title = '修改测试树';
-};
-
-/** 提交按钮 */
-const submitForm = () => {
-  treeFormRef.value?.validate(async (valid: boolean) => {
-    if (valid) {
-      buttonLoading.value = true;
-      if (form.value.id) {
-        await updateTree(form.value).finally(() => (buttonLoading.value = false));
-      } else {
-        await addTree(form.value).finally(() => (buttonLoading.value = false));
-      }
-      proxy?.$modal.msgSuccess('操作成功');
-      dialog.visible = false;
-      await getList();
-    }
-  });
-};
-
-/** 删除按钮操作 */
-const handleDelete = async (row: TreeVO) => {
-  await proxy?.$modal.confirm('是否确认删除测试树编号为"' + row.id + '"的数据项?');
-  loading.value = true;
-  await delTree(row.id).finally(() => (loading.value = false));
-  await getList();
-  proxy?.$modal.msgSuccess('删除成功');
-};
-
-onMounted(() => {
-  getList();
-});
-</script>

+ 0 - 314
src/views/login copy.vue

@@ -1,314 +0,0 @@
-<template>
-  <div class="login">
-    <el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form">
-      <div class="title-box">
-        <h3 class="title">{{ title }}</h3>
-        <lang-select />
-      </div>
-      <el-form-item v-if="tenantEnabled" prop="tenantId">
-        <el-select v-model="loginForm.tenantId" filterable :placeholder="proxy.$t('login.selectPlaceholder')" style="width: 100%">
-          <el-option v-for="item in tenantList" :key="item.tenantId" :label="item.companyName" :value="item.tenantId"></el-option>
-          <template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template>
-        </el-select>
-      </el-form-item>
-      <el-form-item prop="username">
-        <el-input v-model="loginForm.username" type="text" size="large" auto-complete="off" :placeholder="proxy.$t('login.username')">
-          <template #prefix><svg-icon icon-class="user" class="el-input__icon input-icon" /></template>
-        </el-input>
-      </el-form-item>
-      <el-form-item prop="password">
-        <el-input
-          v-model="loginForm.password"
-          type="password"
-          size="large"
-          auto-complete="off"
-          :placeholder="proxy.$t('login.password')"
-          @keyup.enter="handleLogin"
-        >
-          <template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template>
-        </el-input>
-      </el-form-item>
-      <el-form-item v-if="captchaEnabled" prop="code">
-        <el-input
-          v-model="loginForm.code"
-          size="large"
-          auto-complete="off"
-          :placeholder="proxy.$t('login.code')"
-          style="width: 63%"
-          @keyup.enter="handleLogin"
-        >
-          <template #prefix><svg-icon icon-class="validCode" class="el-input__icon input-icon" /></template>
-        </el-input>
-        <div class="login-code">
-          <img :src="codeUrl" class="login-code-img" @click="getCode" />
-        </div>
-      </el-form-item>
-      <el-checkbox v-model="loginForm.rememberMe" style="margin: 0 0 25px 0">{{ proxy.$t('login.rememberPassword') }}</el-checkbox>
-      <el-form-item style="float: right">
-        <el-button circle :title="proxy.$t('login.social.wechat')" @click="doSocialLogin('wechat')">
-          <svg-icon icon-class="wechat" />
-        </el-button>
-        <el-button circle :title="proxy.$t('login.social.maxkey')" @click="doSocialLogin('maxkey')">
-          <svg-icon icon-class="maxkey" />
-        </el-button>
-        <el-button circle :title="proxy.$t('login.social.topiam')" @click="doSocialLogin('topiam')">
-          <svg-icon icon-class="topiam" />
-        </el-button>
-        <el-button circle :title="proxy.$t('login.social.gitee')" @click="doSocialLogin('gitee')">
-          <svg-icon icon-class="gitee" />
-        </el-button>
-        <el-button circle :title="proxy.$t('login.social.github')" @click="doSocialLogin('github')">
-          <svg-icon icon-class="github" />
-        </el-button>
-      </el-form-item>
-      <el-form-item style="width: 100%">
-        <el-button :loading="loading" size="large" type="primary" style="width: 100%" @click.prevent="handleLogin">
-          <span v-if="!loading">{{ proxy.$t('login.login') }}</span>
-          <span v-else>{{ proxy.$t('login.logging') }}</span>
-        </el-button>
-        <div v-if="register" style="float: right">
-          <router-link class="link-type" :to="'/register'">{{ proxy.$t('login.switchRegisterPage') }}</router-link>
-        </div>
-      </el-form-item>
-    </el-form>
-    <!--  底部  -->
-    <div class="el-login-footer">
-      <span>Copyright © 2018-2026 疯狂的狮子Li All Rights Reserved.</span>
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-import { getCodeImg, getTenantList } from '@/api/login';
-import { authRouterUrl } from '@/api/system/social/auth';
-import { useUserStore } from '@/store/modules/user';
-import { LoginData, TenantVO } from '@/api/types';
-import { to } from 'await-to-js';
-import { HttpStatus } from '@/enums/RespEnum';
-import { useI18n } from 'vue-i18n';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const title = import.meta.env.VITE_APP_TITLE;
-const userStore = useUserStore();
-const router = useRouter();
-const { t } = useI18n();
-
-const loginForm = ref<LoginData>({
-  tenantId: '000000',
-  username: 'admin',
-  password: 'admin123',
-  rememberMe: false,
-  code: '',
-  uuid: ''
-} as LoginData);
-
-const loginRules: ElFormRules = {
-  tenantId: [{ required: true, trigger: 'blur', message: t('login.rule.tenantId.required') }],
-  username: [{ required: true, trigger: 'blur', message: t('login.rule.username.required') }],
-  password: [{ required: true, trigger: 'blur', message: t('login.rule.password.required') }],
-  code: [{ required: true, trigger: 'change', message: t('login.rule.code.required') }]
-};
-
-const codeUrl = ref('');
-const loading = ref(false);
-// 验证码开关
-const captchaEnabled = ref(true);
-// 租户开关
-const tenantEnabled = ref(true);
-
-// 注册开关
-const register = ref(false);
-const redirect = ref('/');
-const loginRef = ref<ElFormInstance>();
-// 租户列表
-const tenantList = ref<TenantVO[]>([]);
-
-watch(
-  () => router.currentRoute.value,
-  (newRoute: any) => {
-    redirect.value = newRoute.query && newRoute.query.redirect && decodeURIComponent(newRoute.query.redirect);
-  },
-  { immediate: true }
-);
-
-const handleLogin = () => {
-  loginRef.value?.validate(async (valid: boolean, fields: any) => {
-    if (valid) {
-      loading.value = true;
-      // 勾选了需要记住密码设置在 localStorage 中设置记住用户名和密码
-      if (loginForm.value.rememberMe) {
-        localStorage.setItem('tenantId', String(loginForm.value.tenantId));
-        localStorage.setItem('username', String(loginForm.value.username));
-        localStorage.setItem('password', String(loginForm.value.password));
-        localStorage.setItem('rememberMe', String(loginForm.value.rememberMe));
-      } else {
-        // 否则移除
-        localStorage.removeItem('tenantId');
-        localStorage.removeItem('username');
-        localStorage.removeItem('password');
-        localStorage.removeItem('rememberMe');
-      }
-      // 调用action的登录方法
-      const [err] = await to(userStore.login(loginForm.value));
-      if (!err) {
-        const redirectUrl = redirect.value || '/';
-        await router.push(redirectUrl);
-        loading.value = false;
-      } else {
-        loading.value = false;
-        // 重新获取验证码
-        if (captchaEnabled.value) {
-          await getCode();
-        }
-      }
-    } else {
-      console.log('error submit!', fields);
-    }
-  });
-};
-
-/**
- * 获取验证码
- */
-const getCode = async () => {
-  const res = await getCodeImg();
-  const { data } = res;
-  captchaEnabled.value = data.captchaEnabled === undefined ? true : data.captchaEnabled;
-  if (captchaEnabled.value) {
-    // 刷新验证码时清空输入框
-    loginForm.value.code = '';
-    codeUrl.value = 'data:image/gif;base64,' + data.img;
-    loginForm.value.uuid = data.uuid;
-  }
-};
-
-const getLoginData = () => {
-  const tenantId = localStorage.getItem('tenantId');
-  const username = localStorage.getItem('username');
-  const password = localStorage.getItem('password');
-  const rememberMe = localStorage.getItem('rememberMe');
-  loginForm.value = {
-    tenantId: tenantId === null ? String(loginForm.value.tenantId) : tenantId,
-    username: username === null ? String(loginForm.value.username) : username,
-    password: password === null ? String(loginForm.value.password) : String(password),
-    rememberMe: rememberMe === null ? false : Boolean(rememberMe)
-  } as LoginData;
-};
-
-/**
- * 获取租户列表
- */
-const initTenantList = async () => {
-  const { data } = await getTenantList(false);
-  tenantEnabled.value = data.tenantEnabled === undefined ? true : data.tenantEnabled;
-  if (tenantEnabled.value) {
-    tenantList.value = data.voList;
-    if (tenantList.value != null && tenantList.value.length !== 0) {
-      loginForm.value.tenantId = tenantList.value[0].tenantId;
-    }
-  }
-};
-
-/**
- * 第三方登录
- * @param type
- */
-const doSocialLogin = (type: string) => {
-  authRouterUrl(type, loginForm.value.tenantId).then((res: any) => {
-    if (res.code === HttpStatus.SUCCESS) {
-      // 获取授权地址跳转
-      window.location.href = res.data;
-    } else {
-      ElMessage.error(res.msg);
-    }
-  });
-};
-
-onMounted(() => {
-  getCode();
-  initTenantList();
-  getLoginData();
-});
-</script>
-
-<style lang="scss" scoped>
-.login {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  height: 100%;
-  background-image: url('../assets/images/login-background.jpg');
-  background-size: cover;
-}
-
-.title-box {
-  display: flex;
-
-  .title {
-    margin: 0px auto 30px auto;
-    text-align: center;
-    color: #707070;
-  }
-
-  :deep(.lang-select--style) {
-    line-height: 0;
-    color: #7483a3;
-  }
-}
-
-.login-form {
-  border-radius: 6px;
-  background: #ffffff;
-  width: 400px;
-  padding: 25px 25px 5px 25px;
-  z-index: 1;
-  .el-input {
-    height: 40px;
-    input {
-      height: 40px;
-    }
-  }
-
-  .input-icon {
-    height: 39px;
-    width: 14px;
-    margin-left: 0px;
-  }
-}
-
-.login-tip {
-  font-size: 13px;
-  text-align: center;
-  color: #bfbfbf;
-}
-
-.login-code {
-  width: 33%;
-  height: 40px;
-  float: right;
-
-  img {
-    cursor: pointer;
-    vertical-align: middle;
-  }
-}
-
-.el-login-footer {
-  height: 40px;
-  line-height: 40px;
-  position: fixed;
-  bottom: 0;
-  width: 100%;
-  text-align: center;
-  color: #fff;
-  font-family: Arial, serif;
-  font-size: 12px;
-  letter-spacing: 1px;
-}
-
-.login-code-img {
-  height: 40px;
-  padding-left: 12px;
-}
-</style>

+ 0 - 9
src/views/monitor/admin/index.vue

@@ -1,9 +0,0 @@
-<template>
-  <div>
-    <i-frame v-model:src="url"></i-frame>
-  </div>
-</template>
-
-<script setup lang="ts">
-const url = ref(import.meta.env.VITE_APP_MONITOR_ADMIN);
-</script>

+ 0 - 192
src/views/monitor/cache/index.vue

@@ -1,192 +0,0 @@
-<template>
-  <div class="p-2">
-    <el-row :gutter="10">
-      <el-col :span="24" class="card-box">
-        <el-card shadow="hover">
-          <template #header>
-            <Monitor style="width: 1em; height: 1em; vertical-align: middle" />
-            <span style="vertical-align: middle">基本信息</span>
-          </template>
-
-          <div class="el-table el-table--enable-row-hover el-table--medium">
-            <table style="width: 100%">
-              <tbody>
-                <tr>
-                  <td class="el-table__cell is-leaf">
-                    <div class="cell">Redis版本</div>
-                  </td>
-                  <td class="el-table__cell is-leaf">
-                    <div v-if="cache.info" class="cell">{{ cache.info.redis_version }}</div>
-                  </td>
-                  <td class="el-table__cell is-leaf">
-                    <div class="cell">运行模式</div>
-                  </td>
-                  <td class="el-table__cell is-leaf">
-                    <div v-if="cache.info" class="cell">{{ cache.info.redis_mode === 'standalone' ? '单机' : '集群' }}</div>
-                  </td>
-                  <td class="el-table__cell is-leaf">
-                    <div class="cell">端口</div>
-                  </td>
-                  <td class="el-table__cell is-leaf">
-                    <div v-if="cache.info" class="cell">{{ cache.info.tcp_port }}</div>
-                  </td>
-                  <td class="el-table__cell is-leaf">
-                    <div class="cell">客户端数</div>
-                  </td>
-                  <td class="el-table__cell is-leaf">
-                    <div v-if="cache.info" class="cell">{{ cache.info.connected_clients }}</div>
-                  </td>
-                </tr>
-                <tr>
-                  <td class="el-table__cell is-leaf">
-                    <div class="cell">运行时间(天)</div>
-                  </td>
-                  <td class="el-table__cell is-leaf">
-                    <div v-if="cache.info" class="cell">{{ cache.info.uptime_in_days }}</div>
-                  </td>
-                  <td class="el-table__cell is-leaf">
-                    <div class="cell">使用内存</div>
-                  </td>
-                  <td class="el-table__cell is-leaf">
-                    <div v-if="cache.info" class="cell">{{ cache.info.used_memory_human }}</div>
-                  </td>
-                  <td class="el-table__cell is-leaf">
-                    <div class="cell">使用CPU</div>
-                  </td>
-                  <td class="el-table__cell is-leaf">
-                    <div v-if="cache.info" class="cell">{{ parseFloat(cache.info.used_cpu_user_children).toFixed(2) }}</div>
-                  </td>
-                  <td class="el-table__cell is-leaf">
-                    <div class="cell">内存配置</div>
-                  </td>
-                  <td class="el-table__cell is-leaf">
-                    <div v-if="cache.info" class="cell">{{ cache.info.maxmemory_human }}</div>
-                  </td>
-                </tr>
-                <tr>
-                  <td class="el-table__cell is-leaf">
-                    <div class="cell">AOF是否开启</div>
-                  </td>
-                  <td class="el-table__cell is-leaf">
-                    <div v-if="cache.info" class="cell">{{ cache.info.aof_enabled === '0' ? '否' : '是' }}</div>
-                  </td>
-                  <td class="el-table__cell is-leaf">
-                    <div class="cell">RDB是否成功</div>
-                  </td>
-                  <td class="el-table__cell is-leaf">
-                    <div v-if="cache.info" class="cell">{{ cache.info.rdb_last_bgsave_status }}</div>
-                  </td>
-                  <td class="el-table__cell is-leaf">
-                    <div class="cell">Key数量</div>
-                  </td>
-                  <td class="el-table__cell is-leaf">
-                    <div v-if="cache.dbSize" class="cell">{{ cache.dbSize }}</div>
-                  </td>
-                  <td class="el-table__cell is-leaf">
-                    <div class="cell">网络入口/出口</div>
-                  </td>
-                  <td class="el-table__cell is-leaf">
-                    <div v-if="cache.info" class="cell">
-                      {{ cache.info.instantaneous_input_kbps }}kps/{{ cache.info.instantaneous_output_kbps }}kps
-                    </div>
-                  </td>
-                </tr>
-              </tbody>
-            </table>
-          </div>
-        </el-card>
-      </el-col>
-
-      <el-col :span="12" class="card-box">
-        <el-card shadow="hover">
-          <template #header>
-            <PieChart style="width: 1em; height: 1em; vertical-align: middle" />
-            <span style="vertical-align: middle">命令统计</span>
-          </template>
-          <div class="el-table el-table--enable-row-hover el-table--medium">
-            <div ref="commandstats" style="height: 420px" />
-          </div>
-        </el-card>
-      </el-col>
-
-      <el-col :span="12" class="card-box">
-        <el-card shadow="hover">
-          <template #header>
-            <Odometer style="width: 1em; height: 1em; vertical-align: middle" /> <span style="vertical-align: middle">内存信息</span>
-          </template>
-          <div class="el-table el-table--enable-row-hover el-table--medium">
-            <div ref="usedmemory" style="height: 420px" />
-          </div>
-        </el-card>
-      </el-col>
-    </el-row>
-  </div>
-</template>
-
-<script setup name="Cache" lang="ts">
-import { getCache } from '@/api/monitor/cache';
-import * as echarts from 'echarts';
-import { CacheVO } from '@/api/monitor/cache/types';
-
-const cache = ref<Partial<CacheVO>>({});
-const commandstats = ref();
-const usedmemory = ref();
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const getList = async () => {
-  proxy?.$modal.loading('正在加载缓存监控数据,请稍候!');
-  const res = await getCache();
-  proxy?.$modal.closeLoading();
-  cache.value = res.data;
-  const commandstatsIntance = echarts.init(commandstats.value, 'macarons');
-  commandstatsIntance.setOption({
-    tooltip: {
-      trigger: 'item',
-      formatter: '{a} <br/>{b} : {c} ({d}%)'
-    },
-    series: [
-      {
-        name: '命令',
-        type: 'pie',
-        roseType: 'radius',
-        radius: [15, 95],
-        center: ['50%', '38%'],
-        data: res.data.commandStats,
-        animationEasing: 'cubicInOut',
-        animationDuration: 1000
-      }
-    ]
-  });
-  const usedmemoryInstance = echarts.init(usedmemory.value, 'macarons');
-  usedmemoryInstance.setOption({
-    tooltip: {
-      formatter: '{b} <br/>{a} : ' + cache.value.info.used_memory_human
-    },
-    series: [
-      {
-        name: '峰值',
-        type: 'gauge',
-        min: 0,
-        max: 1000,
-        detail: {
-          formatter: cache.value.info.used_memory_human
-        },
-        data: [
-          {
-            value: parseFloat(cache.value.info.used_memory_human),
-            name: '内存消耗'
-          }
-        ]
-      }
-    ]
-  });
-  window.addEventListener('resize', () => {
-    commandstatsIntance.resize();
-    usedmemoryInstance.resize();
-  });
-};
-
-onMounted(() => {
-  getList();
-});
-</script>

+ 0 - 209
src/views/monitor/logininfor/index.vue

@@ -1,209 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
-        <el-card shadow="hover">
-          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="登录地址" prop="ipaddr">
-              <el-input v-model="queryParams.ipaddr" placeholder="请输入登录地址" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="用户名称" prop="userName">
-              <el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="状态" prop="status">
-              <el-select v-model="queryParams.status" placeholder="登录状态" clearable>
-                <el-option v-for="dict in sys_common_status" :key="dict.value" :label="dict.label" :value="dict.value" />
-              </el-select>
-            </el-form-item>
-            <el-form-item label="登录时间" style="width: 308px">
-              <el-date-picker
-                v-model="dateRange"
-                value-format="YYYY-MM-DD HH:mm:ss"
-                type="daterange"
-                range-separator="-"
-                start-placeholder="开始日期"
-                end-placeholder="结束日期"
-                :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
-              ></el-date-picker>
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
-      </div>
-    </transition>
-
-    <el-card shadow="hover">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['monitor:logininfor:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">
-              删除
-            </el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['monitor:logininfor:remove']" type="danger" plain icon="Delete" @click="handleClean">清空</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['monitor:logininfor:unlock']" type="primary" plain icon="Unlock" :disabled="single" @click="handleUnlock">
-              解锁
-            </el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['monitor:logininfor:export']" type="warning" plain icon="Download" @click="handleExport">导出</el-button>
-          </el-col>
-          <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
-        </el-row>
-      </template>
-
-      <el-table
-        ref="loginInfoTableRef"
-        v-loading="loading"
-        :data="loginInfoList"
-        :default-sort="defaultSort"
-        border
-        @selection-change="handleSelectionChange"
-        @sort-change="handleSortChange"
-      >
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column label="访问编号" align="center" prop="infoId" />
-        <el-table-column
-          label="用户名称"
-          align="center"
-          prop="userName"
-          :show-overflow-tooltip="true"
-          sortable="custom"
-          :sort-orders="['descending', 'ascending']"
-        />
-        <el-table-column label="客户端" align="center" prop="clientKey" :show-overflow-tooltip="true" />
-        <el-table-column label="设备类型" align="center">
-          <template #default="scope">
-            <dict-tag :options="sys_device_type" :value="scope.row.deviceType" />
-          </template>
-        </el-table-column>
-        <el-table-column label="地址" align="center" prop="ipaddr" :show-overflow-tooltip="true" />
-        <el-table-column label="登录地点" align="center" prop="loginLocation" :show-overflow-tooltip="true" />
-        <el-table-column label="操作系统" align="center" prop="os" :show-overflow-tooltip="true" />
-        <el-table-column label="浏览器" align="center" prop="browser" :show-overflow-tooltip="true" />
-        <el-table-column label="登录状态" align="center" prop="status">
-          <template #default="scope">
-            <dict-tag :options="sys_common_status" :value="scope.row.status" />
-          </template>
-        </el-table-column>
-        <el-table-column label="描述" align="center" prop="msg" :show-overflow-tooltip="true" />
-        <el-table-column label="访问时间" align="center" prop="loginTime" sortable="custom" :sort-orders="['descending', 'ascending']" width="180">
-          <template #default="scope">
-            <span>{{ proxy.parseTime(scope.row.loginTime) }}</span>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
-    </el-card>
-  </div>
-</template>
-
-<script setup name="Logininfor" lang="ts">
-import { list, delLoginInfo, cleanLoginInfo, unlockLoginInfo } from '@/api/monitor/loginInfo';
-import { LoginInfoQuery, LoginInfoVO } from '@/api/monitor/loginInfo/types';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { sys_device_type } = toRefs<any>(proxy?.useDict('sys_device_type'));
-const { sys_common_status } = toRefs<any>(proxy?.useDict('sys_common_status'));
-
-const loginInfoList = ref<LoginInfoVO[]>([]);
-const loading = ref(true);
-const showSearch = ref(true);
-const ids = ref<Array<number | string>>([]);
-const single = ref(true);
-const multiple = ref(true);
-const selectName = ref<Array<string>>([]);
-const total = ref(0);
-const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
-const defaultSort = ref<any>({ prop: 'loginTime', order: 'descending' });
-
-const queryFormRef = ref<ElFormInstance>();
-const loginInfoTableRef = ref<ElTableInstance>();
-// 查询参数
-const queryParams = ref<LoginInfoQuery>({
-  pageNum: 1,
-  pageSize: 10,
-  ipaddr: '',
-  userName: '',
-  status: '',
-  orderByColumn: defaultSort.value.prop,
-  isAsc: defaultSort.value.order
-});
-
-/** 查询登录日志列表 */
-const getList = async () => {
-  loading.value = true;
-  const res = await list(proxy?.addDateRange(queryParams.value, dateRange.value));
-  loginInfoList.value = res.rows;
-  total.value = res.total;
-  loading.value = false;
-};
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.value.pageNum = 1;
-  getList();
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  dateRange.value = ['', ''];
-  queryFormRef.value?.resetFields();
-  queryParams.value.pageNum = 1;
-  loginInfoTableRef.value?.sort(defaultSort.value.prop, defaultSort.value.order);
-};
-/** 多选框选中数据 */
-const handleSelectionChange = (selection: LoginInfoVO[]) => {
-  ids.value = selection.map((item) => item.infoId);
-  multiple.value = !selection.length;
-  single.value = selection.length != 1;
-  selectName.value = selection.map((item) => item.userName);
-};
-/** 排序触发事件 */
-const handleSortChange = (column: any) => {
-  queryParams.value.orderByColumn = column.prop;
-  queryParams.value.isAsc = column.order;
-  getList();
-};
-/** 删除按钮操作 */
-const handleDelete = async (row?: LoginInfoVO) => {
-  const infoIds = row?.infoId || ids.value;
-  await proxy?.$modal.confirm('是否确认删除访问编号为"' + infoIds + '"的数据项?');
-  await delLoginInfo(infoIds);
-  await getList();
-  proxy?.$modal.msgSuccess('删除成功');
-};
-/** 清空按钮操作 */
-const handleClean = async () => {
-  await proxy?.$modal.confirm('是否确认清空所有登录日志数据项?');
-  await cleanLoginInfo();
-  await getList();
-  proxy?.$modal.msgSuccess('清空成功');
-};
-/** 解锁按钮操作 */
-const handleUnlock = async () => {
-  const username = selectName.value;
-  await proxy?.$modal.confirm('是否确认解锁用户"' + username + '"数据项?');
-  await unlockLoginInfo(username);
-  proxy?.$modal.msgSuccess('用户' + username + '解锁成功');
-};
-/** 导出按钮操作 */
-const handleExport = () => {
-  proxy?.download(
-    'monitor/logininfor/export',
-    {
-      ...queryParams.value
-    },
-    `logininfor_${new Date().getTime()}.xlsx`
-  );
-};
-
-onMounted(() => {
-  getList();
-});
-</script>

+ 0 - 117
src/views/monitor/online/index.vue

@@ -1,117 +0,0 @@
-<template>
-  <div class="p-2">
-    <div class="mb-[10px]">
-      <el-card shadow="hover">
-        <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-          <el-form-item label="登录地址" prop="ipaddr">
-            <el-input v-model="queryParams.ipaddr" placeholder="请输入登录地址" clearable @keyup.enter="handleQuery" />
-          </el-form-item>
-          <el-form-item label="用户名称" prop="userName">
-            <el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable @keyup.enter="handleQuery" />
-          </el-form-item>
-          <el-form-item>
-            <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-            <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-          </el-form-item>
-        </el-form>
-      </el-card>
-    </div>
-    <el-card shadow="hover">
-      <el-table
-        v-loading="loading"
-        border
-        :data="onlineList.slice((queryParams.pageNum - 1) * queryParams.pageSize, queryParams.pageNum * queryParams.pageSize)"
-        style="width: 100%"
-      >
-        <el-table-column label="序号" width="50" type="index" align="center">
-          <template #default="scope">
-            <span>{{ (queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1 }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="会话编号" align="center" prop="tokenId" :show-overflow-tooltip="true" />
-        <el-table-column label="登录名称" align="center" prop="userName" :show-overflow-tooltip="true" />
-        <el-table-column label="客户端" align="center" prop="clientKey" :show-overflow-tooltip="true" />
-        <el-table-column label="设备类型" align="center">
-          <template #default="scope">
-            <dict-tag :options="sys_device_type" :value="scope.row.deviceType" />
-          </template>
-        </el-table-column>
-        <el-table-column label="所属部门" align="center" prop="deptName" :show-overflow-tooltip="true" />
-        <el-table-column label="主机" align="center" prop="ipaddr" :show-overflow-tooltip="true" />
-        <el-table-column label="登录地点" align="center" prop="loginLocation" :show-overflow-tooltip="true" />
-        <el-table-column label="操作系统" align="center" prop="os" :show-overflow-tooltip="true" />
-        <el-table-column label="浏览器" align="center" prop="browser" :show-overflow-tooltip="true" />
-        <el-table-column label="登录时间" align="center" prop="loginTime" width="180">
-          <template #default="scope">
-            <span>{{ proxy.parseTime(scope.row.loginTime) }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
-          <template #default="scope">
-            <el-tooltip content="强退" placement="top">
-              <el-button v-hasPermi="['monitor:online:forceLogout']" link type="primary" icon="Delete" @click="handleForceLogout(scope.row)">
-              </el-button>
-            </el-tooltip>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" />
-    </el-card>
-  </div>
-</template>
-
-<script setup name="Online" lang="ts">
-import { forceLogout, list as initData } from '@/api/monitor/online';
-import { OnlineQuery, OnlineVO } from '@/api/monitor/online/types';
-import api from '@/api/system/user';
-import { to } from 'await-to-js';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { sys_device_type } = toRefs<any>(proxy?.useDict('sys_device_type'));
-
-const onlineList = ref<OnlineVO[]>([]);
-const loading = ref(true);
-const total = ref(0);
-
-const queryFormRef = ref<ElFormInstance>();
-
-const queryParams = ref<OnlineQuery>({
-  pageNum: 1,
-  pageSize: 10,
-  ipaddr: '',
-  userName: ''
-});
-
-/** 查询登录日志列表 */
-const getList = async () => {
-  loading.value = true;
-  const res = await initData(queryParams.value);
-  onlineList.value = res.rows;
-  total.value = res.total;
-  loading.value = false;
-};
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.value.pageNum = 1;
-  getList();
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  handleQuery();
-};
-/** 强退按钮操作 */
-const handleForceLogout = async (row: OnlineVO) => {
-  const [err] = await to(proxy?.$modal.confirm('是否确认强退名称为"' + row.userName + '"的用户?') as any);
-  if (!err) {
-    await forceLogout(row.tokenId);
-    await getList();
-    proxy?.$modal.msgSuccess('删除成功');
-  }
-};
-
-onMounted(() => {
-  getList();
-});
-</script>

+ 0 - 261
src/views/monitor/operlog/index.vue

@@ -1,261 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
-        <el-card shadow="hover">
-          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="操作地址" prop="operIp">
-              <el-input v-model="queryParams.operIp" placeholder="请输入操作地址" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="系统模块" prop="title">
-              <el-input v-model="queryParams.title" placeholder="请输入系统模块" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="操作人员" prop="operName">
-              <el-input v-model="queryParams.operName" placeholder="请输入操作人员" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="类型" prop="businessType">
-              <el-select v-model="queryParams.businessType" placeholder="操作类型" clearable>
-                <el-option v-for="dict in sys_oper_type" :key="dict.value" :label="dict.label" :value="dict.value" />
-              </el-select>
-            </el-form-item>
-            <el-form-item label="状态" prop="status">
-              <el-select v-model="queryParams.status" placeholder="操作状态" clearable>
-                <el-option v-for="dict in sys_common_status" :key="dict.value" :label="dict.label" :value="dict.value" />
-              </el-select>
-            </el-form-item>
-            <el-form-item label="操作时间" style="width: 308px">
-              <el-date-picker
-                v-model="dateRange"
-                value-format="YYYY-MM-DD HH:mm:ss"
-                type="daterange"
-                range-separator="-"
-                start-placeholder="开始日期"
-                end-placeholder="结束日期"
-                :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
-              ></el-date-picker>
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
-      </div>
-    </transition>
-
-    <el-card shadow="hover">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['monitor:operlog:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">
-              删除
-            </el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['monitor:operlog:remove']" type="danger" plain icon="WarnTriangleFilled" @click="handleClean">清空</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['monitor:operlog:export']" type="warning" plain icon="Download" @click="handleExport">导出</el-button>
-          </el-col>
-          <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
-        </el-row>
-      </template>
-
-      <el-table
-        ref="operLogTableRef"
-        v-loading="loading"
-        :data="operlogList"
-        border
-        :default-sort="defaultSort"
-        @selection-change="handleSelectionChange"
-        @sort-change="handleSortChange"
-      >
-        <el-table-column type="selection" width="50" align="center" />
-        <el-table-column label="日志编号" align="center" prop="operId" />
-        <el-table-column label="系统模块" align="center" prop="title" :show-overflow-tooltip="true" />
-        <el-table-column label="操作类型" align="center" prop="businessType">
-          <template #default="scope">
-            <dict-tag :options="sys_oper_type" :value="scope.row.businessType" />
-          </template>
-        </el-table-column>
-        <el-table-column
-          label="操作人员"
-          align="center"
-          width="110"
-          prop="operName"
-          :show-overflow-tooltip="true"
-          sortable="custom"
-          :sort-orders="['descending', 'ascending']"
-        />
-        <el-table-column label="部门" align="center" prop="deptName" width="130" :show-overflow-tooltip="true" />
-        <el-table-column label="操作地址" align="center" prop="operIp" width="130" :show-overflow-tooltip="true" />
-        <el-table-column label="操作状态" align="center" prop="status">
-          <template #default="scope">
-            <dict-tag :options="sys_common_status" :value="scope.row.status" />
-          </template>
-        </el-table-column>
-        <el-table-column label="操作日期" align="center" prop="operTime" width="180" sortable="custom" :sort-orders="['descending', 'ascending']">
-          <template #default="scope">
-            <span>{{ proxy.parseTime(scope.row.operTime) }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column
-          label="消耗时间"
-          align="center"
-          prop="costTime"
-          width="110"
-          :show-overflow-tooltip="true"
-          sortable="custom"
-          :sort-orders="['descending', 'ascending']"
-        >
-          <template #default="scope">
-            <span>{{ scope.row.costTime }}毫秒</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="操作" fixed="right" align="center" class-name="small-padding fixed-width">
-          <template #default="scope">
-            <el-tooltip content="详细" placement="top">
-              <el-button v-hasPermi="['monitor:operlog:query']" link type="primary" icon="View" @click="handleView(scope.row)"> </el-button>
-            </el-tooltip>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
-    </el-card>
-    <!-- 操作日志详细 -->
-    <OperInfoDialog ref="operInfoDialogRef" />
-  </div>
-</template>
-
-<script setup name="Operlog" lang="ts">
-import { list, delOperlog, cleanOperlog } from '@/api/monitor/operlog';
-import { OperLogForm, OperLogQuery, OperLogVO } from '@/api/monitor/operlog/types';
-import OperInfoDialog from './oper-info-dialog.vue';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { sys_oper_type, sys_common_status } = toRefs<any>(proxy?.useDict('sys_oper_type', 'sys_common_status'));
-
-const operlogList = ref<OperLogVO[]>([]);
-const loading = ref(true);
-const showSearch = ref(true);
-const ids = ref<Array<number | string>>([]);
-const multiple = ref(true);
-const total = ref(0);
-const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
-const defaultSort = ref<any>({ prop: 'operTime', order: 'descending' });
-
-const operLogTableRef = ref<ElTableInstance>();
-const queryFormRef = ref<ElFormInstance>();
-
-const data = reactive<PageData<OperLogForm, OperLogQuery>>({
-  form: {
-    operId: undefined,
-    tenantId: undefined,
-    title: '',
-    businessType: 0,
-    businessTypes: undefined,
-    method: '',
-    requestMethod: '',
-    operatorType: 0,
-    operName: '',
-    deptName: '',
-    operUrl: '',
-    operIp: '',
-    operLocation: '',
-    operParam: '',
-    jsonResult: '',
-    status: 0,
-    errorMsg: '',
-    operTime: '',
-    costTime: 0
-  },
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    operIp: '',
-    title: '',
-    operName: '',
-    businessType: '',
-    status: '',
-    orderByColumn: defaultSort.value.prop,
-    isAsc: defaultSort.value.order
-  },
-  rules: {}
-});
-
-const { queryParams, form } = toRefs(data);
-
-/** 查询登录日志 */
-const getList = async () => {
-  loading.value = true;
-  const res = await list(proxy?.addDateRange(queryParams.value, dateRange.value));
-  operlogList.value = res.rows;
-  total.value = res.total;
-  loading.value = false;
-};
-/** 操作日志类型字典翻译 */
-const typeFormat = (row: OperLogForm) => {
-  return proxy?.selectDictLabel(sys_oper_type.value, row.businessType);
-};
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.value.pageNum = 1;
-  getList();
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  dateRange.value = ['', ''];
-  queryFormRef.value?.resetFields();
-  queryParams.value.pageNum = 1;
-  operLogTableRef.value?.sort(defaultSort.value.prop, defaultSort.value.order);
-};
-/** 多选框选中数据 */
-const handleSelectionChange = (selection: OperLogVO[]) => {
-  ids.value = selection.map((item) => item.operId);
-  multiple.value = !selection.length;
-};
-/** 排序触发事件 */
-const handleSortChange = (column: any) => {
-  queryParams.value.orderByColumn = column.prop;
-  queryParams.value.isAsc = column.order;
-  getList();
-};
-
-const operInfoDialogRef = ref<InstanceType<typeof OperInfoDialog>>();
-/** 详细按钮操作 */
-const handleView = (row: OperLogVO) => {
-  operInfoDialogRef.value.openDialog(row);
-};
-
-/** 删除按钮操作 */
-const handleDelete = async (row?: OperLogVO) => {
-  const operIds = row?.operId || ids.value;
-  await proxy?.$modal.confirm('是否确认删除日志编号为"' + operIds + '"的数据项?');
-  await delOperlog(operIds);
-  await getList();
-  proxy?.$modal.msgSuccess('删除成功');
-};
-
-/** 清空按钮操作 */
-const handleClean = async () => {
-  await proxy?.$modal.confirm('是否确认清空所有操作日志数据项?');
-  await cleanOperlog();
-  await getList();
-  proxy?.$modal.msgSuccess('清空成功');
-};
-
-/** 导出按钮操作 */
-const handleExport = () => {
-  proxy?.download(
-    'monitor/operlog/export',
-    {
-      ...queryParams.value
-    },
-    `config_${new Date().getTime()}.xlsx`
-  );
-};
-onMounted(() => {
-  getList();
-});
-</script>

+ 0 - 111
src/views/monitor/operlog/oper-info-dialog.vue

@@ -1,111 +0,0 @@
-<template>
-  <el-dialog v-model="open" title="操作日志详细" width="700px" append-to-body close-on-click-modal @closed="info = null">
-    <el-descriptions v-if="info" :column="1" border>
-      <el-descriptions-item label="操作状态">
-        <template #default>
-          <el-tag v-if="info.status === 0" type="success">正常</el-tag>
-          <el-tag v-else-if="info.status === 1" type="danger">失败</el-tag>
-        </template>
-      </el-descriptions-item>
-      <el-descriptions-item label="登录信息">
-        <template #default> {{ info.operName }} / {{ info.deptName }} / {{ info.operIp }} / {{ info.operLocation }} </template>
-      </el-descriptions-item>
-      <el-descriptions-item label="请求信息">
-        <template #default> {{ info.requestMethod }} {{ info.operUrl }} </template>
-      </el-descriptions-item>
-      <el-descriptions-item label="操作模块">
-        <template #default> {{ info.title }} / {{ typeFormat(info) }} </template>
-      </el-descriptions-item>
-      <el-descriptions-item label="操作方法">
-        <template #default>
-          {{ info.method }}
-        </template>
-      </el-descriptions-item>
-      <el-descriptions-item label="请求参数">
-        <template #default>
-          <div class="max-h-300px overflow-y-auto">
-            <VueJsonPretty :data="formatToJsonObject(info.operParam)" />
-          </div>
-        </template>
-      </el-descriptions-item>
-      <el-descriptions-item label="返回参数">
-        <template #default>
-          <div class="max-h-300px overflow-y-auto">
-            <VueJsonPretty :data="formatToJsonObject(info.jsonResult)" />
-          </div>
-        </template>
-      </el-descriptions-item>
-      <el-descriptions-item label="消耗时间">
-        <template #default>
-          <span> {{ info.costTime }}ms </span>
-        </template>
-      </el-descriptions-item>
-      <el-descriptions-item label="操作时间">
-        <template #default> {{ proxy.parseTime(info.operTime) }}</template>
-      </el-descriptions-item>
-      <el-descriptions-item v-if="info.status === 1" label="异常信息">
-        <template #default>
-          <span class="text-danger"> {{ info.errorMsg }}</span>
-        </template>
-      </el-descriptions-item>
-    </el-descriptions>
-  </el-dialog>
-</template>
-
-<script setup lang="ts">
-import type { OperLogForm } from '@/api/monitor/operlog/types';
-import VueJsonPretty from 'vue-json-pretty';
-import 'vue-json-pretty/lib/styles.css';
-
-const open = ref(false);
-const info = ref<OperLogForm | null>(null);
-function openDialog(row: OperLogForm) {
-  info.value = row;
-  open.value = true;
-}
-
-function closeDialog() {
-  open.value = false;
-}
-
-defineExpose({
-  openDialog,
-  closeDialog
-});
-
-/**
- * json转为对象
- * @param data 原始数据
- */
-function formatToJsonObject(data: string) {
-  try {
-    return JSON.parse(data);
-  } catch (error) {
-    return data;
-  }
-}
-
-/**
- * 字典信息
- */
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { sys_oper_type } = toRefs<any>(proxy?.useDict('sys_oper_type'));
-const typeFormat = (row: OperLogForm) => {
-  return proxy?.selectDictLabel(sys_oper_type.value, row.businessType);
-};
-</script>
-
-<style lang="scss" scoped>
-/**
-label宽度固定
-*/
-:deep(.el-descriptions__label) {
-  min-width: 100px;
-}
-/**
-文字超过 换行显示
-*/
-:deep(.el-descriptions__content) {
-  max-width: 300px;
-}
-</style>

+ 0 - 9
src/views/monitor/snailjob/index.vue

@@ -1,9 +0,0 @@
-<template>
-  <div>
-    <i-frame v-model:src="url"></i-frame>
-  </div>
-</template>
-
-<script setup lang="ts">
-const url = ref(import.meta.env.VITE_APP_SNAILJOB_ADMIN);
-</script>

+ 0 - 316
src/views/system/client/index.vue

@@ -1,316 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="search">
-        <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="85px">
-          <el-form-item label="客户端key" prop="clientKey">
-            <el-input v-model="queryParams.clientKey" placeholder="请输入客户端key" clearable @keyup.enter="handleQuery" />
-          </el-form-item>
-          <el-form-item label="客户端秘钥" prop="clientSecret">
-            <el-input v-model="queryParams.clientSecret" placeholder="请输入客户端秘钥" clearable @keyup.enter="handleQuery" />
-          </el-form-item>
-          <el-form-item label="状态" prop="status">
-            <el-select v-model="queryParams.status" placeholder="状态" clearable>
-              <el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
-            </el-select>
-          </el-form-item>
-          <el-form-item>
-            <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-            <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-          </el-form-item>
-        </el-form>
-      </div>
-    </transition>
-
-    <el-card shadow="never">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:client:add']" type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:client:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()">
-              修改
-            </el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:client:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">
-              删除
-            </el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:client:export']" type="warning" plain icon="Download" @click="handleExport">导出</el-button>
-          </el-col>
-          <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
-        </el-row>
-      </template>
-
-      <el-table v-loading="loading" :data="clientList" border @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column v-if="true" label="id" align="center" prop="id" />
-        <el-table-column label="客户端id" align="center" prop="clientId" />
-        <el-table-column label="客户端key" align="center" prop="clientKey" />
-        <el-table-column label="客户端秘钥" align="center" prop="clientSecret" />
-        <el-table-column label="授权类型" align="center">
-          <template #default="scope">
-            <dict-tag :options="sys_grant_type" :value="scope.row.grantTypeList" />
-          </template>
-        </el-table-column>
-        <el-table-column label="设备类型" align="center">
-          <template #default="scope">
-            <dict-tag :options="sys_device_type" :value="scope.row.deviceType" />
-          </template>
-        </el-table-column>
-        <el-table-column label="Token活跃超时时间" align="center" prop="activeTimeout" />
-        <el-table-column label="Token固定超时时间" align="center" prop="timeout" />
-        <el-table-column key="status" label="状态" align="center">
-          <template #default="scope">
-            <el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
-          </template>
-        </el-table-column>
-        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
-          <template #default="scope">
-            <el-tooltip content="修改" placement="top">
-              <el-button v-hasPermi="['system:client:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>
-            </el-tooltip>
-            <el-tooltip content="删除" placement="top">
-              <el-button v-hasPermi="['system:client:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
-            </el-tooltip>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
-    </el-card>
-    <!-- 添加或修改客户端管理对话框 -->
-    <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body>
-      <el-form ref="clientFormRef" :model="form" :rules="rules" label-width="100px">
-        <el-form-item label="客户端key" prop="clientKey">
-          <el-input v-model="form.clientKey" :disabled="form.id != null" placeholder="请输入客户端key" />
-        </el-form-item>
-        <el-form-item label="客户端秘钥" prop="clientSecret">
-          <el-input v-model="form.clientSecret" :disabled="form.id != null" placeholder="请输入客户端秘钥" />
-        </el-form-item>
-        <el-form-item label="授权类型" prop="grantTypeList">
-          <el-select v-model="form.grantTypeList" multiple placeholder="请输入授权类型">
-            <el-option v-for="dict in sys_grant_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
-          </el-select>
-        </el-form-item>
-        <el-form-item label="设备类型" prop="deviceType">
-          <el-select v-model="form.deviceType" placeholder="请输入设备类型">
-            <el-option v-for="dict in sys_device_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
-          </el-select>
-        </el-form-item>
-        <el-form-item prop="activeTimeout" label-width="auto">
-          <template #label>
-            <span>
-              <el-tooltip content="指定时间无操作则过期(单位:秒),默认30分钟(1800秒)" placement="top">
-                <el-icon><question-filled /></el-icon>
-              </el-tooltip>
-              Token活跃超时时间
-            </span>
-          </template>
-          <el-input v-model="form.activeTimeout" placeholder="请输入Token活跃超时时间" />
-        </el-form-item>
-        <el-form-item prop="timeout" label-width="auto">
-          <template #label>
-            <span>
-              <el-tooltip content="指定时间必定过期(单位:秒),默认七天(604800秒)" placement="top">
-                <el-icon><question-filled /></el-icon>
-              </el-tooltip>
-              Token固定超时时间
-            </span>
-          </template>
-          <el-input v-model="form.timeout" placeholder="请输入Token固定超时时间" />
-        </el-form-item>
-        <el-form-item label="状态">
-          <el-radio-group v-model="form.status">
-            <el-radio v-for="dict in sys_normal_disable" :key="dict.value" :value="dict.value">
-              {{ dict.label }}
-            </el-radio>
-          </el-radio-group>
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
-          <el-button @click="cancel">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup name="Client" lang="ts">
-import { listClient, getClient, delClient, addClient, updateClient, changeStatus } from '@/api/system/client';
-import { ClientVO, ClientQuery, ClientForm } from '@/api/system/client/types';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { sys_normal_disable } = toRefs<any>(proxy?.useDict('sys_normal_disable'));
-const { sys_grant_type } = toRefs<any>(proxy?.useDict('sys_grant_type'));
-const { sys_device_type } = toRefs<any>(proxy?.useDict('sys_device_type'));
-
-const clientList = ref<ClientVO[]>([]);
-const buttonLoading = ref(false);
-const loading = ref(true);
-const showSearch = ref(true);
-const ids = ref<Array<string | number>>([]);
-const single = ref(true);
-const multiple = ref(true);
-const total = ref(0);
-
-const queryFormRef = ref<ElFormInstance>();
-const clientFormRef = ref<ElFormInstance>();
-
-const dialog = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-const initFormData: ClientForm = {
-  id: undefined,
-  clientId: undefined,
-  clientKey: undefined,
-  clientSecret: undefined,
-  grantTypeList: undefined,
-  deviceType: undefined,
-  activeTimeout: undefined,
-  timeout: undefined,
-  status: undefined
-};
-const data = reactive<PageData<ClientForm, ClientQuery>>({
-  form: { ...initFormData },
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    clientId: undefined,
-    clientKey: undefined,
-    clientSecret: undefined,
-    grantType: undefined,
-    deviceType: undefined,
-    activeTimeout: undefined,
-    timeout: undefined,
-    status: undefined
-  },
-  rules: {
-    id: [{ required: true, message: 'id不能为空', trigger: 'blur' }],
-    clientId: [{ required: true, message: '客户端id不能为空', trigger: 'blur' }],
-    clientKey: [{ required: true, message: '客户端key不能为空', trigger: 'blur' }],
-    clientSecret: [{ required: true, message: '客户端秘钥不能为空', trigger: 'blur' }],
-    grantTypeList: [{ required: true, message: '授权类型不能为空', trigger: 'change' }],
-    deviceType: [{ required: true, message: '设备类型不能为空', trigger: 'change' }]
-  }
-});
-
-const { queryParams, form, rules } = toRefs(data);
-
-/** 查询客户端管理列表 */
-const getList = async () => {
-  loading.value = true;
-  const res = await listClient(queryParams.value);
-  clientList.value = res.rows;
-  total.value = res.total;
-  loading.value = false;
-};
-
-/** 取消按钮 */
-const cancel = () => {
-  reset();
-  dialog.visible = false;
-};
-
-/** 表单重置 */
-const reset = () => {
-  form.value = { ...initFormData };
-  clientFormRef.value?.resetFields();
-};
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.value.pageNum = 1;
-  getList();
-};
-
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  handleQuery();
-};
-
-/** 多选框选中数据 */
-const handleSelectionChange = (selection: ClientVO[]) => {
-  ids.value = selection.map((item) => item.id);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
-};
-
-/** 新增按钮操作 */
-const handleAdd = () => {
-  reset();
-  dialog.visible = true;
-  dialog.title = '添加客户端管理';
-};
-
-/** 修改按钮操作 */
-const handleUpdate = async (row?: ClientVO) => {
-  reset();
-  const _id = row?.id || ids.value[0];
-  const res = await getClient(_id);
-  Object.assign(form.value, res.data);
-  dialog.visible = true;
-  dialog.title = '修改客户端管理';
-};
-
-/** 提交按钮 */
-const submitForm = () => {
-  clientFormRef.value?.validate(async (valid: boolean) => {
-    if (valid) {
-      buttonLoading.value = true;
-      if (form.value.id) {
-        await updateClient(form.value).finally(() => (buttonLoading.value = false));
-      } else {
-        await addClient(form.value).finally(() => (buttonLoading.value = false));
-      }
-      proxy?.$modal.msgSuccess('修改成功');
-      dialog.visible = false;
-      await getList();
-    }
-  });
-};
-
-/** 删除按钮操作 */
-const handleDelete = async (row?: ClientVO) => {
-  const _ids = row?.id || ids.value;
-  await proxy?.$modal.confirm('是否确认删除客户端管理编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
-  await delClient(_ids);
-  proxy?.$modal.msgSuccess('删除成功');
-  await getList();
-};
-
-/** 导出按钮操作 */
-const handleExport = () => {
-  proxy?.download(
-    'system/client/export',
-    {
-      ...queryParams.value
-    },
-    `client_${new Date().getTime()}.xlsx`
-  );
-};
-
-/** 状态修改  */
-const handleStatusChange = async (row: ClientVO) => {
-  const text = row.status === '0' ? '启用' : '停用';
-  try {
-    await proxy?.$modal.confirm('确认要"' + text + '"吗?');
-    await changeStatus(row.clientId, row.status);
-    proxy?.$modal.msgSuccess(text + '成功');
-  } catch (err) {
-    row.status = row.status === '0' ? '1' : '0';
-  }
-};
-
-onMounted(() => {
-  getList();
-});
-</script>

+ 0 - 261
src/views/system/config/index.vue

@@ -1,261 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
-        <el-card shadow="hover">
-          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="参数名称" prop="configName">
-              <el-input v-model="queryParams.configName" placeholder="请输入参数名称" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="参数键名" prop="configKey">
-              <el-input v-model="queryParams.configKey" placeholder="请输入参数键名" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="系统内置" prop="configType">
-              <el-select v-model="queryParams.configType" placeholder="系统内置" clearable>
-                <el-option v-for="dict in sys_yes_no" :key="dict.value" :label="dict.label" :value="dict.value" />
-              </el-select>
-            </el-form-item>
-            <el-form-item label="创建时间" style="width: 308px">
-              <el-date-picker
-                v-model="dateRange"
-                value-format="YYYY-MM-DD HH:mm:ss"
-                type="daterange"
-                range-separator="-"
-                start-placeholder="开始日期"
-                end-placeholder="结束日期"
-                :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
-              ></el-date-picker>
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
-      </div>
-    </transition>
-    <el-card shadow="hover">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:config:add']" type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:config:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()">
-              修改
-            </el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:config:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">
-              删除
-            </el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:config:export']" type="warning" plain icon="Download" @click="handleExport">导出</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:config:remove']" type="danger" plain icon="Refresh" @click="handleRefreshCache">刷新缓存</el-button>
-          </el-col>
-          <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
-        </el-row>
-      </template>
-
-      <el-table v-loading="loading" border :data="configList" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column v-if="false" label="参数主键" align="center" prop="configId" />
-        <el-table-column label="参数名称" align="center" prop="configName" :show-overflow-tooltip="true" />
-        <el-table-column label="参数键名" align="center" prop="configKey" :show-overflow-tooltip="true" />
-        <el-table-column label="参数键值" align="center" prop="configValue" :show-overflow-tooltip="true" />
-        <el-table-column label="系统内置" align="center" prop="configType">
-          <template #default="scope">
-            <dict-tag :options="sys_yes_no" :value="scope.row.configType" />
-          </template>
-        </el-table-column>
-        <el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" />
-        <el-table-column label="创建时间" align="center" prop="createTime" width="180">
-          <template #default="scope">
-            <span>{{ proxy.parseTime(scope.row.createTime) }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="操作" align="center" width="150" class-name="small-padding fixed-width">
-          <template #default="scope">
-            <el-tooltip content="修改" placement="top">
-              <el-button v-hasPermi="['system:config:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>
-            </el-tooltip>
-            <el-tooltip content="删除" placement="top">
-              <el-button v-hasPermi="['system:config:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
-            </el-tooltip>
-          </template>
-        </el-table-column>
-      </el-table>
-      <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
-    </el-card>
-
-    <!-- 添加或修改参数配置对话框 -->
-    <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body>
-      <el-form ref="configFormRef" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="参数名称" prop="configName">
-          <el-input v-model="form.configName" placeholder="请输入参数名称" />
-        </el-form-item>
-        <el-form-item label="参数键名" prop="configKey">
-          <el-input v-model="form.configKey" placeholder="请输入参数键名" />
-        </el-form-item>
-        <el-form-item label="参数键值" prop="configValue">
-          <el-input v-model="form.configValue" type="textarea" placeholder="请输入参数键值" />
-        </el-form-item>
-        <el-form-item label="系统内置" prop="configType">
-          <el-radio-group v-model="form.configType">
-            <el-radio v-for="dict in sys_yes_no" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label="备注" prop="remark">
-          <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button type="primary" @click="submitForm">确 定</el-button>
-          <el-button @click="cancel">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup name="Config" lang="ts">
-import { listConfig, getConfig, delConfig, addConfig, updateConfig, refreshCache } from '@/api/system/config';
-import { ConfigForm, ConfigQuery, ConfigVO } from '@/api/system/config/types';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { sys_yes_no } = toRefs<any>(proxy?.useDict('sys_yes_no'));
-
-const configList = ref<ConfigVO[]>([]);
-const loading = ref(true);
-const showSearch = ref(true);
-const ids = ref<Array<number | string>>([]);
-const single = ref(true);
-const multiple = ref(true);
-const total = ref(0);
-const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
-
-const queryFormRef = ref<ElFormInstance>();
-const configFormRef = ref<ElFormInstance>();
-const dialog = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-const initFormData: ConfigForm = {
-  configId: undefined,
-  configName: '',
-  configKey: '',
-  configValue: '',
-  configType: 'Y',
-  remark: ''
-};
-const data = reactive<PageData<ConfigForm, ConfigQuery>>({
-  form: { ...initFormData },
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    configName: '',
-    configKey: '',
-    configType: ''
-  },
-  rules: {
-    configName: [{ required: true, message: '参数名称不能为空', trigger: 'blur' }],
-    configKey: [{ required: true, message: '参数键名不能为空', trigger: 'blur' }],
-    configValue: [{ required: true, message: '参数键值不能为空', trigger: 'blur' }]
-  }
-});
-
-const { queryParams, form, rules } = toRefs(data);
-
-/** 查询参数列表 */
-const getList = async () => {
-  loading.value = true;
-  const res = await listConfig(proxy?.addDateRange(queryParams.value, dateRange.value));
-  configList.value = res.rows;
-  total.value = res.total;
-  loading.value = false;
-};
-/** 取消按钮 */
-const cancel = () => {
-  reset();
-  dialog.visible = false;
-};
-/** 表单重置 */
-const reset = () => {
-  form.value = { ...initFormData };
-  configFormRef.value?.resetFields();
-};
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.value.pageNum = 1;
-  getList();
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  dateRange.value = ['', ''];
-  queryFormRef.value?.resetFields();
-  handleQuery();
-};
-/** 多选框选中数据 */
-const handleSelectionChange = (selection: ConfigVO[]) => {
-  ids.value = selection.map((item) => item.configId);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
-};
-/** 新增按钮操作 */
-const handleAdd = () => {
-  reset();
-  dialog.visible = true;
-  dialog.title = '添加参数';
-};
-/** 修改按钮操作 */
-const handleUpdate = async (row?: ConfigVO) => {
-  reset();
-  const configId = row?.configId || ids.value[0];
-  const res = await getConfig(configId);
-  Object.assign(form.value, res.data);
-  dialog.visible = true;
-  dialog.title = '修改参数';
-};
-/** 提交按钮 */
-const submitForm = () => {
-  configFormRef.value?.validate(async (valid: boolean) => {
-    if (valid) {
-      form.value.configId ? await updateConfig(form.value) : await addConfig(form.value);
-      proxy?.$modal.msgSuccess('操作成功');
-      dialog.visible = false;
-      await getList();
-    }
-  });
-};
-/** 删除按钮操作 */
-const handleDelete = async (row?: ConfigVO) => {
-  const configIds = row?.configId || ids.value;
-  await proxy?.$modal.confirm('是否确认删除参数编号为"' + configIds + '"的数据项?');
-  await delConfig(configIds);
-  await getList();
-  proxy?.$modal.msgSuccess('删除成功');
-};
-/** 导出按钮操作 */
-const handleExport = () => {
-  proxy?.download(
-    'system/config/export',
-    {
-      ...queryParams.value
-    },
-    `config_${new Date().getTime()}.xlsx`
-  );
-};
-/** 刷新缓存按钮操作 */
-const handleRefreshCache = async () => {
-  await refreshCache();
-  proxy?.$modal.msgSuccess('刷新缓存成功');
-};
-
-onMounted(() => {
-  getList();
-});
-</script>

+ 0 - 320
src/views/system/dept/index.vue

@@ -1,320 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
-        <el-card shadow="hover">
-          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="部门名称" prop="deptName">
-              <el-input v-model="queryParams.deptName" placeholder="请输入部门名称" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="类别编码" prop="deptCategory">
-              <el-input v-model="queryParams.deptCategory" placeholder="请输入类别编码" clearable style="width: 240px" @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="状态" prop="status">
-              <el-select v-model="queryParams.status" placeholder="部门状态" clearable>
-                <el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
-              </el-select>
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
-      </div>
-    </transition>
-
-    <el-card shadow="hover">
-      <template #header>
-        <el-row :gutter="10">
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:dept:add']" type="primary" plain icon="Plus" @click="handleAdd()">新增 </el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="info" plain icon="Sort" @click="handleToggleExpandAll">展开/折叠</el-button>
-          </el-col>
-          <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
-        </el-row>
-      </template>
-
-      <el-table
-        ref="deptTableRef"
-        v-loading="loading"
-        :data="deptList"
-        row-key="deptId"
-        border
-        :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
-        :default-expand-all="isExpandAll"
-      >
-        <el-table-column prop="deptName" label="部门名称" width="260"></el-table-column>
-        <el-table-column prop="deptCategory" align="center" label="类别编码" width="200"></el-table-column>
-        <el-table-column prop="orderNum" align="center" label="排序" width="200"></el-table-column>
-        <el-table-column prop="status" align="center" label="状态" width="100">
-          <template #default="scope">
-            <dict-tag :options="sys_normal_disable" :value="scope.row.status" />
-          </template>
-        </el-table-column>
-        <el-table-column label="创建时间" align="center" prop="createTime" width="200">
-          <template #default="scope">
-            <span>{{ proxy.parseTime(scope.row.createTime) }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column fixed="right" align="center" label="操作">
-          <template #default="scope">
-            <el-tooltip content="修改" placement="top">
-              <el-button v-hasPermi="['system:dept:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)" />
-            </el-tooltip>
-            <el-tooltip content="新增" placement="top">
-              <el-button v-hasPermi="['system:dept:add']" link type="primary" icon="Plus" @click="handleAdd(scope.row)" />
-            </el-tooltip>
-            <el-tooltip content="删除" placement="top">
-              <el-button v-hasPermi="['system:dept:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)" />
-            </el-tooltip>
-          </template>
-        </el-table-column>
-      </el-table>
-    </el-card>
-
-    <el-dialog v-model="dialog.visible" :title="dialog.title" destroy-on-close append-to-body width="600px">
-      <el-form ref="deptFormRef" :model="form" :rules="rules" label-width="80px">
-        <el-row>
-          <el-col v-if="form.parentId !== 0" :span="24">
-            <el-form-item label="上级部门" prop="parentId">
-              <el-tree-select
-                v-model="form.parentId"
-                :data="deptOptions"
-                :props="{ value: 'deptId', label: 'deptName', children: 'children' } as any"
-                value-key="deptId"
-                placeholder="选择上级部门"
-                check-strictly
-              />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="部门名称" prop="deptName">
-              <el-input v-model="form.deptName" placeholder="请输入部门名称" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="类别编码" prop="deptCategory">
-              <el-input v-model="form.deptCategory" placeholder="请输入类别编码" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="显示排序" prop="orderNum">
-              <el-input-number v-model="form.orderNum" controls-position="right" :min="0" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="负责人" prop="leader">
-              <el-select v-model="form.leader" placeholder="请选择负责人">
-                <el-option v-for="item in deptUserList" :key="item.userId" :label="item.userName" :value="item.userId" />
-              </el-select>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="联系电话" prop="phone">
-              <el-input v-model="form.phone" placeholder="请输入联系电话" maxlength="11" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="邮箱" prop="email">
-              <el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="部门状态">
-              <el-radio-group v-model="form.status">
-                <el-radio v-for="dict in sys_normal_disable" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
-              </el-radio-group>
-            </el-form-item>
-          </el-col>
-        </el-row>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button type="primary" @click="submitForm">确 定</el-button>
-          <el-button @click="cancel">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup name="Dept" lang="ts">
-import { listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild } from '@/api/system/dept';
-import { DeptForm, DeptQuery, DeptVO } from '@/api/system/dept/types';
-import { UserVO } from '@/api/system/user/types';
-import { listUserByDeptId } from '@/api/system/user';
-
-interface DeptOptionsType {
-  deptId: number | string;
-  deptName: string;
-  children: DeptOptionsType[];
-}
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { sys_normal_disable } = toRefs<any>(proxy?.useDict('sys_normal_disable'));
-
-const deptList = ref<DeptVO[]>([]);
-const loading = ref(true);
-const showSearch = ref(true);
-const deptOptions = ref<DeptOptionsType[]>([]);
-const isExpandAll = ref(true);
-const deptUserList = ref<UserVO[]>([]);
-
-const dialog = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-const deptTableRef = ref<ElTableInstance>();
-const queryFormRef = ref<ElFormInstance>();
-const deptFormRef = ref<ElFormInstance>();
-
-const initFormData: DeptForm = {
-  deptId: undefined,
-  parentId: undefined,
-  deptName: undefined,
-  deptCategory: undefined,
-  orderNum: 0,
-  leader: undefined,
-  phone: undefined,
-  email: undefined,
-  status: '0'
-};
-const initData: PageData<DeptForm, DeptQuery> = {
-  form: { ...initFormData },
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    deptName: undefined,
-    deptCategory: undefined,
-    status: undefined
-  },
-  rules: {
-    parentId: [{ required: true, message: '上级部门不能为空', trigger: 'blur' }],
-    deptName: [{ required: true, message: '部门名称不能为空', trigger: 'blur' }],
-    orderNum: [{ required: true, message: '显示排序不能为空', trigger: 'blur' }],
-    email: [{ type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] }],
-    phone: [{ pattern: /^1[3456789][0-9]\d{8}$/, message: '请输入正确的手机号码', trigger: 'blur' }]
-  }
-};
-const data = reactive<PageData<DeptForm, DeptQuery>>(initData);
-
-const { queryParams, form, rules } = toRefs<PageData<DeptForm, DeptQuery>>(data);
-
-/** 查询菜单列表 */
-const getList = async () => {
-  loading.value = true;
-  const res = await listDept(queryParams.value);
-  const data = proxy?.handleTree<DeptVO>(res.data, 'deptId');
-  if (data) {
-    deptList.value = data;
-  }
-  loading.value = false;
-};
-
-/** 查询当前部门的所有用户 */
-async function getDeptAllUser(deptId: any) {
-  if (deptId !== null && deptId !== '' && deptId !== undefined) {
-    const res = await listUserByDeptId(deptId);
-    deptUserList.value = res.data;
-  }
-}
-
-/** 取消按钮 */
-const cancel = () => {
-  reset();
-  dialog.visible = false;
-};
-/** 表单重置 */
-const reset = () => {
-  form.value = { ...initFormData };
-  deptFormRef.value?.resetFields();
-};
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  getList();
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  handleQuery();
-};
-
-/** 展开/折叠操作 */
-const handleToggleExpandAll = () => {
-  isExpandAll.value = !isExpandAll.value;
-  toggleExpandAll(deptList.value, isExpandAll.value);
-};
-/** 展开/折叠所有 */
-const toggleExpandAll = (data: DeptVO[], status: boolean) => {
-  data.forEach((item) => {
-    deptTableRef.value?.toggleRowExpansion(item, status);
-    if (item.children && item.children.length > 0) toggleExpandAll(item.children, status);
-  });
-};
-
-/** 新增按钮操作 */
-const handleAdd = async (row?: DeptVO) => {
-  reset();
-  const res = await listDept();
-  const data = proxy?.handleTree<DeptOptionsType>(res.data, 'deptId');
-  if (data) {
-    deptOptions.value = data;
-    if (row && row.deptId) {
-      form.value.parentId = row?.deptId;
-    }
-    dialog.visible = true;
-    dialog.title = '添加部门';
-  }
-};
-
-/** 修改按钮操作 */
-const handleUpdate = async (row: DeptVO) => {
-  reset();
-  //查询当前部门所有用户
-  getDeptAllUser(row.deptId);
-  const res = await getDept(row.deptId);
-  form.value = res.data;
-  const response = await listDeptExcludeChild(row.deptId);
-  const data = proxy?.handleTree<DeptOptionsType>(response.data, 'deptId');
-  if (data) {
-    deptOptions.value = data;
-    if (data.length === 0) {
-      const noResultsOptions: DeptOptionsType = {
-        deptId: res.data.parentId,
-        deptName: res.data.parentName,
-        children: []
-      };
-      deptOptions.value.push(noResultsOptions);
-    }
-  }
-  dialog.visible = true;
-  dialog.title = '修改部门';
-};
-/** 提交按钮 */
-const submitForm = () => {
-  deptFormRef.value?.validate(async (valid: boolean) => {
-    if (valid) {
-      form.value.deptId ? await updateDept(form.value) : await addDept(form.value);
-      proxy?.$modal.msgSuccess('操作成功');
-      dialog.visible = false;
-      await getList();
-    }
-  });
-};
-/** 删除按钮操作 */
-const handleDelete = async (row: DeptVO) => {
-  await proxy?.$modal.confirm('是否确认删除名称为"' + row.deptName + '"的数据项?');
-  await delDept(row.deptId);
-  await getList();
-  proxy?.$modal.msgSuccess('删除成功');
-};
-
-onMounted(() => {
-  getList();
-});
-</script>

+ 0 - 309
src/views/system/dict/data.vue

@@ -1,309 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
-        <el-card shadow="hover">
-          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="字典名称" prop="dictType">
-              <el-select v-model="queryParams.dictType">
-                <el-option v-for="item in typeOptions" :key="item.dictId" :label="item.dictName" :value="item.dictType" />
-              </el-select>
-            </el-form-item>
-            <el-form-item label="字典标签" prop="dictLabel">
-              <el-input v-model="queryParams.dictLabel" placeholder="请输入字典标签" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
-      </div>
-    </transition>
-    <el-card shadow="hover">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:dict:add']" type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:dict:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()">修改</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:dict:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">
-              删除
-            </el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:dict:export']" type="warning" plain icon="Download" @click="handleExport">导出</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="warning" plain icon="Close" @click="handleClose">关闭</el-button>
-          </el-col>
-          <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
-        </el-row>
-      </template>
-
-      <el-table v-loading="loading" border :data="dataList" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column v-if="false" label="字典编码" align="center" prop="dictCode" />
-        <el-table-column label="字典标签" align="center" prop="dictLabel">
-          <template #default="scope">
-            <span
-              v-if="(scope.row.listClass === '' || scope.row.listClass === 'default') && (scope.row.cssClass === '' || scope.row.cssClass == null)"
-              >{{ scope.row.dictLabel }}</span
-            >
-            <el-tag
-              v-else
-              :type="scope.row.listClass === 'primary' || scope.row.listClass === 'default' ? 'primary' : scope.row.listClass"
-              :class="scope.row.cssClass"
-              >{{ scope.row.dictLabel }}</el-tag
-            >
-          </template>
-        </el-table-column>
-        <el-table-column label="字典键值" align="center" prop="dictValue" />
-        <el-table-column label="字典排序" align="center" prop="dictSort" />
-        <el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" />
-        <el-table-column label="创建时间" align="center" prop="createTime" width="180">
-          <template #default="scope">
-            <span>{{ proxy.parseTime(scope.row.createTime) }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width">
-          <template #default="scope">
-            <el-tooltip content="修改" placement="top">
-              <el-button v-hasPermi="['system:dict:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>
-            </el-tooltip>
-            <el-tooltip content="删除" placement="top">
-              <el-button v-hasPermi="['system:dict:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
-            </el-tooltip>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
-    </el-card>
-    <!-- 添加或修改参数配置对话框 -->
-    <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body>
-      <el-form ref="dataFormRef" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="字典类型">
-          <el-input v-model="form.dictType" :disabled="true" />
-        </el-form-item>
-        <el-form-item label="数据标签" prop="dictLabel">
-          <el-input v-model="form.dictLabel" placeholder="请输入数据标签" />
-        </el-form-item>
-        <el-form-item label="数据键值" prop="dictValue">
-          <el-input v-model="form.dictValue" placeholder="请输入数据键值" />
-        </el-form-item>
-        <el-form-item label="样式属性" prop="cssClass">
-          <el-input v-model="form.cssClass" placeholder="请输入样式属性" />
-        </el-form-item>
-        <el-form-item label="显示排序" prop="dictSort">
-          <el-input-number v-model="form.dictSort" controls-position="right" :min="0" />
-        </el-form-item>
-        <el-form-item label="回显样式" prop="listClass">
-          <el-select v-model="form.listClass">
-            <el-option
-              v-for="item in listClassOptions"
-              :key="item.value"
-              :label="item.label + '(' + item.value + ')'"
-              :value="item.value"
-            ></el-option>
-          </el-select>
-        </el-form-item>
-        <el-form-item label="备注" prop="remark">
-          <el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button type="primary" @click="submitForm">确 定</el-button>
-          <el-button @click="cancel">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup name="Data" lang="ts">
-import { useDictStore } from '@/store/modules/dict';
-import { optionselect as getDictOptionselect, getType } from '@/api/system/dict/type';
-import { listData, getData, delData, addData, updateData } from '@/api/system/dict/data';
-import { DictTypeVO } from '@/api/system/dict/type/types';
-import { DictDataForm, DictDataQuery, DictDataVO } from '@/api/system/dict/data/types';
-import { RouteLocationNormalized } from 'vue-router';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const route = useRoute();
-
-const dataList = ref<DictDataVO[]>([]);
-const loading = ref(true);
-const showSearch = ref(true);
-const ids = ref<Array<string | number>>([]);
-const single = ref(true);
-const multiple = ref(true);
-const total = ref(0);
-const defaultDictType = ref('');
-const typeOptions = ref<DictTypeVO[]>([]);
-
-const dataFormRef = ref<ElFormInstance>();
-const queryFormRef = ref<ElFormInstance>();
-
-const dialog = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-// 数据标签回显样式
-const listClassOptions = ref<Array<{ value: string; label: string }>>([
-  { value: 'default', label: '默认' },
-  { value: 'primary', label: '主要' },
-  { value: 'success', label: '成功' },
-  { value: 'info', label: '信息' },
-  { value: 'warning', label: '警告' },
-  { value: 'danger', label: '危险' }
-]);
-
-const initFormData: DictDataForm = {
-  dictCode: undefined,
-  dictLabel: '',
-  dictValue: '',
-  cssClass: '',
-  listClass: 'primary',
-  dictSort: 0,
-  remark: ''
-};
-const data = reactive<PageData<DictDataForm, DictDataQuery>>({
-  form: { ...initFormData },
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    dictName: '',
-    dictType: '',
-    dictLabel: ''
-  },
-  rules: {
-    dictLabel: [{ required: true, message: '数据标签不能为空', trigger: 'blur' }],
-    dictValue: [{ required: true, message: '数据键值不能为空', trigger: 'blur' }],
-    dictSort: [{ required: true, message: '数据顺序不能为空', trigger: 'blur' }]
-  }
-});
-
-const { queryParams, form, rules } = toRefs(data);
-
-/** 查询字典类型详细 */
-const getTypes = async (dictId: string | number) => {
-  const { data } = await getType(dictId);
-  queryParams.value.dictType = data.dictType;
-  defaultDictType.value = data.dictType;
-  getList();
-};
-
-/** 查询字典类型列表 */
-const getTypeList = async () => {
-  const res = await getDictOptionselect();
-  typeOptions.value = res.data;
-};
-/** 查询字典数据列表 */
-const getList = async () => {
-  loading.value = true;
-  const res = await listData(queryParams.value);
-  dataList.value = res.rows;
-  total.value = res.total;
-  loading.value = false;
-};
-/** 取消按钮 */
-const cancel = () => {
-  dialog.visible = false;
-  reset();
-};
-/** 表单重置 */
-const reset = () => {
-  form.value = { ...initFormData };
-  dataFormRef.value?.resetFields();
-};
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.value.pageNum = 1;
-  getList();
-};
-/** 返回按钮操作 */
-const handleClose = () => {
-  const obj: RouteLocationNormalized = {
-    fullPath: '',
-    hash: '',
-    matched: [],
-    meta: undefined,
-    name: undefined,
-    params: undefined,
-    query: undefined,
-    redirectedFrom: undefined,
-    path: '/system/dict'
-  };
-  proxy?.$tab.closeOpenPage(obj);
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  queryParams.value.dictType = defaultDictType.value;
-  handleQuery();
-};
-/** 新增按钮操作 */
-const handleAdd = () => {
-  reset();
-  form.value.dictType = queryParams.value.dictType;
-  dialog.visible = true;
-  dialog.title = '添加字典数据';
-};
-/** 多选框选中数据 */
-const handleSelectionChange = (selection: DictDataVO[]) => {
-  ids.value = selection.map((item) => item.dictCode);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
-};
-/** 修改按钮操作 */
-const handleUpdate = async (row?: DictDataVO) => {
-  reset();
-  const dictCode = row?.dictCode || ids.value[0];
-  const res = await getData(dictCode);
-  Object.assign(form.value, res.data);
-  dialog.visible = true;
-  dialog.title = '修改字典数据';
-};
-/** 提交按钮 */
-const submitForm = () => {
-  dataFormRef.value?.validate(async (valid: boolean) => {
-    if (valid) {
-      form.value.dictCode ? await updateData(form.value) : await addData(form.value);
-      useDictStore().removeDict(queryParams.value.dictType);
-      proxy?.$modal.msgSuccess('操作成功');
-      dialog.visible = false;
-      await getList();
-    }
-  });
-};
-/** 删除按钮操作 */
-const handleDelete = async (row?: DictDataVO) => {
-  const dictCodes = row?.dictCode || ids.value;
-  await proxy?.$modal.confirm('是否确认删除字典编码为"' + dictCodes + '"的数据项?');
-  await delData(dictCodes);
-  await getList();
-  proxy?.$modal.msgSuccess('删除成功');
-  useDictStore().removeDict(queryParams.value.dictType);
-};
-/** 导出按钮操作 */
-const handleExport = () => {
-  proxy?.download(
-    'system/dict/data/export',
-    {
-      ...queryParams.value
-    },
-    `dict_data_${new Date().getTime()}.xlsx`
-  );
-};
-
-onMounted(() => {
-  getTypes(route.params && (route.params.dictId as string));
-  getTypeList();
-});
-</script>

+ 0 - 246
src/views/system/dict/index.vue

@@ -1,246 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
-        <el-card shadow="hover">
-          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="字典名称" prop="dictName">
-              <el-input v-model="queryParams.dictName" placeholder="请输入字典名称" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="字典类型" prop="dictType">
-              <el-input v-model="queryParams.dictType" placeholder="请输入字典类型" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="创建时间" style="width: 308px">
-              <el-date-picker
-                v-model="dateRange"
-                value-format="YYYY-MM-DD HH:mm:ss"
-                type="daterange"
-                range-separator="-"
-                start-placeholder="开始日期"
-                end-placeholder="结束日期"
-                :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
-              ></el-date-picker>
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
-      </div>
-    </transition>
-    <el-card shadow="hover">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:dict:add']" type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:dict:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()">修改</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:dict:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">
-              删除
-            </el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:dict:export']" type="warning" plain icon="Download" @click="handleExport">导出</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:dict:remove']" type="danger" plain icon="Refresh" @click="handleRefreshCache">刷新缓存</el-button>
-          </el-col>
-          <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
-        </el-row>
-      </template>
-
-      <el-table v-loading="loading" border :data="typeList" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column v-if="false" label="字典编号" align="center" prop="dictId" />
-        <el-table-column label="字典名称" align="center" prop="dictName" :show-overflow-tooltip="true" />
-        <el-table-column label="字典类型" align="center" :show-overflow-tooltip="true">
-          <template #default="scope">
-            <router-link :to="'/system/dict-data/index/' + scope.row.dictId" class="link-type">
-              <span>{{ scope.row.dictType }}</span>
-            </router-link>
-          </template>
-        </el-table-column>
-        <el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" />
-        <el-table-column label="创建时间" align="center" prop="createTime" width="180">
-          <template #default="scope">
-            <span>{{ proxy.parseTime(scope.row.createTime) }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width">
-          <template #default="scope">
-            <el-tooltip content="修改" placement="top">
-              <el-button v-hasPermi="['system:dict:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>
-            </el-tooltip>
-            <el-tooltip content="删除" placement="top">
-              <el-button v-hasPermi="['system:dict:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
-            </el-tooltip>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
-    </el-card>
-    <!-- 添加或修改参数配置对话框 -->
-    <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body>
-      <el-form ref="dictFormRef" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="字典名称" prop="dictName">
-          <el-input v-model="form.dictName" placeholder="请输入字典名称" />
-        </el-form-item>
-        <el-form-item label="字典类型" prop="dictType">
-          <el-input v-model="form.dictType" placeholder="请输入字典类型" />
-        </el-form-item>
-        <el-form-item label="备注" prop="remark">
-          <el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button type="primary" @click="submitForm">确 定</el-button>
-          <el-button @click="cancel">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup name="Dict" lang="ts">
-import { useDictStore } from '@/store/modules/dict';
-import { listType, getType, delType, addType, updateType, refreshCache } from '@/api/system/dict/type';
-import { DictTypeForm, DictTypeQuery, DictTypeVO } from '@/api/system/dict/type/types';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const typeList = ref<DictTypeVO[]>([]);
-const loading = ref(true);
-const showSearch = ref(true);
-const ids = ref<Array<number | string>>([]);
-const single = ref(true);
-const multiple = ref(true);
-const total = ref(0);
-const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
-
-const dictFormRef = ref<ElFormInstance>();
-const queryFormRef = ref<ElFormInstance>();
-
-const dialog = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-const initFormData: DictTypeForm = {
-  dictId: undefined,
-  dictName: '',
-  dictType: '',
-  remark: ''
-};
-const data = reactive<PageData<DictTypeForm, DictTypeQuery>>({
-  form: { ...initFormData },
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    dictName: '',
-    dictType: ''
-  },
-  rules: {
-    dictName: [{ required: true, message: '字典名称不能为空', trigger: 'blur' }],
-    dictType: [{ required: true, message: '字典类型不能为空', trigger: 'blur' }]
-  }
-});
-
-const { queryParams, form, rules } = toRefs(data);
-
-/** 查询字典类型列表 */
-const getList = () => {
-  loading.value = true;
-  listType(proxy?.addDateRange(queryParams.value, dateRange.value)).then((res) => {
-    typeList.value = res.rows;
-    total.value = res.total;
-    loading.value = false;
-  });
-};
-/** 取消按钮 */
-const cancel = () => {
-  reset();
-  dialog.visible = false;
-};
-/** 表单重置 */
-const reset = () => {
-  form.value = { ...initFormData };
-  dictFormRef.value?.resetFields();
-};
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.value.pageNum = 1;
-  getList();
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  dateRange.value = ['', ''];
-  queryFormRef.value?.resetFields();
-  handleQuery();
-};
-/** 新增按钮操作 */
-const handleAdd = () => {
-  reset();
-  dialog.visible = true;
-  dialog.title = '添加字典类型';
-};
-/** 多选框选中数据 */
-const handleSelectionChange = (selection: DictTypeVO[]) => {
-  ids.value = selection.map((item) => item.dictId);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
-};
-/** 修改按钮操作 */
-const handleUpdate = async (row?: DictTypeVO) => {
-  reset();
-  const dictId = row?.dictId || ids.value[0];
-  const res = await getType(dictId);
-  Object.assign(form.value, res.data);
-  dialog.visible = true;
-  dialog.title = '修改字典类型';
-};
-/** 提交按钮 */
-const submitForm = () => {
-  dictFormRef.value?.validate(async (valid: boolean) => {
-    if (valid) {
-      form.value.dictId ? await updateType(form.value) : await addType(form.value);
-      proxy?.$modal.msgSuccess('操作成功');
-      dialog.visible = false;
-      getList();
-    }
-  });
-};
-/** 删除按钮操作 */
-const handleDelete = async (row?: DictTypeVO) => {
-  const dictIds = row?.dictId || ids.value;
-  await proxy?.$modal.confirm('是否确认删除字典编号为"' + dictIds + '"的数据项?');
-  await delType(dictIds);
-  getList();
-  proxy?.$modal.msgSuccess('删除成功');
-};
-/** 导出按钮操作 */
-const handleExport = () => {
-  proxy?.download(
-    'system/dict/type/export',
-    {
-      ...queryParams.value
-    },
-    `dict_${new Date().getTime()}.xlsx`
-  );
-};
-/** 刷新缓存按钮操作 */
-const handleRefreshCache = async () => {
-  await refreshCache();
-  proxy?.$modal.msgSuccess('刷新成功');
-  useDictStore().cleanDict();
-};
-
-onMounted(() => {
-  getList();
-});
-</script>

+ 0 - 540
src/views/system/menu/index.vue

@@ -1,540 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
-        <el-card shadow="hover">
-          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="菜单名称" prop="menuName">
-              <el-input v-model="queryParams.menuName" placeholder="请输入菜单名称" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="状态" prop="status">
-              <el-select v-model="queryParams.status" placeholder="菜单状态" clearable>
-                <el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
-              </el-select>
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
-      </div>
-    </transition>
-
-    <el-card shadow="hover">
-      <template #header>
-        <el-row :gutter="10">
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:menu:add']" type="primary" plain icon="Plus" @click="handleAdd()">新增</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:menu:remove']" type="danger" plain icon="Delete" @click="handleCascadeDelete" :loading="deleteLoading">级联删除</el-button>
-          </el-col>
-          <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
-        </el-row>
-      </template>
-
-      <el-table
-        ref="menuTableRef"
-        v-loading="loading"
-        :data="menuList"
-        row-key="menuId"
-        border
-        :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
-        :default-expand-all="false"
-        lazy
-        :load="getChildrenList"
-        :expand-change="expandMenuHandle"
-      >
-        <el-table-column prop="menuName" label="菜单名称" :show-overflow-tooltip="true" width="160"></el-table-column>
-        <el-table-column prop="icon" label="图标" align="center" width="100">
-          <template #default="scope">
-            <svg-icon :icon-class="scope.row.icon" />
-          </template>
-        </el-table-column>
-        <el-table-column prop="orderNum" label="排序" width="60"></el-table-column>
-        <el-table-column prop="perms" label="权限标识" :show-overflow-tooltip="true"></el-table-column>
-        <el-table-column prop="component" label="组件路径" :show-overflow-tooltip="true"></el-table-column>
-        <el-table-column prop="status" label="状态" width="80">
-          <template #default="scope">
-            <dict-tag :options="sys_normal_disable" :value="scope.row.status" />
-          </template>
-        </el-table-column>
-        <el-table-column label="创建时间" align="center" prop="createTime">
-          <template #default="scope">
-            <span>{{ scope.row.createTime }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column fixed="right" label="操作" width="180">
-          <template #default="scope">
-            <el-tooltip content="修改" placement="top">
-              <el-button v-hasPermi="['system:menu:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)" />
-            </el-tooltip>
-            <el-tooltip content="新增" placement="top">
-              <el-button v-hasPermi="['system:menu:add']" link type="primary" icon="Plus" @click="handleAdd(scope.row)" />
-            </el-tooltip>
-            <el-tooltip content="删除" placement="top">
-              <el-button v-hasPermi="['system:menu:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)" />
-            </el-tooltip>
-          </template>
-        </el-table-column>
-      </el-table>
-    </el-card>
-
-    <el-dialog v-model="dialog.visible" :title="dialog.title" destroy-on-close append-to-bod width="750px">
-      <el-form ref="menuFormRef" :model="form" :rules="rules" label-width="100px">
-        <el-row>
-          <el-col :span="24">
-            <el-form-item label="上级菜单">
-              <el-tree-select
-                v-model="form.parentId"
-                :data="menuOptions"
-                :props="{ value: 'menuId', label: 'menuName', children: 'children' } as any"
-                value-key="menuId"
-                placeholder="选择上级菜单"
-                check-strictly
-              />
-            </el-form-item>
-          </el-col>
-          <el-col :span="24">
-            <el-form-item label="菜单类型" prop="menuType">
-              <el-radio-group v-model="form.menuType">
-                <el-radio value="M">目录</el-radio>
-                <el-radio value="C">菜单</el-radio>
-                <el-radio value="F">按钮</el-radio>
-              </el-radio-group>
-            </el-form-item>
-          </el-col>
-          <el-col v-if="form.menuType !== 'F'" :span="24">
-            <el-form-item label="菜单图标" prop="icon">
-              <!-- 图标选择器 -->
-              <icon-select v-model="form.icon" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="菜单名称" prop="menuName">
-              <el-input v-model="form.menuName" placeholder="请输入菜单名称" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="显示排序" prop="orderNum">
-              <el-input-number v-model="form.orderNum" controls-position="right" :min="0" />
-            </el-form-item>
-          </el-col>
-          <el-col v-if="form.menuType !== 'F'" :span="12">
-            <el-form-item>
-              <template #label>
-                <span>
-                  <el-tooltip content="选择是外链则路由地址需要以`http(s)://`开头" placement="top">
-                    <el-icon>
-                      <question-filled />
-                    </el-icon> </el-tooltip
-                  >是否外链
-                </span>
-              </template>
-              <el-radio-group v-model="form.isFrame">
-                <el-radio value="0">是</el-radio>
-                <el-radio value="1">否</el-radio>
-              </el-radio-group>
-            </el-form-item>
-          </el-col>
-          <el-col v-if="form.menuType !== 'F'" :span="12">
-            <el-form-item prop="path">
-              <template #label>
-                <span>
-                  <el-tooltip content="访问的路由地址,如:`user`,如外网地址需内链访问则以`http(s)://`开头" placement="top">
-                    <el-icon>
-                      <question-filled />
-                    </el-icon>
-                  </el-tooltip>
-                  路由地址
-                </span>
-              </template>
-              <el-input v-model="form.path" placeholder="请输入路由地址" />
-            </el-form-item>
-          </el-col>
-          <el-col v-if="form.menuType === 'C'" :span="12">
-            <el-form-item prop="component">
-              <template #label>
-                <span>
-                  <el-tooltip content="访问的组件路径,如:`system/user/index`,默认在`views`目录下" placement="top">
-                    <el-icon>
-                      <question-filled />
-                    </el-icon>
-                  </el-tooltip>
-                  组件路径
-                </span>
-              </template>
-              <el-input v-model="form.component" placeholder="请输入组件路径" />
-            </el-form-item>
-          </el-col>
-          <el-col v-if="form.menuType !== 'M'" :span="12">
-            <el-form-item>
-              <el-input v-model="form.perms" placeholder="请输入权限标识" maxlength="100" />
-              <template #label>
-                <span>
-                  <el-tooltip content="控制器中定义的权限字符,如:@SaCheckPermission('system:user:list')" placement="top">
-                    <el-icon>
-                      <question-filled />
-                    </el-icon>
-                  </el-tooltip>
-                  权限字符
-                </span>
-              </template>
-            </el-form-item>
-          </el-col>
-          <el-col v-if="form.menuType === 'C'" :span="12">
-            <el-form-item>
-              <el-input v-model="form.queryParam" placeholder="请输入路由参数" maxlength="255" />
-              <template #label>
-                <span>
-                  <el-tooltip content='访问路由的默认传递参数,如:`{"id": 1, "name": "ry"}`' placement="top">
-                    <el-icon>
-                      <question-filled />
-                    </el-icon>
-                  </el-tooltip>
-                  路由参数
-                </span>
-              </template>
-            </el-form-item>
-          </el-col>
-          <el-col v-if="form.menuType === 'C'" :span="12">
-            <el-form-item>
-              <template #label>
-                <span>
-                  <el-tooltip content="选择是则会被`keep-alive`缓存,需要匹配组件的`name`和地址保持一致" placement="top">
-                    <el-icon>
-                      <question-filled />
-                    </el-icon>
-                  </el-tooltip>
-                  是否缓存
-                </span>
-              </template>
-              <el-radio-group v-model="form.isCache">
-                <el-radio value="0">缓存</el-radio>
-                <el-radio value="1">不缓存</el-radio>
-              </el-radio-group>
-            </el-form-item>
-          </el-col>
-          <el-col v-if="form.menuType !== 'F'" :span="12">
-            <el-form-item>
-              <template #label>
-                <span>
-                  <el-tooltip content="选择隐藏则路由将不会出现在侧边栏,但仍然可以访问" placement="top">
-                    <el-icon>
-                      <question-filled />
-                    </el-icon>
-                  </el-tooltip>
-                  显示状态
-                </span>
-              </template>
-              <el-radio-group v-model="form.visible">
-                <el-radio v-for="dict in sys_show_hide" :key="dict.value" :value="dict.value">{{ dict.label }} </el-radio>
-              </el-radio-group>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item>
-              <template #label>
-                <span>
-                  <el-tooltip content="选择停用则路由将不会出现在侧边栏,也不能被访问" placement="top">
-                    <el-icon>
-                      <question-filled />
-                    </el-icon>
-                  </el-tooltip>
-                  菜单状态
-                </span>
-              </template>
-              <el-radio-group v-model="form.status">
-                <el-radio v-for="dict in sys_normal_disable" :key="dict.value" :value="dict.value">
-                  {{ dict.label }}
-                </el-radio>
-              </el-radio-group>
-            </el-form-item>
-          </el-col>
-          <el-col v-if="form.visible !== '0'" :span="12">
-            <el-form-item label="激活路径" prop="form.remark">
-              <template #label>
-                <span>
-                  <el-tooltip content="隐藏菜单填写默认激活路由,比如激活父菜单的路由 /system/user" placement="top">
-                    <el-icon>
-                      <question-filled />
-                    </el-icon>
-                  </el-tooltip>
-                  激活路由
-                </span>
-              </template>
-              <el-input v-model="form.remark" placeholder="请输入激活路径" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button type="primary" @click="submitForm">确 定</el-button>
-          <el-button @click="cancel">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
-
-    <el-dialog v-model="deleteDialog.visible" :title="deleteDialog.title" destroy-on-close append-to-bod width="750px">
-      <el-tree
-        ref="menuTreeRef"
-        class="tree-border"
-        :data="menuOptions"
-        show-checkbox
-        node-key="menuId"
-        :check-strictly="false"
-        empty-text="加载中,请稍候"
-        :default-expanded-keys="[0]"
-        :props="{ value: 'menuId', label: 'menuName', children: 'children' } as any"
-      />
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button type="primary" @click="submitDeleteForm" :loading="deleteLoading">确 定</el-button>
-          <el-button @click="cancelCascade">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup name="Menu" lang="ts">
-import { addMenu, cascadeDelMenu, delMenu, getMenu, listMenu, updateMenu } from '@/api/system/menu';
-import { MenuForm, MenuQuery, MenuVO } from '@/api/system/menu/types';
-import { MenuTypeEnum } from '@/enums/MenuTypeEnum';
-
-interface MenuOptionsType {
-  menuId: number;
-  menuName: string;
-  children: MenuOptionsType[] | undefined;
-}
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { sys_show_hide, sys_normal_disable } = toRefs<any>(proxy?.useDict('sys_show_hide', 'sys_normal_disable'));
-
-const menuList = ref<MenuVO[]>([]);
-const menuChildrenListMap = ref({});
-const menuExpandMap = ref({});
-const loading = ref(true);
-const showSearch = ref(true);
-const menuOptions = ref<MenuOptionsType[]>([]);
-
-const dialog = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-const queryFormRef = ref<ElFormInstance>();
-const menuFormRef = ref<ElFormInstance>();
-const initFormData = {
-  path: '',
-  menuId: undefined,
-  parentId: 0,
-  menuName: '',
-  icon: '',
-  menuType: MenuTypeEnum.M,
-  orderNum: 1,
-  isFrame: '1',
-  isCache: '0',
-  visible: '0',
-  status: '0'
-};
-const data = reactive<PageData<MenuForm, MenuQuery>>({
-  form: { ...initFormData },
-  queryParams: {
-    menuName: undefined,
-    status: undefined
-  },
-  rules: {
-    menuName: [{ required: true, message: '菜单名称不能为空', trigger: 'blur' }],
-    orderNum: [{ required: true, message: '菜单顺序不能为空', trigger: 'blur' }],
-    path: [{ required: true, message: '路由地址不能为空', trigger: 'blur' }]
-  }
-});
-
-const menuTableRef = ref<ElTableInstance>();
-
-const { queryParams, form, rules } = toRefs<PageData<MenuForm, MenuQuery>>(data);
-
-/** 获取子菜单列表 */
-const getChildrenList = async (row: any, treeNode: unknown, resolve: (data: any[]) => void) => {
-  menuExpandMap.value[row.menuId] = { row, treeNode, resolve };
-  const children = menuChildrenListMap.value[row.menuId] || [];
-  // 菜单的子菜单清空后关闭展开
-  if (children.length == 0) {
-    // fix: 处理当菜单只有一个子菜单并被删除,需要将父菜单的展开状态关闭
-    menuTableRef.value?.updateKeyChildren(row.menuId, children);
-  }
-  resolve(children);
-};
-
-/** 收起菜单时从menuExpandMap中删除对应菜单id数据 */
-const expandMenuHandle = async (row: any, expanded: boolean) => {
-  if (!expanded) {
-    menuExpandMap.value[row.menuId] = undefined;
-  }
-};
-
-/** 刷新展开的菜单数据 */
-const refreshLoadTree = (parentId: string | number) => {
-  if (menuExpandMap.value[parentId]) {
-    const { row, treeNode, resolve } = menuExpandMap.value[parentId];
-    if (row) {
-      getChildrenList(row, treeNode, resolve);
-      if (row.parentId) {
-        const grandpaMenu = menuExpandMap.value[row.parentId];
-        getChildrenList(grandpaMenu.row, grandpaMenu.treeNode, grandpaMenu.resolve);
-      }
-    }
-  }
-};
-
-/** 重新加载所有已展开的菜单的数据 */
-const refreshAllExpandMenuData = () => {
-  for (const menuId in menuExpandMap.value) {
-    refreshLoadTree(menuId);
-  }
-};
-
-/** 查询菜单列表 */
-const getList = async () => {
-  loading.value = true;
-  const res = await listMenu(queryParams.value);
-
-  const tempMap = {};
-  // 存储 父菜单:子菜单列表
-  for (const menu of res.data) {
-    const parentId = menu.parentId;
-    if (!tempMap[parentId]) {
-      tempMap[parentId] = [];
-    }
-    tempMap[parentId].push(menu);
-  }
-  // 创建一个当前所有 menuId 的 Set,用于查找父菜单是否存在于当前数据中
-  const menuIdSet = new Set();
-  // 设置有没有子菜单
-  for (const menu of res.data) {
-    menu['hasChildren'] = tempMap[menu.menuId]?.length > 0;
-    menuIdSet.add(menu.menuId);
-  }
-  menuChildrenListMap.value = tempMap;
-  // 找出所有父ID不在当前菜单ID集合中的菜单项,作为新的顶层菜单
-  menuList.value = res.data.filter((menu) => !menuIdSet.has(menu.parentId));
-  // 根据新数据重新加载子菜单数据
-  refreshAllExpandMenuData();
-  loading.value = false;
-};
-/** 查询菜单下拉树结构 */
-const getTreeselect = async () => {
-  menuOptions.value = [];
-  const response = await listMenu();
-  const menu: MenuOptionsType = { menuId: 0, menuName: '主类目', children: [] };
-  menu.children = proxy?.handleTree<MenuOptionsType>(response.data, 'menuId');
-  menuOptions.value.push(menu);
-};
-/** 取消按钮 */
-const cancel = () => {
-  reset();
-  dialog.visible = false;
-};
-/** 表单重置 */
-const reset = () => {
-  form.value = { ...initFormData };
-  menuFormRef.value?.resetFields();
-};
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  getList();
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  handleQuery();
-};
-/** 新增按钮操作 */
-const handleAdd = (row?: MenuVO) => {
-  reset();
-  getTreeselect();
-  row && row.menuId ? (form.value.parentId = row.menuId) : (form.value.parentId = 0);
-  dialog.visible = true;
-  dialog.title = '添加菜单';
-};
-/** 修改按钮操作 */
-const handleUpdate = async (row: MenuVO) => {
-  reset();
-  await getTreeselect();
-  if (row.menuId) {
-    const { data } = await getMenu(row.menuId);
-    form.value = data;
-  }
-  dialog.visible = true;
-  dialog.title = '修改菜单';
-};
-/** 提交按钮 */
-const submitForm = () => {
-  menuFormRef.value?.validate(async (valid: boolean) => {
-    if (valid) {
-      form.value.menuId ? await updateMenu(form.value) : await addMenu(form.value);
-      proxy?.$modal.msgSuccess('操作成功');
-      dialog.visible = false;
-      await getList();
-    }
-  });
-};
-/** 删除按钮操作 */
-const handleDelete = async (row: MenuVO) => {
-  await proxy?.$modal.confirm('是否确认删除名称为"' + row.menuName + '"的数据项?');
-  await delMenu(row.menuId);
-  await getList();
-  proxy?.$modal.msgSuccess('删除成功');
-};
-
-const deleteLoading = ref<boolean>(false);
-const menuTreeRef = ref<ElTreeInstance>();
-
-const deleteDialog = reactive<DialogOption>({
-  visible: false,
-  title: '级联删除菜单'
-});
-
-/** 级联删除按钮操作 */
-const handleCascadeDelete = () => {
-  menuTreeRef.value?.setCheckedKeys([]);
-  getTreeselect();
-  deleteDialog.visible = true;
-};
-
-/** 取消按钮 */
-const cancelCascade = () => {
-  menuTreeRef.value?.setCheckedKeys([]);
-  deleteDialog.visible = false;
-};
-
-/** 删除提交按钮 */
-const submitDeleteForm = async () => {
-  const menuIds = menuTreeRef.value?.getCheckedKeys();
-  if (menuIds.length < 0) {
-    proxy?.$modal.msgWarning('请选择要删除的菜单');
-    return;
-  }
-
-  deleteLoading.value = true;
-  await cascadeDelMenu(menuIds).finally(() => (deleteLoading.value = false));
-  await getList();
-  proxy?.$modal.msgSuccess('删除成功');
-  deleteDialog.visible = false;
-};
-
-onMounted(() => {
-  getList();
-});
-</script>
-
-<style scoped lang="scss">
-.tree-border {
-  height: 300px;
-  overflow: auto;
-}
-</style>

+ 0 - 243
src/views/system/notice/index.vue

@@ -1,243 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
-        <el-card shadow="hover">
-          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="公告标题" prop="noticeTitle">
-              <el-input v-model="queryParams.noticeTitle" placeholder="请输入公告标题" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="操作人员" prop="createByName">
-              <el-input v-model="queryParams.createByName" placeholder="请输入操作人员" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="类型" prop="noticeType">
-              <el-select v-model="queryParams.noticeType" placeholder="公告类型" clearable>
-                <el-option v-for="dict in sys_notice_type" :key="dict.value" :label="dict.label" :value="dict.value" />
-              </el-select>
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
-      </div>
-    </transition>
-
-    <el-card shadow="hover">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:notice:add']" type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:notice:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()"
-              >修改</el-button
-            >
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:notice:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">
-              删除
-            </el-button>
-          </el-col>
-          <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
-        </el-row>
-      </template>
-
-      <el-table v-loading="loading" border :data="noticeList" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column v-if="false" label="序号" align="center" prop="noticeId" width="100" />
-        <el-table-column label="公告标题" align="center" prop="noticeTitle" :show-overflow-tooltip="true" />
-        <el-table-column label="公告类型" align="center" prop="noticeType" width="100">
-          <template #default="scope">
-            <dict-tag :options="sys_notice_type" :value="scope.row.noticeType" />
-          </template>
-        </el-table-column>
-        <el-table-column label="状态" align="center" prop="status" width="100">
-          <template #default="scope">
-            <dict-tag :options="sys_notice_status" :value="scope.row.status" />
-          </template>
-        </el-table-column>
-        <el-table-column label="创建者" align="center" prop="createByName" width="100" />
-        <el-table-column label="创建时间" align="center" prop="createTime" width="100">
-          <template #default="scope">
-            <span>{{ proxy.parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
-          <template #default="scope">
-            <el-tooltip content="修改" placement="top">
-              <el-button v-hasPermi="['system:notice:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>
-            </el-tooltip>
-            <el-tooltip content="删除" placement="top">
-              <el-button v-hasPermi="['system:notice:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
-            </el-tooltip>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
-    </el-card>
-    <!-- 添加或修改公告对话框 -->
-    <el-dialog v-model="dialog.visible" :title="dialog.title" width="780px" append-to-body>
-      <el-form ref="noticeFormRef" :model="form" :rules="rules" label-width="80px">
-        <el-row>
-          <el-col :span="12">
-            <el-form-item label="公告标题" prop="noticeTitle">
-              <el-input v-model="form.noticeTitle" placeholder="请输入公告标题" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="公告类型" prop="noticeType">
-              <el-select v-model="form.noticeType" placeholder="请选择">
-                <el-option v-for="dict in sys_notice_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
-              </el-select>
-            </el-form-item>
-          </el-col>
-          <el-col :span="24">
-            <el-form-item label="状态">
-              <el-radio-group v-model="form.status">
-                <el-radio v-for="dict in sys_notice_status" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
-              </el-radio-group>
-            </el-form-item>
-          </el-col>
-          <el-col :span="24">
-            <el-form-item label="内容">
-              <editor v-model="form.noticeContent" :min-height="192" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button type="primary" @click="submitForm">确 定</el-button>
-          <el-button @click="cancel">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup name="Notice" lang="ts">
-import { listNotice, getNotice, delNotice, addNotice, updateNotice } from '@/api/system/notice';
-import { NoticeForm, NoticeQuery, NoticeVO } from '@/api/system/notice/types';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { sys_notice_status, sys_notice_type } = toRefs<any>(proxy?.useDict('sys_notice_status', 'sys_notice_type'));
-
-const noticeList = ref<NoticeVO[]>([]);
-const loading = ref(true);
-const showSearch = ref(true);
-const ids = ref<Array<string | number>>([]);
-const single = ref(true);
-const multiple = ref(true);
-const total = ref(0);
-
-const queryFormRef = ref<ElFormInstance>();
-const noticeFormRef = ref<ElFormInstance>();
-
-const dialog = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-const initFormData: NoticeForm = {
-  noticeId: undefined,
-  noticeTitle: '',
-  noticeType: '',
-  noticeContent: '',
-  status: '0',
-  remark: '',
-  createByName: ''
-};
-const data = reactive<PageData<NoticeForm, NoticeQuery>>({
-  form: { ...initFormData },
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    noticeTitle: '',
-    createByName: '',
-    status: '',
-    noticeType: ''
-  },
-  rules: {
-    noticeTitle: [{ required: true, message: '公告标题不能为空', trigger: 'blur' }],
-    noticeType: [{ required: true, message: '公告类型不能为空', trigger: 'change' }]
-  }
-});
-
-const { queryParams, form, rules } = toRefs(data);
-
-/** 查询公告列表 */
-const getList = async () => {
-  loading.value = true;
-  const res = await listNotice(queryParams.value);
-  noticeList.value = res.rows;
-  total.value = res.total;
-  loading.value = false;
-};
-/** 取消按钮 */
-const cancel = () => {
-  reset();
-  dialog.visible = false;
-};
-/** 表单重置 */
-const reset = () => {
-  form.value = { ...initFormData };
-  noticeFormRef.value?.resetFields();
-};
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.value.pageNum = 1;
-  getList();
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  handleQuery();
-};
-/** 多选框选中数据 */
-const handleSelectionChange = (selection: NoticeVO[]) => {
-  ids.value = selection.map((item) => item.noticeId);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
-};
-/** 新增按钮操作 */
-const handleAdd = () => {
-  reset();
-  dialog.visible = true;
-  dialog.title = '添加公告';
-};
-/**修改按钮操作 */
-const handleUpdate = async (row?: NoticeVO) => {
-  reset();
-  const noticeId = row?.noticeId || ids.value[0];
-  const { data } = await getNotice(noticeId);
-  Object.assign(form.value, data);
-  dialog.visible = true;
-  dialog.title = '修改公告';
-};
-/** 提交按钮 */
-const submitForm = () => {
-  noticeFormRef.value?.validate(async (valid: boolean) => {
-    if (valid) {
-      form.value.noticeId ? await updateNotice(form.value) : await addNotice(form.value);
-      proxy?.$modal.msgSuccess('操作成功');
-      dialog.visible = false;
-      await getList();
-    }
-  });
-};
-/** 删除按钮操作 */
-const handleDelete = async (row?: NoticeVO) => {
-  const noticeIds = row?.noticeId || ids.value;
-  await proxy?.$modal.confirm('是否确认删除公告编号为"' + noticeIds + '"的数据项?');
-  await delNotice(noticeIds);
-  await getList();
-  proxy?.$modal.msgSuccess('删除成功');
-};
-
-onMounted(() => {
-  getList();
-});
-</script>

+ 0 - 344
src/views/system/oss/config.vue

@@ -1,344 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
-        <el-card shadow="hover">
-          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="配置key" prop="configKey">
-              <el-input v-model="queryParams.configKey" placeholder="配置key" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="桶名称" prop="bucketName">
-              <el-input v-model="queryParams.bucketName" placeholder="请输入桶名称" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="是否默认" prop="status">
-              <el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
-                <el-option key="0" label="是" value="0" />
-                <el-option key="1" label="否" value="1" />
-              </el-select>
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" icon="search" @click="handleQuery">搜索</el-button>
-              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
-      </div>
-    </transition>
-
-    <el-card shadow="hover">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:ossConfig:add']" type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:ossConfig:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()"
-              >修改</el-button
-            >
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:ossConfig:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">
-              删除
-            </el-button>
-          </el-col>
-          <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
-        </el-row>
-      </template>
-
-      <el-table v-loading="loading" border :data="ossConfigList" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column v-if="columns[0].visible" label="主建" align="center" prop="ossConfigId" />
-        <el-table-column v-if="columns[1].visible" label="配置key" align="center" prop="configKey" />
-        <el-table-column v-if="columns[2].visible" label="访问站点" align="center" prop="endpoint" width="200" />
-        <el-table-column v-if="columns[3].visible" label="自定义域名" align="center" prop="domain" width="200" />
-        <el-table-column v-if="columns[4].visible" label="桶名称" align="center" prop="bucketName" />
-        <el-table-column v-if="columns[5].visible" label="前缀" align="center" prop="prefix" />
-        <el-table-column v-if="columns[6].visible" label="域" align="center" prop="region" />
-        <el-table-column v-if="columns[7].visible" label="桶权限类型" align="center" prop="accessPolicy">
-          <template #default="scope">
-            <el-tag v-if="scope.row.accessPolicy === '0'" type="warning">private</el-tag>
-            <el-tag v-if="scope.row.accessPolicy === '1'" type="success">public</el-tag>
-            <el-tag v-if="scope.row.accessPolicy === '2'" type="info">custom</el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column v-if="columns[8].visible" label="是否默认" align="center" prop="status">
-          <template #default="scope">
-            <el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
-          </template>
-        </el-table-column>
-        <el-table-column label="操作" fixed="right" align="center" width="150" class-name="small-padding">
-          <template #default="scope">
-            <el-tooltip content="修改" placement="top">
-              <el-button v-hasPermi="['system:ossConfig:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>
-            </el-tooltip>
-            <el-tooltip content="删除" placement="top">
-              <el-button v-hasPermi="['system:ossConfig:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
-            </el-tooltip>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
-    </el-card>
-    <!-- 添加或修改对象存储配置对话框 -->
-    <el-dialog v-model="dialog.visible" :title="dialog.title" width="800px" append-to-body>
-      <el-form ref="ossConfigFormRef" :model="form" :rules="rules" label-width="120px">
-        <el-form-item label="配置key" prop="configKey">
-          <el-input v-model="form.configKey" placeholder="请输入配置key" />
-        </el-form-item>
-        <el-form-item label="访问站点" prop="endpoint">
-          <el-input v-model="form.endpoint" placeholder="请输入访问站点">
-            <template #prefix>
-              <span style="color: #999">{{ protocol }}</span>
-            </template>
-          </el-input>
-        </el-form-item>
-        <el-form-item label="自定义域名" prop="domain">
-          <el-input v-model="form.domain" placeholder="请输入自定义域名">
-            <template #prefix>
-              <span style="color: #999">{{ protocol }}</span>
-            </template>
-          </el-input>
-        </el-form-item>
-        <el-form-item label="accessKey" prop="accessKey">
-          <el-input v-model="form.accessKey" placeholder="请输入accessKey" />
-        </el-form-item>
-        <el-form-item label="secretKey" prop="secretKey">
-          <el-input v-model="form.secretKey" placeholder="请输入秘钥" show-password />
-        </el-form-item>
-        <el-form-item label="桶名称" prop="bucketName">
-          <el-input v-model="form.bucketName" placeholder="请输入桶名称" />
-        </el-form-item>
-        <el-form-item label="前缀" prop="prefix">
-          <el-input v-model="form.prefix" placeholder="请输入前缀" />
-        </el-form-item>
-        <el-form-item label="是否HTTPS">
-          <el-radio-group v-model="form.isHttps">
-            <el-radio v-for="dict in sys_yes_no" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label="桶权限类型">
-          <el-radio-group v-model="form.accessPolicy">
-            <el-radio value="0">private</el-radio>
-            <el-radio value="1">public</el-radio>
-            <el-radio value="2">custom</el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label="域" prop="region">
-          <el-input v-model="form.region" placeholder="请输入域" />
-        </el-form-item>
-        <el-form-item label="备注" prop="remark">
-          <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
-          <el-button @click="cancel">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup name="OssConfig" lang="ts">
-import { listOssConfig, getOssConfig, delOssConfig, addOssConfig, updateOssConfig, changeOssConfigStatus } from '@/api/system/ossConfig';
-import { OssConfigForm, OssConfigQuery, OssConfigVO } from '@/api/system/ossConfig/types';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { sys_yes_no } = toRefs<any>(proxy?.useDict('sys_yes_no'));
-
-const ossConfigList = ref<OssConfigVO[]>([]);
-const buttonLoading = ref(false);
-const loading = ref(true);
-const showSearch = ref(true);
-const ids = ref<Array<number | string>>([]);
-const single = ref(true);
-const multiple = ref(true);
-const total = ref(0);
-
-const queryFormRef = ref<ElFormInstance>();
-const ossConfigFormRef = ref<ElFormInstance>();
-
-const dialog = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-// 列显隐信息
-const columns = ref<FieldOption[]>([
-  { key: 0, label: `主建`, visible: false },
-  { key: 1, label: `配置key`, visible: true },
-  { key: 2, label: `访问站点`, visible: true },
-  { key: 3, label: `自定义域名`, visible: true },
-  { key: 4, label: `桶名称`, visible: true },
-  { key: 5, label: `前缀`, visible: true },
-  { key: 6, label: `域`, visible: true },
-  { key: 7, label: `桶权限类型`, visible: true },
-  { key: 8, label: `状态`, visible: true }
-]);
-
-const initFormData: OssConfigForm = {
-  ossConfigId: undefined,
-  configKey: '',
-  accessKey: '',
-  secretKey: '',
-  bucketName: '',
-  prefix: '',
-  endpoint: '',
-  domain: '',
-  isHttps: 'N',
-  accessPolicy: '1',
-  region: '',
-  status: '1',
-  remark: ''
-};
-const data = reactive<PageData<OssConfigForm, OssConfigQuery>>({
-  form: { ...initFormData },
-  // 查询参数
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    configKey: '',
-    bucketName: '',
-    status: ''
-  },
-  rules: {
-    configKey: [{ required: true, message: 'configKey不能为空', trigger: 'blur' }],
-    accessKey: [
-      { required: true, message: 'accessKey不能为空', trigger: 'blur' },
-      {
-        min: 2,
-        max: 200,
-        message: 'accessKey长度必须介于 2 和 100 之间',
-        trigger: 'blur'
-      }
-    ],
-    secretKey: [
-      { required: true, message: 'secretKey不能为空', trigger: 'blur' },
-      {
-        min: 2,
-        max: 100,
-        message: 'secretKey长度必须介于 2 和 100 之间',
-        trigger: 'blur'
-      }
-    ],
-    bucketName: [
-      { required: true, message: 'bucketName不能为空', trigger: 'blur' },
-      {
-        min: 2,
-        max: 100,
-        message: 'bucketName长度必须介于 2 和 100 之间',
-        trigger: 'blur'
-      }
-    ],
-    endpoint: [
-      { required: true, message: 'endpoint不能为空', trigger: 'blur' },
-      {
-        min: 2,
-        max: 100,
-        message: 'endpoint名称长度必须介于 2 和 100 之间',
-        trigger: 'blur'
-      }
-    ],
-    accessPolicy: [{ required: true, message: 'accessPolicy不能为空', trigger: 'blur' }]
-  }
-});
-
-const { queryParams, form, rules } = toRefs(data);
-
-const protocol = computed(() => (form.value.isHttps === 'Y' ? 'https://' : 'http://'));
-
-/** 查询对象存储配置列表 */
-const getList = async () => {
-  loading.value = true;
-  const res = await listOssConfig(queryParams.value);
-  ossConfigList.value = res.rows;
-  total.value = res.total;
-  loading.value = false;
-};
-/** 取消按钮 */
-const cancel = () => {
-  dialog.visible = false;
-  reset();
-};
-/** 表单重置 */
-const reset = () => {
-  form.value = { ...initFormData };
-  ossConfigFormRef.value?.resetFields();
-};
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.value.pageNum = 1;
-  getList();
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  handleQuery();
-};
-/** 选择条数  */
-const handleSelectionChange = (selection: OssConfigVO[]) => {
-  ids.value = selection.map((item) => item.ossConfigId);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
-};
-/** 新增按钮操作 */
-const handleAdd = () => {
-  reset();
-  dialog.visible = true;
-  dialog.title = '添加对象存储配置';
-};
-/** 修改按钮操作 */
-const handleUpdate = async (row?: OssConfigVO) => {
-  reset();
-  const ossConfigId = row?.ossConfigId || ids.value[0];
-  const res = await getOssConfig(ossConfigId);
-  Object.assign(form.value, res.data);
-  dialog.visible = true;
-  dialog.title = '修改对象存储配置';
-};
-/** 提交按钮 */
-const submitForm = () => {
-  ossConfigFormRef.value?.validate(async (valid: boolean) => {
-    if (valid) {
-      buttonLoading.value = true;
-      if (form.value.ossConfigId) {
-        await updateOssConfig(form.value).finally(() => (buttonLoading.value = false));
-      } else {
-        await addOssConfig(form.value).finally(() => (buttonLoading.value = false));
-      }
-      proxy?.$modal.msgSuccess('新增成功');
-      dialog.visible = false;
-      await getList();
-    }
-  });
-};
-/** 状态修改  */
-const handleStatusChange = async (row: OssConfigVO) => {
-  const text = row.status === '0' ? '启用' : '停用';
-  try {
-    await proxy?.$modal.confirm('确认要"' + text + '""' + row.configKey + '"配置吗?');
-    await changeOssConfigStatus(row.ossConfigId, row.status, row.configKey);
-    await getList();
-    proxy?.$modal.msgSuccess(text + '成功');
-  } catch {
-    return;
-  } finally {
-    row.status = row.status === '0' ? '1' : '0';
-  }
-};
-/** 删除按钮操作 */
-const handleDelete = async (row?: OssConfigVO) => {
-  const ossConfigIds = row?.ossConfigId || ids.value;
-  await proxy?.$modal.confirm('是否确认删除OSS配置编号为"' + ossConfigIds + '"的数据项?');
-  loading.value = true;
-  await delOssConfig(ossConfigIds).finally(() => (loading.value = false));
-  await getList();
-  proxy?.$modal.msgSuccess('删除成功');
-};
-
-onMounted(() => {
-  getList();
-});
-</script>

+ 0 - 333
src/views/system/oss/index.vue

@@ -1,333 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
-        <el-card shadow="hover">
-          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="文件名" prop="fileName">
-              <el-input v-model="queryParams.fileName" placeholder="请输入文件名" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="原名" prop="originalName">
-              <el-input v-model="queryParams.originalName" placeholder="请输入原名" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="文件后缀" prop="fileSuffix">
-              <el-input v-model="queryParams.fileSuffix" placeholder="请输入文件后缀" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="创建时间" style="width: 308px">
-              <el-date-picker
-                v-model="dateRangeCreateTime"
-                value-format="YYYY-MM-DD HH:mm:ss"
-                type="daterange"
-                range-separator="-"
-                start-placeholder="开始日期"
-                end-placeholder="结束日期"
-                :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
-              ></el-date-picker>
-            </el-form-item>
-            <el-form-item label="服务商" prop="service">
-              <el-input v-model="queryParams.service" placeholder="请输入服务商" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" icon="search" @click="handleQuery">搜索</el-button>
-              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
-      </div>
-    </transition>
-
-    <el-card shadow="hover">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:oss:upload']" type="primary" plain icon="Upload" @click="handleFile">上传文件</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:oss:upload']" type="primary" plain icon="Upload" @click="handleImage">上传图片</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:oss:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">
-              删除
-            </el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button
-              v-hasPermi="['system:oss:edit']"
-              :type="previewListResource ? 'danger' : 'warning'"
-              plain
-              @click="handlePreviewListResource(!previewListResource)"
-              >预览开关 : {{ previewListResource ? '禁用' : '启用' }}</el-button
-            >
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:ossConfig:list']" type="info" plain icon="Operation" @click="handleOssConfig">配置管理</el-button>
-          </el-col>
-          <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
-        </el-row>
-      </template>
-
-      <el-table
-        v-if="showTable"
-        v-loading="loading"
-        :data="ossList"
-        border
-        :header-cell-class-name="handleHeaderClass"
-        @selection-change="handleSelectionChange"
-        @header-click="handleHeaderCLick"
-      >
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column v-if="false" label="对象存储主键" align="center" prop="ossId" />
-        <el-table-column label="文件名" align="center" prop="fileName" />
-        <el-table-column label="原名" align="center" prop="originalName" />
-        <el-table-column label="文件后缀" align="center" prop="fileSuffix" />
-        <el-table-column label="文件展示" align="center" prop="url">
-          <template #default="scope">
-            <ImagePreview
-              v-if="previewListResource && checkFileSuffix(scope.row.fileSuffix)"
-              :width="100"
-              :height="100"
-              :src="scope.row.url"
-              :preview-src-list="[scope.row.url]"
-            />
-            <span v-if="!checkFileSuffix(scope.row.fileSuffix) || !previewListResource" v-text="scope.row.url" />
-          </template>
-        </el-table-column>
-        <el-table-column label="创建时间" align="center" prop="createTime" width="180" sortable="custom">
-          <template #default="scope">
-            <span>{{ proxy.parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="上传人" align="center" prop="createByName" />
-        <el-table-column label="服务商" align="center" prop="service" sortable="custom" />
-        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
-          <template #default="scope">
-            <el-tooltip content="下载" placement="top">
-              <el-button v-hasPermi="['system:oss:download']" link type="primary" icon="Download" @click="handleDownload(scope.row)"></el-button>
-            </el-tooltip>
-            <el-tooltip content="删除" placement="top">
-              <el-button v-hasPermi="['system:oss:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
-            </el-tooltip>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
-    </el-card>
-    <!-- 添加或修改OSS对象存储对话框 -->
-    <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body>
-      <el-form ref="ossFormRef" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="文件名">
-          <fileUpload v-if="type === 0" v-model="form.file" />
-          <imageUpload v-if="type === 1" v-model="form.file" />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
-          <el-button @click="cancel">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup name="Oss" lang="ts">
-import { listOss, delOss } from '@/api/system/oss';
-import ImagePreview from '@/components/ImagePreview/index.vue';
-import { OssForm, OssQuery, OssVO } from '@/api/system/oss/types';
-
-const router = useRouter();
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const ossList = ref<OssVO[]>([]);
-const showTable = ref(true);
-const buttonLoading = ref(false);
-const loading = ref(true);
-const showSearch = ref(true);
-const ids = ref<Array<string | number>>([]);
-const single = ref(true);
-const multiple = ref(true);
-const total = ref(0);
-const type = ref(0);
-const previewListResource = ref(true);
-const dateRangeCreateTime = ref<[DateModelType, DateModelType]>(['', '']);
-
-const dialog = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-// 默认排序
-const defaultSort = ref({ prop: 'createTime', order: 'ascending' });
-
-const ossFormRef = ref<ElFormInstance>();
-const queryFormRef = ref<ElFormInstance>();
-
-const initFormData = {
-  file: undefined
-};
-const data = reactive<PageData<OssForm, OssQuery>>({
-  form: { ...initFormData },
-  // 查询参数
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    fileName: '',
-    originalName: '',
-    fileSuffix: '',
-    createTime: '',
-    service: '',
-    orderByColumn: defaultSort.value.prop,
-    isAsc: defaultSort.value.order
-  },
-  rules: {
-    file: [{ required: true, message: '文件不能为空', trigger: 'blur' }]
-  }
-});
-
-const { queryParams, form, rules } = toRefs(data);
-
-/** 查询OSS对象存储列表 */
-const getList = async () => {
-  loading.value = true;
-  const res = await proxy?.getConfigKey('sys.oss.previewListResource');
-  previewListResource.value = res?.data === undefined ? true : res.data === 'true';
-  const response = await listOss(proxy?.addDateRange(queryParams.value, dateRangeCreateTime.value, 'CreateTime'));
-  ossList.value = response.rows;
-  total.value = response.total;
-  loading.value = false;
-  showTable.value = true;
-};
-function checkFileSuffix(fileSuffix: string | string[]) {
-  const arr = ['.png', '.jpg', '.jpeg'];
-  const suffixArray = Array.isArray(fileSuffix) ? fileSuffix : [fileSuffix];
-  return suffixArray.some((suffix) => arr.includes(suffix.toLowerCase()));
-}
-/** 取消按钮 */
-function cancel() {
-  dialog.visible = false;
-  reset();
-}
-/** 表单重置 */
-function reset() {
-  form.value = { ...initFormData };
-  ossFormRef.value?.resetFields();
-}
-/** 搜索按钮操作 */
-function handleQuery() {
-  queryParams.value.pageNum = 1;
-  getList();
-}
-/** 重置按钮操作 */
-function resetQuery() {
-  showTable.value = false;
-  dateRangeCreateTime.value = ['', ''];
-  queryFormRef.value?.resetFields();
-  queryParams.value.orderByColumn = defaultSort.value.prop;
-  queryParams.value.isAsc = defaultSort.value.order;
-  handleQuery();
-}
-/** 选择条数  */
-function handleSelectionChange(selection: OssVO[]) {
-  ids.value = selection.map((item) => item.ossId);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
-}
-/** 设置列的排序为我们自定义的排序 */
-const handleHeaderClass = ({ column }: any): any => {
-  column.order = column.multiOrder;
-};
-/** 点击表头进行排序 */
-const handleHeaderCLick = (column: any) => {
-  if (column.sortable !== 'custom') {
-    return;
-  }
-  switch (column.multiOrder) {
-    case 'descending':
-      column.multiOrder = 'ascending';
-      break;
-    case 'ascending':
-      column.multiOrder = '';
-      break;
-    default:
-      column.multiOrder = 'descending';
-      break;
-  }
-  handleOrderChange(column.property, column.multiOrder);
-};
-const handleOrderChange = (prop: string, order: string) => {
-  const orderByArr = queryParams.value.orderByColumn ? queryParams.value.orderByColumn.split(',') : [];
-  const isAscArr = queryParams.value.isAsc ? queryParams.value.isAsc.split(',') : [];
-  const propIndex = orderByArr.indexOf(prop);
-  if (propIndex !== -1) {
-    if (order) {
-      //排序里已存在 只修改排序
-      isAscArr[propIndex] = order;
-    } else {
-      //如果order为null 则删除排序字段和属性
-      isAscArr.splice(propIndex, 1); //删除排序
-      orderByArr.splice(propIndex, 1); //删除属性
-    }
-  } else {
-    //排序里不存在则新增排序
-    orderByArr.push(prop);
-    isAscArr.push(order);
-  }
-  //合并排序
-  queryParams.value.orderByColumn = orderByArr.join(',');
-  queryParams.value.isAsc = isAscArr.join(',');
-  getList();
-};
-/** 任务日志列表查询 */
-const handleOssConfig = () => {
-  router.push('/system/oss-config/index');
-};
-/** 文件按钮操作 */
-const handleFile = () => {
-  reset();
-  type.value = 0;
-  dialog.visible = true;
-  dialog.title = '上传文件';
-};
-/** 图片按钮操作 */
-const handleImage = () => {
-  reset();
-  type.value = 1;
-  dialog.visible = true;
-  dialog.title = '上传图片';
-};
-/** 提交按钮 */
-const submitForm = () => {
-  dialog.visible = false;
-  getList();
-};
-/** 下载按钮操作 */
-const handleDownload = (row: OssVO) => {
-  proxy?.$download.oss(row.ossId);
-};
-/** 预览开关按钮  */
-const handlePreviewListResource = async (preview: boolean) => {
-  const text = preview ? '启用' : '停用';
-  try {
-    await proxy?.$modal.confirm('确认要"' + text + '""预览列表图片"配置吗?');
-    await proxy?.updateConfigByKey('sys.oss.previewListResource', preview);
-    await getList();
-    proxy?.$modal.msgSuccess(text + '成功');
-  } catch {
-    return;
-  }
-};
-/** 删除按钮操作 */
-const handleDelete = async (row?: OssVO) => {
-  const ossIds = row?.ossId || ids.value;
-  await proxy?.$modal.confirm('是否确认删除OSS对象存储编号为"' + ossIds + '"的数据项?');
-  loading.value = true;
-  await delOss(ossIds).finally(() => (loading.value = false));
-  await getList();
-  proxy?.$modal.msgSuccess('删除成功');
-};
-
-onMounted(() => {
-  getList();
-});
-</script>

+ 0 - 361
src/views/system/post/index.vue

@@ -1,361 +0,0 @@
-<template>
-  <div class="p-2">
-    <el-row :gutter="20">
-      <!-- 部门树 -->
-      <el-col :lg="4" :xs="24" style="">
-        <el-card shadow="hover">
-          <el-input v-model="deptName" placeholder="请输入部门名称" prefix-icon="Search" clearable />
-          <el-tree
-            ref="deptTreeRef"
-            class="mt-2"
-            node-key="id"
-            :data="deptOptions"
-            :props="{ label: 'label', children: 'children' } as any"
-            :expand-on-click-node="false"
-            :filter-node-method="filterNode"
-            highlight-current
-            default-expand-all
-            @node-click="handleNodeClick"
-          />
-        </el-card>
-      </el-col>
-      <el-col :lg="20" :xs="24">
-        <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-          <div v-show="showSearch" class="mb-[10px]">
-            <el-card shadow="hover">
-              <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-                <el-form-item label="岗位编码" prop="postCode">
-                  <el-input v-model="queryParams.postCode" placeholder="请输入岗位编码" clearable @keyup.enter="handleQuery" />
-                </el-form-item>
-                <el-form-item label="类别编码" prop="postCategory">
-                  <el-input
-                    v-model="queryParams.postCategory"
-                    placeholder="请输入类别编码"
-                    clearable
-                    style="width: 200px"
-                    @keyup.enter="handleQuery"
-                  />
-                </el-form-item>
-                <el-form-item label="岗位名称" prop="postName">
-                  <el-input v-model="queryParams.postName" placeholder="请输入岗位名称" clearable @keyup.enter="handleQuery" />
-                </el-form-item>
-                <el-form-item label="部门" prop="deptId">
-                  <el-tree-select
-                    v-model="queryParams.deptId"
-                    :data="deptOptions"
-                    :props="{ value: 'id', label: 'label', children: 'children' } as any"
-                    value-key="id"
-                    placeholder="请选择部门"
-                    check-strictly
-                  />
-                </el-form-item>
-                <el-form-item label="状态" prop="status">
-                  <el-select v-model="queryParams.status" placeholder="岗位状态" clearable>
-                    <el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
-                  </el-select>
-                </el-form-item>
-                <el-form-item>
-                  <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-                  <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-                </el-form-item>
-              </el-form>
-            </el-card>
-          </div>
-        </transition>
-        <el-card shadow="hover">
-          <template #header>
-            <el-row :gutter="10" class="mb8">
-              <el-col :span="1.5">
-                <el-button v-hasPermi="['system:post:add']" type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
-              </el-col>
-              <el-col :span="1.5">
-                <el-button v-hasPermi="['system:post:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()"
-                  >修改</el-button
-                >
-              </el-col>
-              <el-col :span="1.5">
-                <el-button v-hasPermi="['system:post:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">
-                  删除
-                </el-button>
-              </el-col>
-              <el-col :span="1.5">
-                <el-button v-hasPermi="['system:post:export']" type="warning" plain icon="Download" @click="handleExport">导出</el-button>
-              </el-col>
-              <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
-            </el-row>
-          </template>
-          <el-table v-loading="loading" border :data="postList" @selection-change="handleSelectionChange">
-            <el-table-column type="selection" width="55" align="center" />
-            <el-table-column v-if="false" label="岗位编号" align="center" prop="postId" />
-            <el-table-column label="岗位编码" align="center" prop="postCode" />
-            <el-table-column label="类别编码" align="center" prop="postCategory" />
-            <el-table-column label="岗位名称" align="center" prop="postName" />
-            <el-table-column label="部门" align="center" prop="deptName" />
-            <el-table-column label="排序" align="center" prop="postSort" />
-            <el-table-column label="状态" align="center" prop="status">
-              <template #default="scope">
-                <dict-tag :options="sys_normal_disable" :value="scope.row.status" />
-              </template>
-            </el-table-column>
-            <el-table-column label="创建时间" align="center" prop="createTime" width="180">
-              <template #default="scope">
-                <span>{{ proxy.parseTime(scope.row.createTime) }}</span>
-              </template>
-            </el-table-column>
-            <el-table-column label="操作" width="180" align="center" class-name="small-padding fixed-width">
-              <template #default="scope">
-                <el-tooltip content="修改" placement="top">
-                  <el-button v-hasPermi="['system:post:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>
-                </el-tooltip>
-                <el-tooltip content="删除" placement="top">
-                  <el-button v-hasPermi="['system:post:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
-                </el-tooltip>
-              </template>
-            </el-table-column>
-          </el-table>
-
-          <pagination
-            v-show="total > 0"
-            v-model:page="queryParams.pageNum"
-            v-model:limit="queryParams.pageSize"
-            :total="total"
-            @pagination="getList"
-          />
-        </el-card>
-
-        <!-- 添加或修改岗位对话框 -->
-        <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body>
-          <el-form ref="postFormRef" :model="form" :rules="rules" label-width="80px">
-            <el-form-item label="岗位名称" prop="postName">
-              <el-input v-model="form.postName" placeholder="请输入岗位名称" />
-            </el-form-item>
-            <el-form-item label="部门" prop="deptId">
-              <el-tree-select
-                v-model="form.deptId"
-                :data="deptOptions"
-                :props="{ value: 'id', label: 'label', children: 'children' } as any"
-                value-key="id"
-                placeholder="请选择部门"
-                check-strictly
-              />
-            </el-form-item>
-            <el-form-item label="岗位编码" prop="postCode">
-              <el-input v-model="form.postCode" placeholder="请输入编码名称" />
-            </el-form-item>
-            <el-form-item label="类别编码" prop="postCategory">
-              <el-input v-model="form.postCategory" placeholder="请输入类别编码" />
-            </el-form-item>
-            <el-form-item label="岗位顺序" prop="postSort">
-              <el-input-number v-model="form.postSort" controls-position="right" :min="0" />
-            </el-form-item>
-            <el-form-item label="岗位状态" prop="status">
-              <el-radio-group v-model="form.status">
-                <el-radio v-for="dict in sys_normal_disable" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
-              </el-radio-group>
-            </el-form-item>
-            <el-form-item label="备注" prop="remark">
-              <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
-            </el-form-item>
-          </el-form>
-          <template #footer>
-            <div class="dialog-footer">
-              <el-button type="primary" @click="submitForm">确 定</el-button>
-              <el-button @click="cancel">取 消</el-button>
-            </div>
-          </template>
-        </el-dialog>
-      </el-col>
-    </el-row>
-  </div>
-</template>
-
-<script setup name="Post" lang="ts">
-import { listPost, addPost, delPost, getPost, updatePost, deptTreeSelect } from '@/api/system/post';
-import { PostForm, PostQuery, PostVO } from '@/api/system/post/types';
-import { DeptTreeVO, DeptVO } from '@/api/system/dept/types';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { sys_normal_disable } = toRefs<any>(proxy?.useDict('sys_normal_disable'));
-
-const postList = ref<PostVO[]>([]);
-const loading = ref(true);
-const showSearch = ref(true);
-const ids = ref<Array<number | string>>([]);
-const single = ref(true);
-const multiple = ref(true);
-const total = ref(0);
-const deptName = ref('');
-const deptOptions = ref<DeptTreeVO[]>([]);
-const deptTreeRef = ref<ElTreeInstance>();
-const postFormRef = ref<ElFormInstance>();
-const queryFormRef = ref<ElFormInstance>();
-
-const dialog = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-const initFormData: PostForm = {
-  postId: undefined,
-  deptId: undefined,
-  postCode: '',
-  postName: '',
-  postCategory: '',
-  postSort: 0,
-  status: '0',
-  remark: ''
-};
-
-const data = reactive<PageData<PostForm, PostQuery>>({
-  form: { ...initFormData },
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    deptId: undefined,
-    belongDeptId: undefined,
-    postCode: '',
-    postName: '',
-    postCategory: '',
-    status: ''
-  },
-  rules: {
-    postName: [{ required: true, message: '岗位名称不能为空', trigger: 'blur' }],
-    postCode: [{ required: true, message: '岗位编码不能为空', trigger: 'blur' }],
-    deptId: [{ required: true, message: '部门不能为空', trigger: 'blur' }],
-    postSort: [{ required: true, message: '岗位顺序不能为空', trigger: 'blur' }]
-  }
-});
-
-const { queryParams, form, rules } = toRefs<PageData<PostForm, PostQuery>>(data);
-
-/** 通过条件过滤节点  */
-const filterNode = (value: string, data: any) => {
-  if (!value) return true;
-  return data.label.indexOf(value) !== -1;
-};
-
-/** 根据名称筛选部门树 */
-watchEffect(
-  () => {
-    deptTreeRef.value?.filter(deptName.value);
-  },
-  {
-    flush: 'post' // watchEffect会在DOM挂载或者更新之前就会触发,此属性控制在DOM元素更新后运行
-  }
-);
-
-/** 查询部门下拉树结构 */
-const getTreeSelect = async () => {
-  const res = await deptTreeSelect();
-  deptOptions.value = res.data;
-};
-
-/** 节点单击事件 */
-const handleNodeClick = (data: DeptVO) => {
-  queryParams.value.belongDeptId = data.id;
-  queryParams.value.deptId = undefined;
-  handleQuery();
-};
-
-/** 查询岗位列表 */
-const getList = async () => {
-  loading.value = true;
-  const res = await listPost(queryParams.value);
-  postList.value = res.rows;
-  total.value = res.total;
-  loading.value = false;
-};
-
-/** 取消按钮 */
-const cancel = () => {
-  reset();
-  dialog.visible = false;
-};
-
-/** 表单重置 */
-const reset = () => {
-  form.value = { ...initFormData };
-  postFormRef.value?.resetFields();
-};
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.value.pageNum = 1;
-  if (queryParams.value.deptId) {
-    queryParams.value.belongDeptId = undefined;
-  }
-  getList();
-};
-
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  queryParams.value.pageNum = 1;
-  queryParams.value.deptId = undefined;
-  deptTreeRef.value?.setCurrentKey(undefined);
-  /** 清空左边部门树选中值 */
-  queryParams.value.belongDeptId = undefined;
-  handleQuery();
-};
-
-/** 多选框选中数据 */
-const handleSelectionChange = (selection: PostVO[]) => {
-  ids.value = selection.map((item) => item.postId);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
-};
-
-/** 新增按钮操作 */
-const handleAdd = () => {
-  reset();
-  dialog.visible = true;
-  dialog.title = '添加岗位';
-};
-
-/** 修改按钮操作 */
-const handleUpdate = async (row?: PostVO) => {
-  reset();
-  const postId = row?.postId || ids.value[0];
-  const res = await getPost(postId);
-  Object.assign(form.value, res.data);
-  dialog.visible = true;
-  dialog.title = '修改岗位';
-};
-
-/** 提交按钮 */
-const submitForm = () => {
-  postFormRef.value?.validate(async (valid: boolean) => {
-    if (valid) {
-      form.value.postId ? await updatePost(form.value) : await addPost(form.value);
-      proxy?.$modal.msgSuccess('操作成功');
-      dialog.visible = false;
-      await getList();
-    }
-  });
-};
-
-/** 删除按钮操作 */
-const handleDelete = async (row?: PostVO) => {
-  const postIds = row?.postId || ids.value;
-  await proxy?.$modal.confirm('是否确认删除岗位编号为"' + postIds + '"的数据项?');
-  await delPost(postIds);
-  await getList();
-  proxy?.$modal.msgSuccess('删除成功');
-};
-
-/** 导出按钮操作 */
-const handleExport = () => {
-  proxy?.download(
-    'system/post/export',
-    {
-      ...queryParams.value
-    },
-    `post_${new Date().getTime()}.xlsx`
-  );
-};
-
-onMounted(() => {
-  getTreeSelect(); // 初始化部门数据
-  getList();
-});
-</script>

+ 0 - 158
src/views/system/role/authUser.vue

@@ -1,158 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="search">
-        <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-          <el-form-item label="用户名称" prop="userName">
-            <el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable @keyup.enter="handleQuery" />
-          </el-form-item>
-          <el-form-item label="手机号码" prop="phonenumber">
-            <el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable @keyup.enter="handleQuery" />
-          </el-form-item>
-          <el-form-item>
-            <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-            <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-          </el-form-item>
-        </el-form>
-      </div>
-    </transition>
-    <el-card shadow="never">
-      <template #header>
-        <el-row :gutter="10">
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:role:add']" type="primary" plain icon="Plus" @click="openSelectUser">添加用户</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:role:remove']" type="danger" plain icon="CircleClose" :disabled="multiple" @click="cancelAuthUserAll">
-              批量取消授权
-            </el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="warning" plain icon="Close" @click="handleClose">关闭</el-button>
-          </el-col>
-          <right-toolbar v-model:show-search="showSearch" :search="true" @query-table="getList"></right-toolbar>
-        </el-row>
-      </template>
-      <el-table v-loading="loading" border :data="userList" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column label="用户名称" prop="userName" :show-overflow-tooltip="true" />
-        <el-table-column label="用户昵称" prop="nickName" :show-overflow-tooltip="true" />
-        <el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" />
-        <el-table-column label="手机" prop="phonenumber" :show-overflow-tooltip="true" />
-        <el-table-column label="状态" align="center" prop="status">
-          <template #default="scope">
-            <dict-tag :options="sys_normal_disable" :value="scope.row.status" />
-          </template>
-        </el-table-column>
-        <el-table-column label="创建时间" align="center" prop="createTime" width="180">
-          <template #default="scope">
-            <span>{{ scope.row.createTime }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
-          <template #default="scope">
-            <el-tooltip content="取消授权" placement="top">
-              <el-button v-hasPermi="['system:role:remove']" link type="primary" icon="CircleClose" @click="cancelAuthUser(scope.row)"> </el-button>
-            </el-tooltip>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
-      <select-user ref="selectRef" :role-id="queryParams.roleId" @ok="handleQuery" />
-    </el-card>
-  </div>
-</template>
-
-<script setup name="AuthUser" lang="ts">
-import { allocatedUserList, authUserCancel, authUserCancelAll } from '@/api/system/role';
-import { UserQuery } from '@/api/system/user/types';
-import { UserVO } from '@/api/system/user/types';
-import SelectUser from './selectUser.vue';
-import { RouteLocationNormalized } from 'vue-router';
-
-const route = useRoute();
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { sys_normal_disable } = toRefs<any>(proxy?.useDict('sys_normal_disable'));
-
-const userList = ref<UserVO[]>([]);
-const loading = ref(true);
-const showSearch = ref(true);
-const multiple = ref(true);
-const total = ref(0);
-const userIds = ref<Array<string | number>>([]);
-
-const queryFormRef = ref<ElFormInstance>();
-const selectRef = ref<InstanceType<typeof SelectUser>>();
-
-const queryParams = reactive<UserQuery>({
-  pageNum: 1,
-  pageSize: 10,
-  roleId: route.params.roleId as string,
-  userName: undefined,
-  phonenumber: undefined
-});
-
-/** 查询授权用户列表 */
-const getList = async () => {
-  loading.value = true;
-  const res = await allocatedUserList(queryParams);
-  userList.value = res.rows;
-  total.value = res.total;
-  loading.value = false;
-};
-// 返回按钮
-const handleClose = () => {
-  const obj: RouteLocationNormalized = {
-    path: '/system/role',
-    fullPath: '',
-    hash: '',
-    matched: [],
-    meta: undefined,
-    name: undefined,
-    params: undefined,
-    query: undefined,
-    redirectedFrom: undefined
-  };
-  proxy?.$tab.closeOpenPage(obj);
-};
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.pageNum = 1;
-  getList();
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  handleQuery();
-};
-// 多选框选中数据
-const handleSelectionChange = (selection: UserVO[]) => {
-  userIds.value = selection.map((item) => item.userId);
-  multiple.value = !selection.length;
-};
-/** 打开授权用户表弹窗 */
-const openSelectUser = () => {
-  selectRef.value?.show();
-};
-/** 取消授权按钮操作 */
-const cancelAuthUser = async (row: UserVO) => {
-  await proxy?.$modal.confirm('确认要取消该用户"' + row.userName + '"角色吗?');
-  await authUserCancel({ userId: row.userId, roleId: queryParams.roleId });
-  await getList();
-  proxy?.$modal.msgSuccess('取消授权成功');
-};
-/** 批量取消授权按钮操作 */
-const cancelAuthUserAll = async () => {
-  const roleId = queryParams.roleId;
-  const uIds = userIds.value.join(',');
-  await proxy?.$modal.confirm('是否取消选中用户授权数据项?');
-  await authUserCancelAll({ roleId: roleId, userIds: uIds });
-  await getList();
-  proxy?.$modal.msgSuccess('取消授权成功');
-};
-
-onMounted(() => {
-  getList();
-});
-</script>

+ 0 - 503
src/views/system/role/index.vue

@@ -1,503 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
-        <el-card shadow="hover">
-          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="角色名称" prop="roleName">
-              <el-input v-model="queryParams.roleName" placeholder="请输入角色名称" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="权限字符" prop="roleKey">
-              <el-input v-model="queryParams.roleKey" placeholder="请输入权限字符" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="状态" prop="status">
-              <el-select v-model="queryParams.status" placeholder="角色状态" clearable>
-                <el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
-              </el-select>
-            </el-form-item>
-            <el-form-item label="创建时间" style="width: 308px">
-              <el-date-picker
-                v-model="dateRange"
-                value-format="YYYY-MM-DD HH:mm:ss"
-                type="daterange"
-                range-separator="-"
-                start-placeholder="开始日期"
-                end-placeholder="结束日期"
-                :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
-              ></el-date-picker>
-            </el-form-item>
-
-            <el-form-item>
-              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
-      </div>
-    </transition>
-
-    <el-card shadow="hover">
-      <template #header>
-        <el-row :gutter="10">
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:role:add']" type="primary" plain icon="Plus" @click="handleAdd()">新增</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:role:edit']" type="success" plain :disabled="single" icon="Edit" @click="handleUpdate()">修改</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:role:delete']" type="danger" plain :disabled="ids.length === 0" @click="handleDelete()">删除</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:role:export']" type="warning" plain icon="Download" @click="handleExport">导出</el-button>
-          </el-col>
-          <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
-        </el-row>
-      </template>
-
-      <el-table ref="roleTableRef" border v-loading="loading" :data="roleList" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column v-if="false" label="角色编号" prop="roleId" width="120" />
-        <el-table-column label="角色名称" prop="roleName" :show-overflow-tooltip="true" width="150" />
-        <el-table-column label="权限字符" prop="roleKey" :show-overflow-tooltip="true" width="200" />
-        <el-table-column label="显示顺序" prop="roleSort" width="100" />
-        <el-table-column label="状态" align="center" width="100">
-          <template #default="scope">
-            <el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
-          </template>
-        </el-table-column>
-        <el-table-column label="创建时间" align="center" prop="createTime">
-          <template #default="scope">
-            <span>{{ proxy.parseTime(scope.row.createTime) }}</span>
-          </template>
-        </el-table-column>
-
-        <el-table-column fixed="right" label="操作" width="180">
-          <template #default="scope">
-            <el-tooltip v-if="scope.row.roleId !== 1" content="修改" placement="top">
-              <el-button v-hasPermi="['system:role:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>
-            </el-tooltip>
-            <el-tooltip v-if="scope.row.roleId !== 1" content="删除" placement="top">
-              <el-button v-hasPermi="['system:role:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
-            </el-tooltip>
-            <el-tooltip v-if="scope.row.roleId !== 1" content="数据权限" placement="top">
-              <el-button v-hasPermi="['system:role:edit']" link type="primary" icon="CircleCheck" @click="handleDataScope(scope.row)"></el-button>
-            </el-tooltip>
-            <el-tooltip v-if="scope.row.roleId !== 1" content="分配用户" placement="top">
-              <el-button v-hasPermi="['system:role:edit']" link type="primary" icon="User" @click="handleAuthUser(scope.row)"></el-button>
-            </el-tooltip>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <pagination
-        v-if="total > 0"
-        v-model:total="total"
-        v-model:page="queryParams.pageNum"
-        v-model:limit="queryParams.pageSize"
-        @pagination="getList"
-      />
-    </el-card>
-
-    <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body>
-      <el-form ref="roleFormRef" :model="form" :rules="rules" label-width="100px">
-        <el-form-item label="角色名称" prop="roleName">
-          <el-input v-model="form.roleName" placeholder="请输入角色名称" />
-        </el-form-item>
-        <el-form-item prop="roleKey">
-          <template #label>
-            <span>
-              <el-tooltip content="控制器中定义的权限字符,如:@SaCheckRole('admin')" placement="top">
-                <el-icon><question-filled /></el-icon>
-              </el-tooltip>
-              权限字符
-            </span>
-          </template>
-          <el-input v-model="form.roleKey" placeholder="请输入权限字符" />
-        </el-form-item>
-        <el-form-item label="角色顺序" prop="roleSort">
-          <el-input-number v-model="form.roleSort" controls-position="right" :min="0" />
-        </el-form-item>
-        <el-form-item label="状态">
-          <el-radio-group v-model="form.status">
-            <el-radio v-for="dict in sys_normal_disable" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label="菜单权限">
-          <el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox>
-          <el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选</el-checkbox>
-          <el-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">父子联动</el-checkbox>
-          <el-tree
-            ref="menuRef"
-            class="tree-border"
-            :data="menuOptions"
-            show-checkbox
-            node-key="id"
-            :check-strictly="!form.menuCheckStrictly"
-            empty-text="加载中,请稍候"
-            :props="{ label: 'label', children: 'children' } as any"
-          ></el-tree>
-        </el-form-item>
-        <el-form-item label="备注">
-          <el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button type="primary" @click="submitForm">确 定</el-button>
-          <el-button @click="cancel">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
-
-    <!-- 分配角色数据权限对话框 -->
-    <el-dialog v-model="openDataScope" :title="dialog.title" width="500px" append-to-body>
-      <el-form ref="dataScopeRef" :model="form" label-width="80px">
-        <el-form-item label="角色名称">
-          <el-input v-model="form.roleName" :disabled="true" />
-        </el-form-item>
-        <el-form-item label="权限字符">
-          <el-input v-model="form.roleKey" :disabled="true" />
-        </el-form-item>
-        <el-form-item label="权限范围">
-          <el-select v-model="form.dataScope" @change="dataScopeSelectChange">
-            <el-option v-for="item in dataScopeOptions" :key="item.value" :label="item.label" :value="item.value"></el-option>
-          </el-select>
-        </el-form-item>
-        <el-form-item v-show="form.dataScope === '2'" label="数据权限">
-          <el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox>
-          <el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">全选/全不选</el-checkbox>
-          <el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">父子联动</el-checkbox>
-          <el-tree
-            ref="deptRef"
-            class="tree-border"
-            :data="deptOptions"
-            show-checkbox
-            default-expand-all
-            node-key="id"
-            :check-strictly="!form.deptCheckStrictly"
-            empty-text="加载中,请稍候"
-            :props="{ label: 'label', children: 'children' } as any"
-          ></el-tree>
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button type="primary" @click="submitDataScope">确 定</el-button>
-          <el-button @click="cancelDataScope">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup name="Role" lang="ts">
-import { addRole, changeRoleStatus, dataScope, delRole, getRole, listRole, updateRole, deptTreeSelect } from '@/api/system/role';
-import { roleMenuTreeselect, treeselect as menuTreeselect } from '@/api/system/menu/index';
-import { RoleVO, RoleForm, RoleQuery, DeptTreeOption } from '@/api/system/role/types';
-import { MenuTreeOption, RoleMenuTree } from '@/api/system/menu/types';
-
-const router = useRouter();
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { sys_normal_disable } = toRefs<any>(proxy?.useDict('sys_normal_disable'));
-
-const roleList = ref<RoleVO[]>();
-const loading = ref(true);
-const showSearch = ref(true);
-const ids = ref<Array<string | number>>([]);
-const single = ref(true);
-const multiple = ref(true);
-const total = ref(0);
-const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
-const menuOptions = ref<MenuTreeOption[]>([]);
-const menuExpand = ref(false);
-const menuNodeAll = ref(false);
-const deptExpand = ref(true);
-const deptNodeAll = ref(false);
-const deptOptions = ref<DeptTreeOption[]>([]);
-const openDataScope = ref(false);
-
-/** 数据范围选项*/
-const dataScopeOptions = ref([
-  { value: '1', label: '全部数据权限' },
-  { value: '2', label: '自定数据权限' },
-  { value: '3', label: '本部门数据权限' },
-  { value: '4', label: '本部门及以下数据权限' },
-  { value: '5', label: '仅本人数据权限' },
-  { value: '6', label: '部门及以下或本人数据权限' }
-]);
-
-const queryFormRef = ref<ElFormInstance>();
-const roleFormRef = ref<ElFormInstance>();
-const dataScopeRef = ref<ElFormInstance>();
-const menuRef = ref<ElTreeInstance>();
-const deptRef = ref<ElTreeInstance>();
-
-const initForm: RoleForm = {
-  roleId: undefined,
-  roleSort: 1,
-  status: '0',
-  roleName: '',
-  roleKey: '',
-  menuCheckStrictly: true,
-  deptCheckStrictly: true,
-  remark: '',
-  dataScope: '1',
-  menuIds: [],
-  deptIds: []
-};
-
-const data = reactive<PageData<RoleForm, RoleQuery>>({
-  form: { ...initForm },
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    roleName: '',
-    roleKey: '',
-    status: ''
-  },
-  rules: {
-    roleName: [{ required: true, message: '角色名称不能为空', trigger: 'blur' }],
-    roleKey: [{ required: true, message: '权限字符不能为空', trigger: 'blur' }],
-    roleSort: [{ required: true, message: '角色顺序不能为空', trigger: 'blur' }]
-  }
-});
-const { form, queryParams, rules } = toRefs(data);
-
-const dialog = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-/**
- * 查询角色列表
- */
-const getList = () => {
-  loading.value = true;
-  listRole(proxy?.addDateRange(queryParams.value, dateRange.value)).then((res) => {
-    roleList.value = res.rows;
-    total.value = res.total;
-    loading.value = false;
-  });
-};
-
-/**
- * 搜索按钮操作
- */
-const handleQuery = () => {
-  queryParams.value.pageNum = 1;
-  getList();
-};
-
-/** 重置 */
-const resetQuery = () => {
-  dateRange.value = ['', ''];
-  queryFormRef.value?.resetFields();
-  handleQuery();
-};
-/**删除按钮操作 */
-const handleDelete = async (row?: RoleVO) => {
-  const roleids = row?.roleId || ids.value;
-  await proxy?.$modal.confirm('是否确认删除角色编号为' + roleids + '数据项目');
-  await delRole(roleids);
-  getList();
-  proxy?.$modal.msgSuccess('删除成功');
-};
-
-/** 导出按钮操作 */
-const handleExport = () => {
-  proxy?.download(
-    'system/role/export',
-    {
-      ...queryParams.value
-    },
-    `role_${new Date().getTime()}.xlsx`
-  );
-};
-/** 多选框选中数据 */
-const handleSelectionChange = (selection: RoleVO[]) => {
-  ids.value = selection.map((item: RoleVO) => item.roleId);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
-};
-
-/** 角色状态修改 */
-const handleStatusChange = async (row: RoleVO) => {
-  const text = row.status === '0' ? '启用' : '停用';
-  try {
-    await proxy?.$modal.confirm('确认要"' + text + '""' + row.roleName + '"角色吗?');
-    await changeRoleStatus(row.roleId, row.status);
-    proxy?.$modal.msgSuccess(text + '成功');
-  } catch {
-    row.status = row.status === '0' ? '1' : '0';
-  }
-};
-
-/** 分配用户 */
-const handleAuthUser = (row: RoleVO) => {
-  router.push('/system/role-auth/user/' + row.roleId);
-};
-
-/** 查询菜单树结构 */
-const getMenuTreeselect = async () => {
-  const res = await menuTreeselect();
-  menuOptions.value = res.data;
-};
-/** 所有部门节点数据 */
-const getDeptAllCheckedKeys = (): any => {
-  // 目前被选中的部门节点
-  const checkedKeys = deptRef.value?.getCheckedKeys();
-  // 半选中的部门节点
-  const halfCheckedKeys = deptRef.value?.getHalfCheckedKeys();
-  if (halfCheckedKeys) {
-    checkedKeys?.unshift(...halfCheckedKeys);
-  }
-  return checkedKeys;
-};
-/** 重置新增的表单以及其他数据  */
-const reset = () => {
-  menuRef.value?.setCheckedKeys([]);
-  menuExpand.value = false;
-  menuNodeAll.value = false;
-  deptExpand.value = true;
-  deptNodeAll.value = false;
-  form.value = { ...initForm };
-  roleFormRef.value?.resetFields();
-};
-
-/** 添加角色 */
-const handleAdd = () => {
-  reset();
-  getMenuTreeselect();
-  dialog.visible = true;
-  dialog.title = '添加角色';
-};
-/** 修改角色 */
-const handleUpdate = async (row?: RoleVO) => {
-  reset();
-  const roleId = row?.roleId || ids.value[0];
-  const { data } = await getRole(roleId);
-  Object.assign(form.value, data);
-  form.value.roleSort = Number(form.value.roleSort);
-  const res = await getRoleMenuTreeselect(roleId);
-  dialog.title = '修改角色';
-  dialog.visible = true;
-  res.checkedKeys.forEach((v) => {
-    nextTick(() => {
-      menuRef.value?.setChecked(v, true, false);
-    });
-  });
-};
-/** 根据角色ID查询菜单树结构 */
-const getRoleMenuTreeselect = (roleId: string | number) => {
-  return roleMenuTreeselect(roleId).then((res): RoleMenuTree => {
-    menuOptions.value = res.data.menus;
-    return res.data;
-  });
-};
-/** 根据角色ID查询部门树结构 */
-const getRoleDeptTreeSelect = async (roleId: string | number) => {
-  const res = await deptTreeSelect(roleId);
-  deptOptions.value = res.data.depts;
-  return res.data;
-};
-/** 树权限(展开/折叠)*/
-const handleCheckedTreeExpand = (value: boolean, type: string) => {
-  if (type == 'menu') {
-    const treeList = menuOptions.value;
-    for (let i = 0; i < treeList.length; i++) {
-      if (menuRef.value) {
-        menuRef.value.store.nodesMap[treeList[i].id].expanded = value;
-      }
-    }
-  } else if (type == 'dept') {
-    const treeList = deptOptions.value;
-    for (let i = 0; i < treeList.length; i++) {
-      if (deptRef.value) {
-        deptRef.value.store.nodesMap[treeList[i].id].expanded = value;
-      }
-    }
-  }
-};
-/** 树权限(全选/全不选) */
-const handleCheckedTreeNodeAll = (value: any, type: string) => {
-  if (type == 'menu') {
-    menuRef.value?.setCheckedNodes(value ? (menuOptions.value as any) : []);
-  } else if (type == 'dept') {
-    deptRef.value?.setCheckedNodes(value ? (deptOptions.value as any) : []);
-  }
-};
-/** 树权限(父子联动) */
-const handleCheckedTreeConnect = (value: any, type: string) => {
-  if (type == 'menu') {
-    form.value.menuCheckStrictly = value;
-  } else if (type == 'dept') {
-    form.value.deptCheckStrictly = value;
-  }
-};
-/** 所有菜单节点数据 */
-const getMenuAllCheckedKeys = (): any => {
-  // 目前被选中的菜单节点
-  const checkedKeys = menuRef.value?.getCheckedKeys();
-  // 半选中的菜单节点
-  const halfCheckedKeys = menuRef.value?.getHalfCheckedKeys();
-  if (halfCheckedKeys) {
-    checkedKeys?.unshift(...halfCheckedKeys);
-  }
-  return checkedKeys;
-};
-/** 提交按钮 */
-const submitForm = () => {
-  roleFormRef.value?.validate(async (valid: boolean) => {
-    if (valid) {
-      form.value.menuIds = getMenuAllCheckedKeys();
-      form.value.roleId ? await updateRole(form.value) : await addRole(form.value);
-      proxy?.$modal.msgSuccess('操作成功');
-      dialog.visible = false;
-      getList();
-    }
-  });
-};
-/** 取消按钮 */
-const cancel = () => {
-  reset();
-  dialog.visible = false;
-};
-/** 选择角色权限范围触发 */
-const dataScopeSelectChange = (value: string) => {
-  if (value !== '2') {
-    deptRef.value?.setCheckedKeys([]);
-  }
-};
-/** 分配数据权限操作 */
-const handleDataScope = async (row: RoleVO) => {
-  const response = await getRole(row.roleId);
-  Object.assign(form.value, response.data);
-  const res = await getRoleDeptTreeSelect(row.roleId);
-  openDataScope.value = true;
-  dialog.title = '分配数据权限';
-  await nextTick(() => {
-    deptRef.value?.setCheckedKeys(res.checkedKeys);
-  });
-};
-/** 提交按钮(数据权限) */
-const submitDataScope = async () => {
-  if (form.value.roleId) {
-    form.value.deptIds = getDeptAllCheckedKeys();
-    await dataScope(form.value);
-    proxy?.$modal.msgSuccess('修改成功');
-    openDataScope.value = false;
-    getList();
-  }
-};
-/** 取消按钮(数据权限)*/
-const cancelDataScope = () => {
-  dataScopeRef.value?.resetFields();
-  form.value = { ...initForm };
-  openDataScope.value = false;
-};
-
-onMounted(() => {
-  getList();
-});
-</script>

+ 0 - 130
src/views/system/role/selectUser.vue

@@ -1,130 +0,0 @@
-<template>
-  <el-row>
-    <el-dialog v-model="visible" title="选择用户" width="800px" top="5vh" append-to-body>
-      <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-        <el-form-item label="用户名称" prop="userName">
-          <el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable @keyup.enter="handleQuery" />
-        </el-form-item>
-        <el-form-item label="手机号码" prop="phonenumber">
-          <el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable @keyup.enter="handleQuery" />
-        </el-form-item>
-        <el-form-item>
-          <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-          <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-        </el-form-item>
-      </el-form>
-      <el-row>
-        <el-table ref="tableRef" border :data="userList" height="260px" @row-click="clickRow" @selection-change="handleSelectionChange">
-          <el-table-column type="selection" width="55"></el-table-column>
-          <el-table-column label="用户名称" prop="userName" :show-overflow-tooltip="true" />
-          <el-table-column label="用户昵称" prop="nickName" :show-overflow-tooltip="true" />
-          <el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" />
-          <el-table-column label="手机" prop="phonenumber" :show-overflow-tooltip="true" />
-          <el-table-column label="状态" align="center" prop="status">
-            <template #default="scope">
-              <dict-tag :options="sys_normal_disable" :value="scope.row.status" />
-            </template>
-          </el-table-column>
-          <el-table-column label="创建时间" align="center" prop="createTime" width="180">
-            <template #default="scope">
-              <span>{{ proxy.parseTime(scope.row.createTime) }}</span>
-            </template>
-          </el-table-column>
-        </el-table>
-        <pagination v-if="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
-      </el-row>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button type="primary" @click="handleSelectUser">确 定</el-button>
-          <el-button @click="visible = false">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </el-row>
-</template>
-
-<script setup name="SelectUser" lang="ts">
-import { authUserSelectAll, unallocatedUserList } from '@/api/system/role';
-import { UserVO } from '@/api/system/user/types';
-import { UserQuery } from '@/api/system/user/types';
-
-const props = defineProps({
-  roleId: {
-    type: [Number, String],
-    required: true
-  }
-});
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { sys_normal_disable } = toRefs<any>(proxy?.useDict('sys_normal_disable'));
-
-const userList = ref<UserVO[]>([]);
-const visible = ref(false);
-const total = ref(0);
-const userIds = ref<Array<string | number>>([]);
-
-const queryParams = reactive<UserQuery>({
-  pageNum: 1,
-  pageSize: 10,
-  roleId: undefined,
-  userName: undefined,
-  phonenumber: undefined
-});
-
-const tableRef = ref<ElTableInstance>();
-const queryFormRef = ref<ElFormInstance>();
-
-const show = () => {
-  queryParams.roleId = props.roleId;
-  getList();
-  visible.value = true;
-};
-
-/**
- * 选择行
- */
-const clickRow = (row: any) => {
-  // ele的bug
-  tableRef.value?.toggleRowSelection(row, false);
-};
-/** 多选框选中数据 */
-const handleSelectionChange = (selection: UserVO[]) => {
-  userIds.value = selection.map((item: UserVO) => item.userId);
-};
-
-/** 查询数据 */
-const getList = async () => {
-  const res = await unallocatedUserList(queryParams);
-  userList.value = res.rows;
-  total.value = res.total;
-};
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.pageNum = 1;
-  getList();
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  getList();
-};
-
-const emit = defineEmits(['ok']);
-/**选择授权用户操作 */
-const handleSelectUser = async () => {
-  const roleId = queryParams.roleId;
-  const ids = userIds.value.join(',');
-  if (ids == '') {
-    proxy?.$modal.msgError('请选择要分配的用户');
-    return;
-  }
-  await authUserSelectAll({ roleId, userIds: ids });
-  proxy?.$modal.msgSuccess('分配成功');
-  emit('ok');
-  visible.value = false;
-};
-// 暴露
-defineExpose({
-  show
-});
-</script>

+ 0 - 382
src/views/system/tenant/index.vue

@@ -1,382 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
-        <el-card shadow="hover">
-          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="租户编号" prop="tenantId">
-              <el-input v-model="queryParams.tenantId" placeholder="请输入租户编号" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="联系人" prop="contactUserName">
-              <el-input v-model="queryParams.contactUserName" placeholder="请输入联系人" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="联系电话" prop="contactPhone">
-              <el-input v-model="queryParams.contactPhone" placeholder="请输入联系电话" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="企业名称" prop="companyName">
-              <el-input v-model="queryParams.companyName" placeholder="请输入企业名称" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
-      </div>
-    </transition>
-
-    <el-card shadow="hover">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:tenant:add']" type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:tenant:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()"
-              >修改</el-button
-            >
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:tenant:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">
-              删除
-            </el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:tenant:export']" type="warning" plain icon="Download" @click="handleExport">导出</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-if="userId === 1" type="success" plain icon="Refresh" @click="handleSyncTenantDict">同步租户字典</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-if="userId === 1" type="success" plain icon="Refresh" @click="handleSyncTenantConfig">同步租户参数配置</el-button>
-          </el-col>
-          <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
-        </el-row>
-      </template>
-
-      <el-table v-loading="loading" border :data="tenantList" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column v-if="false" label="id" align="center" prop="id" />
-        <el-table-column label="租户编号" align="center" prop="tenantId" />
-        <el-table-column label="联系人" align="center" prop="contactUserName" />
-        <el-table-column label="联系电话" align="center" prop="contactPhone" />
-        <el-table-column label="企业名称" align="center" prop="companyName" />
-        <el-table-column label="社会信用代码" align="center" prop="licenseNumber" />
-        <el-table-column label="过期时间" align="center" prop="expireTime" width="180">
-          <template #default="scope">
-            <span>{{ proxy.parseTime(scope.row.expireTime, '{y}-{m}-{d}') }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="租户状态" align="center" prop="status">
-          <template #default="scope">
-            <el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
-          </template>
-        </el-table-column>
-        <el-table-column width="150" label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
-          <template #default="scope">
-            <el-tooltip content="修改" placement="top">
-              <el-button v-hasPermi="['system:tenant:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>
-            </el-tooltip>
-            <el-tooltip content="同步套餐" placement="top">
-              <el-button v-hasPermi="['system:tenant:edit']" link type="primary" icon="Refresh" @click="handleSyncTenantPackage(scope.row)">
-              </el-button>
-            </el-tooltip>
-            <el-tooltip content="删除" placement="top">
-              <el-button v-hasPermi="['system:tenant:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
-            </el-tooltip>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
-    </el-card>
-    <!-- 添加或修改租户对话框 -->
-    <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body>
-      <el-form ref="tenantFormRef" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="企业名称" prop="companyName">
-          <el-input v-model="form.companyName" placeholder="请输入企业名称" />
-        </el-form-item>
-        <el-form-item label="联系人" prop="contactUserName">
-          <el-input v-model="form.contactUserName" placeholder="请输入联系人" />
-        </el-form-item>
-        <el-form-item label="联系电话" prop="contactPhone">
-          <el-input v-model="form.contactPhone" placeholder="请输入联系电话" />
-        </el-form-item>
-        <el-form-item v-if="!form.id" label="用户名" prop="username">
-          <el-input v-model="form.username" placeholder="请输入系统用户名" maxlength="30" />
-        </el-form-item>
-        <el-form-item v-if="!form.id" label="用户密码" prop="password">
-          <el-input v-model="form.password" type="password" placeholder="请输入系统用户密码" maxlength="20" />
-        </el-form-item>
-        <el-form-item label="租户套餐" prop="packageId">
-          <el-select v-model="form.packageId" :disabled="!!form.tenantId" placeholder="请选择租户套餐" clearable style="width: 100%">
-            <el-option v-for="item in packageList" :key="item.packageId" :label="item.packageName" :value="item.packageId" />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="过期时间" prop="expireTime">
-          <el-date-picker v-model="form.expireTime" clearable type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择过期时间">
-          </el-date-picker>
-        </el-form-item>
-        <el-form-item label="用户数量" prop="accountCount">
-          <el-input v-model="form.accountCount" placeholder="请输入用户数量" />
-        </el-form-item>
-        <el-form-item label="绑定域名" prop="domain">
-          <el-input v-model="form.domain" placeholder="请输入绑定域名" />
-        </el-form-item>
-        <el-form-item label="企业地址" prop="address">
-          <el-input v-model="form.address" placeholder="请输入企业地址" />
-        </el-form-item>
-        <el-form-item label="企业代码" prop="licenseNumber">
-          <el-input v-model="form.licenseNumber" placeholder="请输入统一社会信用代码" />
-        </el-form-item>
-        <el-form-item label="企业简介" prop="intro">
-          <el-input v-model="form.intro" type="textarea" placeholder="请输入企业简介" />
-        </el-form-item>
-        <el-form-item label="备注" prop="remark">
-          <el-input v-model="form.remark" placeholder="请输入备注" />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
-          <el-button @click="cancel">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup name="Tenant" lang="ts">
-import {
-  listTenant,
-  getTenant,
-  delTenant,
-  addTenant,
-  updateTenant,
-  changeTenantStatus,
-  syncTenantPackage,
-  syncTenantDict,
-  syncTenantConfig
-} from '@/api/system/tenant';
-import { selectTenantPackage } from '@/api/system/tenantPackage';
-import { useUserStore } from '@/store/modules/user';
-import { TenantForm, TenantQuery, TenantVO } from '@/api/system/tenant/types';
-import { TenantPkgVO } from '@/api/system/tenantPackage/types';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const userStore = useUserStore();
-const userId = ref(userStore.userId);
-const tenantList = ref<TenantVO[]>([]);
-const packageList = ref<TenantPkgVO[]>([]);
-const buttonLoading = ref(false);
-const loading = ref(true);
-const showSearch = ref(true);
-const ids = ref<Array<string | number>>([]);
-const single = ref(true);
-const multiple = ref(true);
-const total = ref(0);
-
-const queryFormRef = ref<ElFormInstance>();
-const tenantFormRef = ref<ElFormInstance>();
-
-const dialog = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-const initFormData: TenantForm = {
-  id: undefined,
-  tenantId: undefined,
-  contactUserName: '',
-  contactPhone: '',
-  username: '',
-  password: '',
-  companyName: '',
-  licenseNumber: '',
-  domain: '',
-  address: '',
-  intro: '',
-  remark: '',
-  packageId: '',
-  expireTime: '',
-  accountCount: 0,
-  status: '0'
-};
-const data = reactive<PageData<TenantForm, TenantQuery>>({
-  form: { ...initFormData },
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    tenantId: '',
-    contactUserName: '',
-    contactPhone: '',
-    companyName: ''
-  },
-  rules: {
-    id: [{ required: true, message: 'id不能为空', trigger: 'blur' }],
-    tenantId: [{ required: true, message: '租户编号不能为空', trigger: 'blur' }],
-    contactUserName: [{ required: true, message: '联系人不能为空', trigger: 'blur' }],
-    contactPhone: [{ required: true, message: '联系电话不能为空', trigger: 'blur' }],
-    companyName: [{ required: true, message: '企业名称不能为空', trigger: 'blur' }],
-    username: [
-      { required: true, message: '用户名不能为空', trigger: 'blur' },
-      { min: 2, max: 20, message: '用户名称长度必须介于 2 和 20 之间', trigger: 'blur' }
-    ],
-    password: [
-      { required: true, message: '密码不能为空', trigger: 'blur' },
-      { min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur' }
-    ]
-  }
-});
-
-const { queryParams, form, rules } = toRefs(data);
-
-/** 查询所有租户套餐 */
-const getTenantPackage = async () => {
-  const res = await selectTenantPackage();
-  packageList.value = res.data;
-};
-
-/** 查询租户列表 */
-const getList = async () => {
-  loading.value = true;
-  const res = await listTenant(queryParams.value);
-  tenantList.value = res.rows;
-  total.value = res.total;
-  loading.value = false;
-};
-
-// 租户套餐状态修改
-const handleStatusChange = async (row: TenantVO) => {
-  const text = row.status === '0' ? '启用' : '停用';
-  try {
-    await proxy?.$modal.confirm('确认要"' + text + '""' + row.companyName + '"租户吗?');
-    await changeTenantStatus(row.id, row.tenantId, row.status);
-    proxy?.$modal.msgSuccess(text + '成功');
-  } catch {
-    row.status = row.status === '0' ? '1' : '0';
-  }
-};
-
-// 取消按钮
-const cancel = () => {
-  reset();
-  dialog.visible = false;
-};
-
-// 表单重置
-const reset = () => {
-  form.value = { ...initFormData };
-  tenantFormRef.value?.resetFields();
-};
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.value.pageNum = 1;
-  getList();
-};
-
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  handleQuery();
-};
-
-// 多选框选中数据
-const handleSelectionChange = (selection: TenantVO[]) => {
-  ids.value = selection.map((item) => item.id);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
-};
-
-/** 新增按钮操作 */
-const handleAdd = () => {
-  reset();
-  getTenantPackage();
-  dialog.visible = true;
-  dialog.title = '添加租户';
-};
-
-/** 修改按钮操作 */
-const handleUpdate = async (row?: TenantVO) => {
-  reset();
-  await getTenantPackage();
-  const _id = row?.id || ids.value[0];
-  const res = await getTenant(_id);
-  Object.assign(form.value, res.data);
-  dialog.visible = true;
-  dialog.title = '修改租户';
-};
-
-/** 提交按钮 */
-const submitForm = () => {
-  tenantFormRef.value?.validate(async (valid: boolean) => {
-    if (valid) {
-      buttonLoading.value = true;
-      if (form.value.id) {
-        await updateTenant(form.value).finally(() => (buttonLoading.value = false));
-      } else {
-        await addTenant(form.value).finally(() => (buttonLoading.value = false));
-      }
-      proxy?.$modal.msgSuccess('操作成功');
-      dialog.visible = false;
-      await getList();
-    }
-  });
-};
-
-/** 删除按钮操作 */
-const handleDelete = async (row?: TenantVO) => {
-  const _ids = row?.id || ids.value;
-  await proxy?.$modal.confirm('是否确认删除租户编号为"' + _ids + '"的数据项?');
-  loading.value = true;
-  await delTenant(_ids).finally(() => (loading.value = false));
-  await getList();
-  proxy?.$modal.msgSuccess('删除成功');
-};
-
-/** 同步租户套餐按钮操作 */
-const handleSyncTenantPackage = async (row: TenantVO) => {
-  try {
-    await proxy?.$modal.confirm('是否确认同步租户套餐租户编号为"' + row.tenantId + '"的数据项?');
-    loading.value = true;
-    await syncTenantPackage(row.tenantId, row.packageId);
-    await getList();
-    proxy?.$modal.msgSuccess('同步成功');
-  } catch {
-    return;
-  } finally {
-    loading.value = false;
-  }
-};
-
-/** 导出按钮操作 */
-const handleExport = () => {
-  proxy?.download(
-    'system/tenant/export',
-    {
-      ...queryParams.value
-    },
-    `tenant_${new Date().getTime()}.xlsx`
-  );
-};
-
-/**同步租户字典*/
-const handleSyncTenantDict = async () => {
-  await proxy?.$modal.confirm('确认要同步所有租户字典吗?');
-  const res = await syncTenantDict();
-  proxy?.$modal.msgSuccess(res.msg);
-};
-
-/**同步租户参数配置*/
-const handleSyncTenantConfig = async () => {
-  await proxy?.$modal.confirm('确认要同步所有租户参数配置吗?');
-  const res = await syncTenantConfig();
-  proxy?.$modal.msgSuccess(res.msg);
-};
-
-onMounted(() => {
-  getList();
-});
-</script>

+ 0 - 329
src/views/system/tenantPackage/index.vue

@@ -1,329 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
-        <el-card shadow="hover">
-          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="套餐名称" prop="packageName">
-              <el-input v-model="queryParams.packageName" placeholder="请输入套餐名称" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
-      </div>
-    </transition>
-
-    <el-card shadow="hover">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:tenantPackage:add']" type="primary" plain icon="Plus" @click="handleAdd"> 新增 </el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:tenantPackage:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()">
-              修改
-            </el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:tenantPackage:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">
-              删除
-            </el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['system:tenantPackage:export']" type="warning" plain icon="Download" @click="handleExport">导出 </el-button>
-          </el-col>
-          <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
-        </el-row>
-      </template>
-
-      <el-table v-loading="loading" border :data="tenantPackageList" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column v-if="false" label="租户套餐id" align="center" prop="packageId" />
-        <el-table-column label="套餐名称" align="center" prop="packageName" />
-        <el-table-column label="备注" align="center" prop="remark" />
-        <el-table-column label="状态" align="center" prop="status">
-          <template #default="scope">
-            <el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @click="handleStatusChange(scope.row)"></el-switch>
-          </template>
-        </el-table-column>
-        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
-          <template #default="scope">
-            <el-tooltip content="修改" placement="top">
-              <el-button v-hasPermi="['system:tenantPackage:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>
-            </el-tooltip>
-            <el-tooltip content="删除" placement="top">
-              <el-button v-hasPermi="['system:tenantPackage:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
-            </el-tooltip>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
-    </el-card>
-
-    <!-- 添加或修改租户套餐对话框 -->
-    <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body>
-      <el-form ref="tenantPackageFormRef" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="套餐名称" prop="packageName">
-          <el-input v-model="form.packageName" placeholder="请输入套餐名称" />
-        </el-form-item>
-        <el-form-item label="关联菜单">
-          <el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox>
-          <el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选 </el-checkbox>
-          <el-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">父子联动 </el-checkbox>
-          <el-tree
-            ref="menuTreeRef"
-            class="tree-border"
-            :data="menuOptions"
-            show-checkbox
-            node-key="id"
-            :check-strictly="!form.menuCheckStrictly"
-            empty-text="加载中,请稍候"
-            :props="{ label: 'label', children: 'children' } as any"
-          ></el-tree>
-        </el-form-item>
-        <el-form-item label="备注" prop="remark">
-          <el-input v-model="form.remark" placeholder="请输入备注" />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
-          <el-button @click="cancel">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup name="TenantPackage" lang="ts">
-import {
-  listTenantPackage,
-  getTenantPackage,
-  delTenantPackage,
-  addTenantPackage,
-  updateTenantPackage,
-  changePackageStatus
-} from '@/api/system/tenantPackage';
-import { tenantPackageMenuTreeselect } from '@/api/system/menu';
-import { TenantPkgForm, TenantPkgQuery, TenantPkgVO } from '@/api/system/tenantPackage/types';
-import { MenuTreeOption } from '@/api/system/menu/types';
-import to from 'await-to-js';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const tenantPackageList = ref<TenantPkgVO[]>([]);
-const buttonLoading = ref(false);
-const loading = ref(true);
-const showSearch = ref(true);
-const ids = ref<Array<string | number>>([]);
-const single = ref(true);
-const multiple = ref(true);
-const total = ref(0);
-const menuExpand = ref(false);
-const menuNodeAll = ref(false);
-const menuOptions = ref<MenuTreeOption[]>([]);
-
-const menuTreeRef = ref<ElTreeInstance>();
-const queryFormRef = ref<ElFormInstance>();
-const tenantPackageFormRef = ref<ElFormInstance>();
-
-const dialog = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-const initFormData: TenantPkgForm = {
-  packageId: undefined,
-  packageName: '',
-  menuIds: '',
-  remark: '',
-  menuCheckStrictly: true
-};
-const data = reactive<PageData<TenantPkgForm, TenantPkgQuery>>({
-  form: { ...initFormData },
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    packageName: ''
-  },
-  rules: {
-    packageId: [{ required: true, message: '租户套餐id不能为空', trigger: 'blur' }],
-    packageName: [{ required: true, message: '套餐名称不能为空', trigger: 'blur' }]
-  }
-});
-
-const { queryParams, form, rules } = toRefs(data);
-
-// 所有菜单节点数据
-const getMenuAllCheckedKeys = (): any => {
-  // 目前被选中的菜单节点
-  const checkedKeys = menuTreeRef.value?.getCheckedKeys();
-  // 半选中的菜单节点
-  const halfCheckedKeys = menuTreeRef.value?.getHalfCheckedKeys();
-  if (halfCheckedKeys) {
-    checkedKeys?.unshift(...halfCheckedKeys);
-  }
-  return checkedKeys;
-};
-
-/** 根据租户套餐ID查询菜单树结构 */
-const getPackageMenuTreeselect = async (packageId: string | number) => {
-  const res = await tenantPackageMenuTreeselect(packageId);
-  menuOptions.value = res.data.menus;
-  return Promise.resolve(res);
-};
-
-/** 查询租户套餐列表 */
-const getList = async () => {
-  loading.value = true;
-  const res = await listTenantPackage(queryParams.value);
-  tenantPackageList.value = res.rows;
-  total.value = res.total;
-  loading.value = false;
-};
-
-// 租户套餐状态修改
-const handleStatusChange = async (row: TenantPkgVO) => {
-  const text = row.status === '0' ? '启用' : '停用';
-  const [err] = await to(proxy?.$modal.confirm('确认要"' + text + '""' + row.packageName + '"套餐吗?') as Promise<any>);
-  if (err) {
-    row.status = row.status === '0' ? '1' : '0';
-  } else {
-    await changePackageStatus(row.packageId, row.status);
-    proxy?.$modal.msgSuccess(text + '成功');
-  }
-};
-
-// 取消按钮
-const cancel = () => {
-  reset();
-  dialog.visible = false;
-};
-
-// 表单重置
-const reset = () => {
-  menuTreeRef.value?.setCheckedKeys([]);
-  menuExpand.value = false;
-  menuNodeAll.value = false;
-  form.value = { ...initFormData };
-  tenantPackageFormRef.value?.resetFields();
-};
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.value.pageNum = 1;
-  getList();
-};
-
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  handleQuery();
-};
-
-// 多选框选中数据
-const handleSelectionChange = (selection: TenantPkgVO[]) => {
-  ids.value = selection.map((item) => item.packageId);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
-};
-
-// 树权限(展开/折叠)
-const handleCheckedTreeExpand = (value: CheckboxValueType, type: string) => {
-  if (type == 'menu') {
-    const treeList = menuOptions.value;
-    for (let i = 0; i < treeList.length; i++) {
-      if (menuTreeRef.value) {
-        menuTreeRef.value.store.nodesMap[treeList[i].id].expanded = value as boolean;
-      }
-    }
-  }
-};
-
-// 树权限(全选/全不选)
-const handleCheckedTreeNodeAll = (value: CheckboxValueType, type: string) => {
-  if (type == 'menu') {
-    menuTreeRef.value?.setCheckedNodes(value ? (menuOptions.value as any) : []);
-  }
-};
-
-// 树权限(父子联动)
-const handleCheckedTreeConnect = (value: CheckboxValueType, type: string) => {
-  if (type == 'menu') {
-    form.value.menuCheckStrictly = value as boolean;
-  }
-};
-
-/** 新增按钮操作 */
-const handleAdd = async () => {
-  reset();
-  await getPackageMenuTreeselect(0);
-  dialog.visible = true;
-  dialog.title = '添加租户套餐';
-};
-
-/** 修改按钮操作 */
-const handleUpdate = async (row?: TenantPkgVO) => {
-  reset();
-  const _packageId = row?.packageId || ids.value[0];
-  const response = await getTenantPackage(_packageId);
-  form.value = response.data;
-  const res = await getPackageMenuTreeselect(_packageId);
-  dialog.visible = true;
-  dialog.title = '修改租户套餐';
-  res.data.checkedKeys.forEach((v) => {
-    nextTick(() => {
-      menuTreeRef.value?.setChecked(v, true, false);
-    });
-  });
-};
-
-/** 提交按钮 */
-const submitForm = () => {
-  tenantPackageFormRef.value?.validate(async (valid: boolean) => {
-    if (valid) {
-      buttonLoading.value = true;
-      form.value.menuIds = getMenuAllCheckedKeys();
-      if (form.value.packageId != null) {
-        await updateTenantPackage(form.value).finally(() => (buttonLoading.value = false));
-      } else {
-        await addTenantPackage(form.value).finally(() => (buttonLoading.value = false));
-      }
-      proxy?.$modal.msgSuccess('操作成功');
-      dialog.visible = false;
-      await getList();
-    }
-  });
-};
-
-/** 删除按钮操作 */
-const handleDelete = async (row?: TenantPkgVO) => {
-  const _packageIds = row?.packageId || ids.value;
-  await proxy?.$modal.confirm('是否确认删除租户套餐编号为"' + _packageIds + '"的数据项?').finally(() => {
-    loading.value = false;
-  });
-  await delTenantPackage(_packageIds);
-  loading.value = true;
-  await getList();
-  proxy?.$modal.msgSuccess('删除成功');
-};
-
-/** 导出按钮操作 */
-const handleExport = () => {
-  proxy?.download(
-    'system/tenant/package/export',
-    {
-      ...queryParams.value
-    },
-    `tenantPackage_${new Date().getTime()}.xlsx`
-  );
-};
-
-onMounted(() => {
-  getList();
-});
-</script>

+ 0 - 146
src/views/system/user/authRole.vue

@@ -1,146 +0,0 @@
-<template>
-  <div class="p-2">
-    <div class="panel">
-      <h4 class="panel-title">基本信息</h4>
-      <el-form :model="form" :inline="true">
-        <el-row :gutter="10">
-          <el-col :span="2.5">
-            <el-form-item label="用户昵称" prop="nickName">
-              <el-input v-model="form.nickName" disabled />
-            </el-form-item>
-          </el-col>
-          <el-col :span="2.5">
-            <el-form-item label="登录账号" prop="userName">
-              <el-input v-model="form.userName" disabled />
-            </el-form-item>
-          </el-col>
-        </el-row>
-      </el-form>
-    </div>
-    <div class="panel">
-      <h4 class="panel-title">角色信息</h4>
-      <div>
-        <el-table
-          ref="tableRef"
-          v-loading="loading"
-          border
-          :row-key="getRowKey"
-          :data="roles.slice((pageNum - 1) * pageSize, pageNum * pageSize)"
-          @row-click="clickRow"
-          @selection-change="handleSelectionChange"
-        >
-          <el-table-column label="序号" width="55" type="index" align="center">
-            <template #default="scope">
-              <span>{{ (pageNum - 1) * pageSize + scope.$index + 1 }}</span>
-            </template>
-          </el-table-column>
-          <el-table-column type="selection" :reserve-selection="true" :selectable="checkSelectable" width="55"></el-table-column>
-          <el-table-column label="角色编号" align="center" prop="roleId" />
-          <el-table-column label="角色名称" align="center" prop="roleName" />
-          <el-table-column label="权限字符" align="center" prop="roleKey" />
-          <el-table-column label="创建时间" align="center" prop="createTime" width="180">
-            <template #default="scope">
-              <span>{{ proxy.parseTime(scope.row.createTime) }}</span>
-            </template>
-          </el-table-column>
-        </el-table>
-        <pagination v-show="total > 0" v-model:page="pageNum" v-model:limit="pageSize" :total="total" />
-        <div style="text-align: center; margin-left: -120px; margin-top: 30px">
-          <el-button type="primary" @click="submitForm()">提交</el-button>
-          <el-button @click="close()">返回</el-button>
-        </div>
-        <div></div>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script setup name="AuthRole" lang="ts">
-import { RoleVO } from '@/api/system/role/types';
-import { getAuthRole, updateAuthRole } from '@/api/system/user';
-import { UserForm } from '@/api/system/user/types';
-import { RouteLocationNormalized } from 'vue-router';
-import { parseTime } from '@/utils/ruoyi';
-
-const route = useRoute();
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const loading = ref(true);
-const total = ref(0);
-const pageNum = ref(1);
-const pageSize = ref(10);
-const roleIds = ref<Array<string | number>>([]);
-const roles = ref<RoleVO[]>([]);
-const form = ref<Partial<UserForm>>({
-  nickName: undefined,
-  userName: '',
-  userId: undefined
-});
-
-const tableRef = ref<ElTableInstance>();
-
-/** 单击选中行数据 */
-const clickRow = (row: RoleVO) => {
-  if (checkSelectable(row)) {
-    row.flag = !row.flag;
-    tableRef.value?.toggleRowSelection(row, row.flag);
-  }
-};
-/** 多选框选中数据 */
-const handleSelectionChange = (selection: RoleVO[]) => {
-  roleIds.value = selection.map((item) => item.roleId);
-};
-/** 保存选中的数据编号 */
-const getRowKey = (row: RoleVO): string => {
-  return String(row.roleId);
-};
-/** 检查角色状态 */
-const checkSelectable = (row: RoleVO): boolean => {
-  return row.status === '0';
-};
-/** 关闭按钮 */
-const close = () => {
-  const obj: RouteLocationNormalized = {
-    fullPath: '',
-    hash: '',
-    matched: [],
-    meta: undefined,
-    name: undefined,
-    params: undefined,
-    query: undefined,
-    redirectedFrom: undefined,
-    path: '/system/user'
-  };
-  proxy?.$tab.closeOpenPage(obj);
-};
-/** 提交按钮 */
-const submitForm = async () => {
-  const userId = form.value.userId;
-  const rIds = roleIds.value.join(',');
-  await updateAuthRole({ userId: userId as string, roleIds: rIds });
-  proxy?.$modal.msgSuccess('授权成功');
-  close();
-};
-
-const getList = async () => {
-  const userId = route.params && route.params.userId;
-  if (userId) {
-    loading.value = true;
-    const res = await getAuthRole(userId as string);
-    Object.assign(form.value, res.data.user);
-    Object.assign(roles.value, res.data.roles);
-    total.value = roles.value.length;
-    await nextTick(() => {
-      roles.value.forEach((row) => {
-        if (row?.flag) {
-          tableRef.value?.toggleRowSelection(row, true);
-        }
-      });
-    });
-    loading.value = false;
-  }
-};
-onMounted(() => {
-  getList();
-});
-</script>

+ 0 - 679
src/views/system/user/index.vue

@@ -1,679 +0,0 @@
-<template>
-  <div class="p-2">
-    <el-row :gutter="20">
-      <!-- 部门树 -->
-      <el-col :lg="4" :xs="24" style="">
-        <el-card shadow="hover">
-          <el-input v-model="deptName" placeholder="请输入部门名称" prefix-icon="Search" clearable />
-          <el-tree
-            ref="deptTreeRef"
-            class="mt-2"
-            node-key="id"
-            :data="deptOptions"
-            :props="{ label: 'label', children: 'children' } as any"
-            :expand-on-click-node="false"
-            :filter-node-method="filterNode"
-            highlight-current
-            default-expand-all
-            @node-click="handleNodeClick"
-          />
-        </el-card>
-      </el-col>
-      <el-col :lg="20" :xs="24">
-        <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-          <div v-show="showSearch" class="mb-[10px]">
-            <el-card shadow="hover">
-              <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-                <el-form-item label="用户名称" prop="userName">
-                  <el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable @keyup.enter="handleQuery" />
-                </el-form-item>
-                <el-form-item label="用户昵称" prop="nickName">
-                  <el-input v-model="queryParams.nickName" placeholder="请输入用户昵称" clearable @keyup.enter="handleQuery" />
-                </el-form-item>
-                <el-form-item label="手机号码" prop="phonenumber">
-                  <el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable @keyup.enter="handleQuery" />
-                </el-form-item>
-
-                <el-form-item label="状态" prop="status">
-                  <el-select v-model="queryParams.status" placeholder="用户状态" clearable>
-                    <el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
-                  </el-select>
-                </el-form-item>
-                <el-form-item label="创建时间" style="width: 308px">
-                  <el-date-picker
-                    v-model="dateRange"
-                    value-format="YYYY-MM-DD HH:mm:ss"
-                    type="daterange"
-                    range-separator="-"
-                    start-placeholder="开始日期"
-                    end-placeholder="结束日期"
-                    :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
-                  ></el-date-picker>
-                </el-form-item>
-                <el-form-item>
-                  <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-                  <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-                </el-form-item>
-              </el-form>
-            </el-card>
-          </div>
-        </transition>
-
-        <el-card shadow="hover">
-          <template #header>
-            <el-row :gutter="10">
-              <el-col :span="1.5">
-                <el-button v-has-permi="['system:user:add']" type="primary" plain icon="Plus" @click="handleAdd()">新增</el-button>
-              </el-col>
-              <el-col :span="1.5">
-                <el-button v-has-permi="['system:user:edit']" type="success" plain :disabled="single" icon="Edit" @click="handleUpdate()">
-                  修改
-                </el-button>
-              </el-col>
-              <el-col :span="1.5">
-                <el-button v-has-permi="['system:user:remove']" type="danger" plain :disabled="multiple" icon="Delete" @click="handleDelete()">
-                  删除
-                </el-button>
-              </el-col>
-              <el-col :span="1.5">
-                <el-dropdown class="mt-[1px]">
-                  <el-button plain type="info">
-                    更多
-                    <el-icon class="el-icon--right"><arrow-down /></el-icon
-                  ></el-button>
-                  <template #dropdown>
-                    <el-dropdown-menu>
-                      <el-dropdown-item icon="Download" @click="importTemplate">下载模板</el-dropdown-item>
-                      <!-- 注意 由于el-dropdown-item标签是延迟加载的 所以v-has-permi自定义标签不生效 需要使用v-if调用方法执行 -->
-                      <el-dropdown-item v-if="checkPermi(['system:user:import'])" icon="Top" @click="handleImport">导入数据</el-dropdown-item>
-                      <el-dropdown-item v-if="checkPermi(['system:user:export'])" icon="Download" @click="handleExport">导出数据</el-dropdown-item>
-                    </el-dropdown-menu>
-                  </template>
-                </el-dropdown>
-              </el-col>
-              <right-toolbar v-model:show-search="showSearch" :columns="columns" :search="true" @query-table="getList"></right-toolbar>
-            </el-row>
-          </template>
-
-          <el-table v-loading="loading" border :data="userList" @selection-change="handleSelectionChange">
-            <el-table-column type="selection" width="50" align="center" />
-            <el-table-column v-if="columns[0].visible" key="userId" label="用户编号" align="center" prop="userId" />
-            <el-table-column v-if="columns[1].visible" key="userName" label="用户名称" align="center" prop="userName" :show-overflow-tooltip="true" />
-            <el-table-column v-if="columns[2].visible" key="nickName" label="用户昵称" align="center" prop="nickName" :show-overflow-tooltip="true" />
-            <el-table-column v-if="columns[3].visible" key="deptName" label="部门" align="center" prop="deptName" :show-overflow-tooltip="true" />
-            <el-table-column v-if="columns[4].visible" key="phonenumber" label="手机号码" align="center" prop="phonenumber" width="120" />
-            <el-table-column v-if="columns[5].visible" key="status" label="状态" align="center">
-              <template #default="scope">
-                <el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
-              </template>
-            </el-table-column>
-
-            <el-table-column v-if="columns[6].visible" label="创建时间" align="center" prop="createTime" width="160">
-              <template #default="scope">
-                <span>{{ scope.row.createTime }}</span>
-              </template>
-            </el-table-column>
-
-            <el-table-column label="操作" fixed="right" width="180" class-name="small-padding fixed-width">
-              <template #default="scope">
-                <el-tooltip v-if="scope.row.userId !== 1" content="修改" placement="top">
-                  <el-button v-hasPermi="['system:user:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>
-                </el-tooltip>
-                <el-tooltip v-if="scope.row.userId !== 1" content="删除" placement="top">
-                  <el-button v-hasPermi="['system:user:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
-                </el-tooltip>
-
-                <el-tooltip v-if="scope.row.userId !== 1" content="重置密码" placement="top">
-                  <el-button v-hasPermi="['system:user:resetPwd']" link type="primary" icon="Key" @click="handleResetPwd(scope.row)"></el-button>
-                </el-tooltip>
-
-                <el-tooltip v-if="scope.row.userId !== 1" content="分配角色" placement="top">
-                  <el-button v-hasPermi="['system:user:edit']" link type="primary" icon="CircleCheck" @click="handleAuthRole(scope.row)"></el-button>
-                </el-tooltip>
-              </template>
-            </el-table-column>
-          </el-table>
-
-          <pagination
-            v-show="total > 0"
-            v-model:page="queryParams.pageNum"
-            v-model:limit="queryParams.pageSize"
-            :total="total"
-            @pagination="getList"
-          />
-        </el-card>
-      </el-col>
-    </el-row>
-
-    <!-- 添加或修改用户配置对话框 -->
-    <el-dialog ref="formDialogRef" v-model="dialog.visible" :title="dialog.title" width="600px" append-to-body @close="closeDialog">
-      <el-form ref="userFormRef" :model="form" :rules="rules" label-width="80px">
-        <el-row>
-          <el-col :span="12">
-            <el-form-item label="用户昵称" prop="nickName">
-              <el-input v-model="form.nickName" placeholder="请输入用户昵称" maxlength="30" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12" v-if="form.userId == null || form.userId != useUserStore().userId">
-            <el-form-item label="归属部门" prop="deptId">
-              <el-tree-select
-                v-model="form.deptId"
-                :data="enabledDeptOptions"
-                :props="{ value: 'id', label: 'label', children: 'children' } as any"
-                value-key="id"
-                placeholder="请选择归属部门"
-                check-strictly
-                @change="handleDeptChange"
-              />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="12">
-            <el-form-item label="手机号码" prop="phonenumber">
-              <el-input v-model="form.phonenumber" placeholder="请输入手机号码" maxlength="11" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="邮箱" prop="email">
-              <el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="12">
-            <el-form-item v-if="form.userId == undefined" label="用户名称" prop="userName">
-              <el-input v-model="form.userName" placeholder="请输入用户名称" maxlength="30" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item v-if="form.userId == undefined" label="用户密码" prop="password">
-              <el-input v-model="form.password" placeholder="请输入用户密码" type="password" maxlength="20" show-password />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="12">
-            <el-form-item label="用户性别">
-              <el-select v-model="form.sex" placeholder="请选择">
-                <el-option v-for="dict in sys_user_sex" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
-              </el-select>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="状态">
-              <el-radio-group v-model="form.status">
-                <el-radio v-for="dict in sys_normal_disable" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
-              </el-radio-group>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="12" v-if="form.userId == null || form.userId != useUserStore().userId">
-            <el-form-item label="岗位">
-              <el-select v-model="form.postIds" multiple placeholder="请选择">
-                <el-option
-                  v-for="item in postOptions"
-                  :key="item.postId"
-                  :label="item.postName"
-                  :value="item.postId"
-                  :disabled="item.status == '1'"
-                ></el-option>
-              </el-select>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12" v-if="form.userId == null || form.userId != useUserStore().userId">
-            <el-form-item label="角色" prop="roleIds">
-              <el-select v-model="form.roleIds" filterable multiple placeholder="请选择">
-                <el-option
-                  v-for="item in roleOptions"
-                  :key="item.roleId"
-                  :label="item.roleName"
-                  :value="item.roleId"
-                  :disabled="item.status == '1'"
-                ></el-option>
-              </el-select>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="24">
-            <el-form-item label="备注">
-              <el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
-            </el-form-item>
-          </el-col>
-        </el-row>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button type="primary" @click="submitForm">确 定</el-button>
-          <el-button @click="cancel()">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
-
-    <!-- 用户导入对话框 -->
-    <el-dialog v-model="upload.open" :title="upload.title" width="400px" append-to-body>
-      <el-upload
-        ref="uploadRef"
-        :limit="1"
-        accept=".xlsx, .xls"
-        :headers="upload.headers"
-        :action="upload.url + '?updateSupport=' + upload.updateSupport"
-        :disabled="upload.isUploading"
-        :on-progress="handleFileUploadProgress"
-        :on-success="handleFileSuccess"
-        :auto-upload="false"
-        drag
-      >
-        <el-icon class="el-icon--upload">
-          <i-ep-upload-filled />
-        </el-icon>
-        <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
-        <template #tip>
-          <div class="text-center el-upload__tip">
-            <div class="el-upload__tip"><el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据</div>
-            <span>仅允许导入xls、xlsx格式文件。</span>
-            <el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" @click="importTemplate">下载模板</el-link>
-          </div>
-        </template>
-      </el-upload>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button type="primary" @click="submitFileForm">确 定</el-button>
-          <el-button @click="upload.open = false">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup name="User" lang="ts">
-import api from '@/api/system/user';
-import { UserForm, UserQuery, UserVO } from '@/api/system/user/types';
-import { DeptTreeVO, DeptVO } from '@/api/system/dept/types';
-import { RoleVO } from '@/api/system/role/types';
-import { PostVO } from '@/api/system/post/types';
-import { globalHeaders } from '@/utils/request';
-import { to } from 'await-to-js';
-import { optionselect } from '@/api/system/post';
-import { checkPermi } from '@/utils/permission';
-import { useUserStore } from '@/store/modules/user';
-
-const router = useRouter();
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { sys_normal_disable, sys_user_sex } = toRefs<any>(proxy?.useDict('sys_normal_disable', 'sys_user_sex'));
-const userList = ref<UserVO[]>();
-const loading = ref(true);
-const showSearch = ref(true);
-const ids = ref<Array<number | string>>([]);
-const single = ref(true);
-const multiple = ref(true);
-const total = ref(0);
-const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
-const deptName = ref('');
-const deptOptions = ref<DeptTreeVO[]>([]);
-const enabledDeptOptions = ref<DeptTreeVO[]>([]);
-const initPassword = ref<string>('');
-const postOptions = ref<PostVO[]>([]);
-const roleOptions = ref<RoleVO[]>([]);
-/*** 用户导入参数 */
-const upload = reactive<ImportOption>({
-  // 是否显示弹出层(用户导入)
-  open: false,
-  // 弹出层标题(用户导入)
-  title: '',
-  // 是否禁用上传
-  isUploading: false,
-  // 是否更新已经存在的用户数据
-  updateSupport: 0,
-  // 设置上传的请求头部
-  headers: globalHeaders(),
-  // 上传的地址
-  url: import.meta.env.VITE_APP_BASE_API + '/system/user/importData'
-});
-// 列显隐信息
-const columns = ref<FieldOption[]>([
-  { key: 0, label: `用户编号`, visible: false, children: [] },
-  { key: 1, label: `用户名称`, visible: true, children: [] },
-  { key: 2, label: `用户昵称`, visible: true, children: [] },
-  { key: 3, label: `部门`, visible: true, children: [] },
-  { key: 4, label: `手机号码`, visible: true, children: [] },
-  { key: 5, label: `状态`, visible: true, children: [] },
-  { key: 6, label: `创建时间`, visible: true, children: [] }
-]);
-
-const deptTreeRef = ref<ElTreeInstance>();
-const queryFormRef = ref<ElFormInstance>();
-const userFormRef = ref<ElFormInstance>();
-const uploadRef = ref<ElUploadInstance>();
-const formDialogRef = ref<ElDialogInstance>();
-
-const dialog = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-const initFormData: UserForm = {
-  userId: undefined,
-  deptId: undefined,
-  userName: '',
-  nickName: undefined,
-  password: '',
-  phonenumber: undefined,
-  email: undefined,
-  sex: undefined,
-  status: '0',
-  remark: '',
-  postIds: [],
-  roleIds: []
-};
-
-const initData: PageData<UserForm, UserQuery> = {
-  form: { ...initFormData },
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    userName: '',
-    phonenumber: '',
-    status: '',
-    deptId: '',
-    roleId: ''
-  },
-  rules: {
-    userName: [
-      { required: true, message: '用户名称不能为空', trigger: 'blur' },
-      {
-        min: 2,
-        max: 20,
-        message: '用户名称长度必须介于 2 和 20 之间',
-        trigger: 'blur'
-      }
-    ],
-    nickName: [{ required: true, message: '用户昵称不能为空', trigger: 'blur' }],
-    password: [
-      { required: true, message: '用户密码不能为空', trigger: 'blur' },
-      {
-        min: 5,
-        max: 20,
-        message: '用户密码长度必须介于 5 和 20 之间',
-        trigger: 'blur'
-      },
-      { pattern: /^[^<>"'|\\]+$/, message: '不能包含非法字符:< > " \' \\ |', trigger: 'blur' }
-    ],
-    email: [
-      {
-        type: 'email',
-        message: '请输入正确的邮箱地址',
-        trigger: ['blur', 'change']
-      }
-    ],
-    phonenumber: [
-      {
-        pattern: /^1[3456789][0-9]\d{8}$/,
-        message: '请输入正确的手机号码',
-        trigger: 'blur'
-      }
-    ],
-    roleIds: [{ required: true, message: '用户角色不能为空', trigger: 'blur' }]
-  }
-};
-const data = reactive<PageData<UserForm, UserQuery>>(initData);
-
-const { queryParams, form, rules } = toRefs<PageData<UserForm, UserQuery>>(data);
-
-/** 通过条件过滤节点  */
-const filterNode = (value: string, data: any) => {
-  if (!value) return true;
-  return data.label.indexOf(value) !== -1;
-};
-/** 根据名称筛选部门树 */
-watchEffect(
-  () => {
-    deptTreeRef.value?.filter(deptName.value);
-  },
-  {
-    flush: 'post' // watchEffect会在DOM挂载或者更新之前就会触发,此属性控制在DOM元素更新后运行
-  }
-);
-
-/** 查询用户列表 */
-const getList = async () => {
-  loading.value = true;
-  const res = await api.listUser(proxy?.addDateRange(queryParams.value, dateRange.value));
-  loading.value = false;
-  userList.value = res.rows;
-  total.value = res.total;
-};
-
-/** 查询部门下拉树结构 */
-const getDeptTree = async () => {
-  const res = await api.deptTreeSelect();
-  deptOptions.value = res.data;
-  enabledDeptOptions.value = filterDisabledDept(res.data);
-};
-
-/** 过滤禁用的部门 */
-const filterDisabledDept = (deptList: DeptTreeVO[]) => {
-  return deptList.filter((dept) => {
-    if (dept.disabled) {
-      return false;
-    }
-    if (dept.children && dept.children.length) {
-      dept.children = filterDisabledDept(dept.children);
-    }
-    return true;
-  });
-};
-
-/** 节点单击事件 */
-const handleNodeClick = (data: DeptVO) => {
-  queryParams.value.deptId = data.id;
-  handleQuery();
-};
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.value.pageNum = 1;
-  getList();
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  dateRange.value = ['', ''];
-  queryFormRef.value?.resetFields();
-  queryParams.value.pageNum = 1;
-  queryParams.value.deptId = undefined;
-  deptTreeRef.value?.setCurrentKey(undefined);
-  handleQuery();
-};
-
-/** 删除按钮操作 */
-const handleDelete = async (row?: UserVO) => {
-  const userIds = row?.userId || ids.value;
-  const [err] = await to(proxy?.$modal.confirm('是否确认删除用户编号为"' + userIds + '"的数据项?') as any);
-  if (!err) {
-    await api.delUser(userIds);
-    await getList();
-    proxy?.$modal.msgSuccess('删除成功');
-  }
-};
-
-/** 用户状态修改  */
-const handleStatusChange = async (row: UserVO) => {
-  const text = row.status === '0' ? '启用' : '停用';
-  try {
-    await proxy?.$modal.confirm('确认要"' + text + '""' + row.userName + '"用户吗?');
-    await api.changeUserStatus(row.userId, row.status);
-    proxy?.$modal.msgSuccess(text + '成功');
-  } catch (err) {
-    row.status = row.status === '0' ? '1' : '0';
-  }
-};
-/** 跳转角色分配 */
-const handleAuthRole = (row: UserVO) => {
-  const userId = row.userId;
-  router.push('/system/user-auth/role/' + userId);
-};
-
-/** 重置密码按钮操作 */
-const handleResetPwd = async (row: UserVO) => {
-  const [err, res] = await to(
-    ElMessageBox.prompt('请输入"' + row.userName + '"的新密码', '提示', {
-      confirmButtonText: '确定',
-      cancelButtonText: '取消',
-      closeOnClickModal: false,
-      inputPattern: /^.{5,20}$/,
-      inputErrorMessage: '用户密码长度必须介于 5 和 20 之间',
-      inputValidator: (value) => {
-        if (/<|>|"|'|\||\\/.test(value)) {
-          return '不能包含非法字符:< > " \' \\ |';
-        }
-      }
-    })
-  );
-  if (!err && res) {
-    await api.resetUserPwd(row.userId, res.value);
-    proxy?.$modal.msgSuccess('修改成功,新密码是:' + res.value);
-  }
-};
-
-/** 选择条数  */
-const handleSelectionChange = (selection: UserVO[]) => {
-  ids.value = selection.map((item) => item.userId);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
-};
-
-/** 导入按钮操作 */
-const handleImport = () => {
-  upload.title = '用户导入';
-  upload.open = true;
-};
-/** 导出按钮操作 */
-const handleExport = () => {
-  proxy?.download(
-    'system/user/export',
-    {
-      ...queryParams.value
-    },
-    `user_${new Date().getTime()}.xlsx`
-  );
-};
-/** 下载模板操作 */
-const importTemplate = () => {
-  proxy?.download('system/user/importTemplate', {}, `user_template_${new Date().getTime()}.xlsx`);
-};
-
-/**文件上传中处理 */
-const handleFileUploadProgress = () => {
-  upload.isUploading = true;
-};
-/** 文件上传成功处理 */
-const handleFileSuccess = (response: any, file: UploadFile) => {
-  upload.open = false;
-  upload.isUploading = false;
-  uploadRef.value?.handleRemove(file);
-  ElMessageBox.alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + '</div>', '导入结果', {
-    dangerouslyUseHTMLString: true
-  });
-  getList();
-};
-
-/** 提交上传文件 */
-function submitFileForm() {
-  uploadRef.value?.submit();
-}
-
-/** 重置操作表单 */
-const reset = () => {
-  form.value = { ...initFormData };
-  userFormRef.value?.resetFields();
-};
-/** 取消按钮 */
-const cancel = () => {
-  dialog.visible = false;
-  reset();
-};
-
-/** 新增按钮操作 */
-const handleAdd = async () => {
-  reset();
-  const { data } = await api.getUser();
-  dialog.visible = true;
-  dialog.title = '新增用户';
-  postOptions.value = data.posts;
-  roleOptions.value = data.roles;
-  form.value.password = initPassword.value.toString();
-};
-
-/** 修改按钮操作 */
-const handleUpdate = async (row?: UserForm) => {
-  reset();
-  const userId = row?.userId || ids.value[0];
-  const { data } = await api.getUser(userId);
-  dialog.visible = true;
-  dialog.title = '修改用户';
-  Object.assign(form.value, data.user);
-  postOptions.value = data.posts;
-  roleOptions.value = Array.from(
-    new Map([...data.roles, ...data.user.roles].map(role => [role.roleId, role])).values()
-  );
-  form.value.postIds = data.postIds;
-  form.value.roleIds = data.roleIds;
-  form.value.password = '';
-};
-
-/** 提交按钮 */
-const submitForm = () => {
-  userFormRef.value?.validate(async (valid: boolean) => {
-    if (valid) {
-      if (form.value.userId) {
-        // 自己编辑自己的情况下 不允许编辑角色部门岗位
-        if (form.value.userId == useUserStore().userId) {
-          form.value.roleIds = null;
-          form.value.deptId = null;
-          form.value.postIds = null;
-        }
-        await api.updateUser(form.value);
-      } else {
-        await api.addUser(form.value);
-      }
-      proxy?.$modal.msgSuccess('操作成功');
-      dialog.visible = false;
-      await getList();
-    }
-  });
-};
-
-/**
- * 关闭用户弹窗
- */
-const closeDialog = () => {
-  dialog.visible = false;
-  resetForm();
-};
-
-/**
- * 重置表单
- */
-const resetForm = () => {
-  userFormRef.value?.resetFields();
-  userFormRef.value?.clearValidate();
-
-  form.value.id = undefined;
-  form.value.status = '1';
-};
-onMounted(() => {
-  getDeptTree(); // 初始化部门数据
-  getList(); // 初始化列表数据
-  proxy?.getConfigKey('sys.user.initPassword').then((response) => {
-    initPassword.value = response.data;
-  });
-});
-
-async function handleDeptChange(value: number | string) {
-  const response = await optionselect(value);
-  postOptions.value = response.data;
-  form.value.postIds = [];
-}
-</script>

+ 0 - 122
src/views/system/user/profile/index.vue

@@ -1,122 +0,0 @@
-<template>
-  <div class="p-2">
-    <el-row :gutter="20">
-      <el-col :span="6" :xs="24">
-        <el-card class="box-card">
-          <template #header>
-            <div class="clearfix">
-              <span>个人信息</span>
-            </div>
-          </template>
-          <div>
-            <div class="text-center">
-              <userAvatar />
-            </div>
-            <ul class="list-group list-group-striped">
-              <li class="list-group-item">
-                <svg-icon icon-class="user" />用户名称
-                <div class="pull-right">{{ state.user.userName }}</div>
-              </li>
-              <li class="list-group-item">
-                <svg-icon icon-class="phone" />手机号码
-                <div class="pull-right">{{ state.user.phonenumber }}</div>
-              </li>
-              <li class="list-group-item">
-                <svg-icon icon-class="email" />用户邮箱
-                <div class="pull-right">{{ state.user.email }}</div>
-              </li>
-              <li class="list-group-item">
-                <svg-icon icon-class="tree" />所属部门
-                <div v-if="state.user.deptName" class="pull-right">{{ state.user.deptName }} / {{ state.postGroup }}</div>
-              </li>
-              <li class="list-group-item">
-                <svg-icon icon-class="peoples" />所属角色
-                <div class="pull-right">{{ state.roleGroup }}</div>
-              </li>
-              <li class="list-group-item">
-                <svg-icon icon-class="date" />创建日期
-                <div class="pull-right">{{ state.user.createTime }}</div>
-              </li>
-            </ul>
-          </div>
-        </el-card>
-      </el-col>
-      <el-col :span="18" :xs="24">
-        <el-card>
-          <template #header>
-            <div class="clearfix">
-              <span>基本资料</span>
-            </div>
-          </template>
-          <el-tabs v-model="activeTab">
-            <el-tab-pane label="基本资料" name="userinfo">
-              <userInfo :user="userForm" />
-            </el-tab-pane>
-            <el-tab-pane label="修改密码" name="resetPwd">
-              <resetPwd />
-            </el-tab-pane>
-            <el-tab-pane label="第三方应用" name="thirdParty">
-              <thirdParty :auths="state.auths" />
-            </el-tab-pane>
-            <el-tab-pane label="在线设备" name="onlineDevice">
-              <onlineDevice :devices="state.devices" />
-            </el-tab-pane>
-          </el-tabs>
-        </el-card>
-      </el-col>
-    </el-row>
-  </div>
-</template>
-
-<script setup name="Profile" lang="ts">
-import UserAvatar from './userAvatar.vue';
-import UserInfo from './userInfo.vue';
-import ResetPwd from './resetPwd.vue';
-import ThirdParty from './thirdParty.vue';
-import OnlineDevice from './onlineDevice.vue';
-import { getAuthList } from '@/api/system/social/auth';
-import { getUserProfile } from '@/api/system/user';
-import { getOnline } from '@/api/monitor/online';
-import { UserVO } from '@/api/system/user/types';
-
-const activeTab = ref('userinfo');
-interface State {
-  user: Partial<UserVO>;
-  roleGroup: string;
-  postGroup: string;
-  auths: any;
-  devices: any;
-}
-const state = ref<State>({
-  user: {},
-  roleGroup: '',
-  postGroup: '',
-  auths: [],
-  devices: []
-});
-
-const userForm = ref({});
-
-const getUser = async () => {
-  const res = await getUserProfile();
-  state.value.user = res.data.user;
-  userForm.value = { ...res.data.user };
-  state.value.roleGroup = res.data.roleGroup;
-  state.value.postGroup = res.data.postGroup;
-};
-
-const getAuths = async () => {
-  const res = await getAuthList();
-  state.value.auths = res.data;
-};
-const getOnlines = async () => {
-  const res = await getOnline();
-  state.value.devices = res.rows;
-};
-
-onMounted(() => {
-  getUser();
-  getAuths();
-  getOnlines();
-});
-</script>

+ 0 - 57
src/views/system/user/profile/onlineDevice.vue

@@ -1,57 +0,0 @@
-<template>
-  <div>
-    <el-table :data="devices" border style="width: 100%; height: 100%; font-size: 14px">
-      <el-table-column label="设备类型" align="center">
-        <template #default="scope">
-          <dict-tag :options="sys_device_type" :value="scope.row.deviceType" />
-        </template>
-      </el-table-column>
-      <el-table-column label="主机" align="center" prop="ipaddr" :show-overflow-tooltip="true" />
-      <el-table-column label="登录地点" align="center" prop="loginLocation" :show-overflow-tooltip="true" />
-      <el-table-column label="操作系统" align="center" prop="os" :show-overflow-tooltip="true" />
-      <el-table-column label="浏览器" align="center" prop="browser" :show-overflow-tooltip="true" />
-      <el-table-column label="登录时间" align="center" prop="loginTime" width="180">
-        <template #default="scope">
-          <span>{{ proxy.parseTime(scope.row.loginTime) }}</span>
-        </template>
-      </el-table-column>
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
-        <template #default="scope">
-          <el-tooltip content="删除" placement="top">
-            <el-button link type="primary" icon="Delete" @click="handldDelOnline(scope.row)"> </el-button>
-          </el-tooltip>
-        </template>
-      </el-table-column>
-    </el-table>
-  </div>
-</template>
-
-<script setup name="Online" lang="ts">
-import { delOnline } from '@/api/monitor/online';
-import { propTypes } from '@/utils/propTypes';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { sys_device_type } = toRefs<any>(proxy?.useDict('sys_device_type'));
-
-const props = defineProps({
-  devices: propTypes.any.isRequired
-});
-const devices = computed(() => props.devices);
-
-/** 删除按钮操作 */
-const handldDelOnline = (row: any) => {
-  ElMessageBox.confirm('删除设备后,在该设备登录需要重新进行验证')
-    .then(() => {
-      return delOnline(row.tokenId);
-    })
-    .then((res: any) => {
-      if (res.code === 200) {
-        proxy?.$modal.msgSuccess('删除成功');
-        proxy?.$tab.refreshPage();
-      } else {
-        proxy?.$modal.msgError(res.msg);
-      }
-    })
-    .catch(() => {});
-};
-</script>

+ 0 - 73
src/views/system/user/profile/resetPwd.vue

@@ -1,73 +0,0 @@
-<template>
-  <el-form ref="pwdRef" :model="user" :rules="rules" label-width="80px">
-    <el-form-item label="旧密码" prop="oldPassword">
-      <el-input v-model="user.oldPassword" placeholder="请输入旧密码" type="password" show-password />
-    </el-form-item>
-    <el-form-item label="新密码" prop="newPassword">
-      <el-input v-model="user.newPassword" placeholder="请输入新密码" type="password" show-password />
-    </el-form-item>
-    <el-form-item label="确认密码" prop="confirmPassword">
-      <el-input v-model="user.confirmPassword" placeholder="请确认新密码" type="password" show-password />
-    </el-form-item>
-    <el-form-item>
-      <el-button type="primary" @click="submit">保存</el-button>
-      <el-button type="danger" @click="close">关闭</el-button>
-    </el-form-item>
-  </el-form>
-</template>
-
-<script setup lang="ts">
-import { updateUserPwd } from '@/api/system/user';
-import type { ResetPwdForm } from '@/api/system/user/types';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const pwdRef = ref<ElFormInstance>();
-const user = ref<ResetPwdForm>({
-  oldPassword: '',
-  newPassword: '',
-  confirmPassword: ''
-});
-
-const equalToPassword = (rule: any, value: string, callback: any) => {
-  if (user.value.newPassword !== value) {
-    callback(new Error('两次输入的密码不一致'));
-  } else {
-    callback();
-  }
-};
-const rules = ref({
-  oldPassword: [{ required: true, message: '旧密码不能为空', trigger: 'blur' }],
-  newPassword: [
-    { required: true, message: '新密码不能为空', trigger: 'blur' },
-    {
-      min: 6,
-      max: 20,
-      message: '长度在 6 到 20 个字符',
-      trigger: 'blur'
-    },
-    { pattern: /^[^<>"'|\\]+$/, message: '不能包含非法字符:< > " \' \\ |', trigger: 'blur' }
-  ],
-  confirmPassword: [
-    { required: true, message: '确认密码不能为空', trigger: 'blur' },
-    {
-      required: true,
-      validator: equalToPassword,
-      trigger: 'blur'
-    }
-  ]
-});
-
-/** 提交按钮 */
-const submit = () => {
-  pwdRef.value?.validate(async (valid: boolean) => {
-    if (valid) {
-      await updateUserPwd(user.value.oldPassword, user.value.newPassword);
-      proxy?.$modal.msgSuccess('修改成功');
-    }
-  });
-};
-/** 关闭按钮 */
-const close = () => {
-  proxy?.$tab.closePage();
-};
-</script>

+ 0 - 145
src/views/system/user/profile/thirdParty.vue

@@ -1,145 +0,0 @@
-<template>
-  <div>
-    <el-table :data="auths" border style="width: 100%; height: 100%; font-size: 14px">
-      <el-table-column label="序号" width="50" type="index" />
-      <el-table-column label="绑定账号平台" width="140" align="center" prop="source" show-overflow-tooltip />
-      <el-table-column label="头像" width="120" align="center" prop="avatar">
-        <template #default="scope">
-          <img :src="scope.row.avatar" style="width: 45px; height: 45px" />
-        </template>
-      </el-table-column>
-      <el-table-column label="系统账号" width="180" align="center" prop="userName" :show-overflow-tooltip="true" />
-      <el-table-column label="绑定时间" width="180" align="center" prop="createTime" />
-      <el-table-column label="操作" width="80" align="center" class-name="small-padding fixed-width">
-        <template #default="scope">
-          <el-button size="small" type="text" @click="unlockAuth(scope.row)">解绑</el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-
-    <div id="git-user-binding">
-      <h4 class="provider-desc">你可以绑定以下第三方帐号</h4>
-      <div id="authlist" class="user-bind">
-        <a class="third-app" href="#" title="使用 微信 账号授权登录" @click="authUrl('wechat')">
-          <div class="git-other-login-icon">
-            <svg-icon icon-class="wechat" />
-          </div>
-          <span class="app-name">WeiXin</span>
-        </a>
-        <a class="third-app" href="#" title="使用 MaxKey 账号授权登录" @click="authUrl('maxkey')">
-          <div class="git-other-login-icon">
-            <svg-icon icon-class="maxkey" />
-          </div>
-          <span class="app-name">MaxKey</span>
-        </a>
-        <a class="third-app" href="#" title="使用 TopIam 账号授权登录" @click="authUrl('topiam')">
-          <div class="git-other-login-icon">
-            <svg-icon icon-class="topiam" />
-          </div>
-          <span class="app-name">TopIam</span>
-        </a>
-        <a class="third-app" href="#" title="使用 Gitee 账号授权登录" @click="authUrl('gitee')">
-          <div class="git-other-login-icon">
-            <svg-icon icon-class="gitee" />
-          </div>
-          <span class="app-name">Gitee</span>
-        </a>
-        <a class="third-app" href="#" title="使用 GitHub 账号授权登录" @click="authUrl('github')">
-          <div class="git-other-login-icon">
-            <svg-icon icon-class="github" />
-          </div>
-          <span class="app-name">Github</span>
-        </a>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-import { authUnlock, authRouterUrl } from '@/api/system/social/auth';
-import { propTypes } from '@/utils/propTypes';
-import { useUserStore } from '@/store/modules/user';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const props = defineProps({
-  auths: propTypes.any.isRequired
-});
-const auths = computed(() => props.auths);
-
-const unlockAuth = (row: any) => {
-  ElMessageBox.confirm('您确定要解除"' + row.source + '"的账号绑定吗?')
-    .then(() => {
-      return authUnlock(row.id);
-    })
-    .then((res: any) => {
-      if (res.code === 200) {
-        proxy?.$modal.msgSuccess('解绑成功');
-        proxy?.$tab.refreshPage();
-      } else {
-        proxy?.$modal.msgError(res.msg);
-      }
-    })
-    .catch(() => {});
-};
-
-const authUrl = (source: string) => {
-  authRouterUrl(source, useUserStore().tenantId).then((res: any) => {
-    if (res.code === 200) {
-      window.location.href = res.data;
-    } else {
-      proxy?.$modal.msgError(res.msg);
-    }
-  });
-};
-</script>
-
-<style lang="scss" scoped>
-.user-bind .third-app {
-  display: -webkit-box;
-  display: -ms-flexbox;
-  display: flex;
-  -webkit-box-orient: vertical;
-  -webkit-box-direction: normal;
-  -ms-flex-direction: column;
-  flex-direction: column;
-  -webkit-box-align: center;
-  -ms-flex-align: center;
-  align-items: center;
-  min-width: 80px;
-  float: left;
-}
-
-.user-bind {
-  font-size: 1rem;
-  text-align: start;
-  height: 50px;
-  margin-top: 10px;
-}
-
-.git-other-login-icon > img {
-  height: 32px;
-}
-
-a {
-  text-decoration: none;
-  cursor: pointer;
-  color: #005980;
-}
-
-.provider-desc {
-  font-family:
-    -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Liberation Sans',
-    'PingFang SC', 'Microsoft YaHei', 'Hiragino Sans GB', 'Wenquanyi Micro Hei', 'WenQuanYi Zen Hei', 'ST Heiti', SimHei, SimSun,
-    'WenQuanYi Zen Hei Sharp', sans-serif;
-  font-size: 1.071rem;
-}
-
-td > img {
-  height: 20px;
-  width: 20px;
-  display: inline-block;
-  border-radius: 50%;
-  margin-right: 5px;
-}
-</style>

+ 0 - 182
src/views/system/user/profile/userAvatar.vue

@@ -1,182 +0,0 @@
-<template>
-  <div class="user-info-head" @click="editCropper()">
-    <img :src="options.img" title="点击上传头像" class="img-circle img-lg" />
-    <el-dialog v-model="open" :title="title" width="800px" append-to-body @opened="modalOpened" @close="closeDialog">
-      <el-row>
-        <el-col :xs="24" :md="12" :style="{ height: '350px' }">
-          <vue-cropper
-            v-if="visible"
-            ref="cropper"
-            :img="options.img"
-            :info="true"
-            :auto-crop="options.autoCrop"
-            :auto-crop-width="options.autoCropWidth"
-            :auto-crop-height="options.autoCropHeight"
-            :fixed-box="options.fixedBox"
-            :output-type="options.outputType"
-            @real-time="realTime"
-          />
-        </el-col>
-        <el-col :xs="24" :md="12" :style="{ height: '350px' }">
-          <div class="avatar-upload-preview">
-            <img :src="options.previews.url" :style="options.previews.img" />
-          </div>
-        </el-col>
-      </el-row>
-      <br />
-      <el-row>
-        <el-col :lg="2" :md="2">
-          <el-upload action="#" :http-request="requestUpload" :show-file-list="false" :before-upload="beforeUpload">
-            <el-button>
-              选择
-              <el-icon class="el-icon--right">
-                <Upload />
-              </el-icon>
-            </el-button>
-          </el-upload>
-        </el-col>
-        <el-col :lg="{ span: 1, offset: 2 }" :md="2">
-          <el-button icon="Plus" @click="changeScale(1)"></el-button>
-        </el-col>
-        <el-col :lg="{ span: 1, offset: 1 }" :md="2">
-          <el-button icon="Minus" @click="changeScale(-1)"></el-button>
-        </el-col>
-        <el-col :lg="{ span: 1, offset: 1 }" :md="2">
-          <el-button icon="RefreshLeft" @click="rotateLeft()"></el-button>
-        </el-col>
-        <el-col :lg="{ span: 1, offset: 1 }" :md="2">
-          <el-button icon="RefreshRight" @click="rotateRight()"></el-button>
-        </el-col>
-        <el-col :lg="{ span: 2, offset: 6 }" :md="2">
-          <el-button type="primary" @click="uploadImg()">提 交</el-button>
-        </el-col>
-      </el-row>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup lang="ts">
-import 'vue-cropper/dist/index.css';
-import { VueCropper } from 'vue-cropper';
-import { uploadAvatar } from '@/api/system/user';
-import { useUserStore } from '@/store/modules/user';
-import { UploadRawFile } from 'element-plus';
-
-interface Options {
-  img: string | any; // 裁剪图片的地址
-  autoCrop: boolean; // 是否默认生成截图框
-  autoCropWidth: number; // 默认生成截图框宽度
-  autoCropHeight: number; // 默认生成截图框高度
-  fixedBox: boolean; // 固定截图框大小 不允许改变
-  fileName: string;
-  previews: any; // 预览数据
-  outputType: string;
-  visible: boolean;
-}
-
-const userStore = useUserStore();
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const open = ref(false);
-const visible = ref(false);
-const title = ref('修改头像');
-
-const cropper = ref<any>({});
-//图片裁剪数据
-const options = reactive<Options>({
-  img: userStore.avatar,
-  autoCrop: true,
-  autoCropWidth: 200,
-  autoCropHeight: 200,
-  fixedBox: true,
-  outputType: 'png',
-  fileName: '',
-  previews: {},
-  visible: false
-});
-
-/** 编辑头像 */
-const editCropper = () => {
-  open.value = true;
-};
-/** 打开弹出层结束时的回调 */
-const modalOpened = () => {
-  visible.value = true;
-};
-/** 覆盖默认上传行为 */
-const requestUpload = (): any => {};
-/** 向左旋转 */
-const rotateLeft = () => {
-  cropper.value.rotateLeft();
-};
-/** 向右旋转 */
-const rotateRight = () => {
-  cropper.value.rotateRight();
-};
-/** 图片缩放 */
-const changeScale = (num: number) => {
-  num = num || 1;
-  cropper.value.changeScale(num);
-};
-/** 上传预处理 */
-const beforeUpload = (file: UploadRawFile): any => {
-  if (file.type.indexOf('image/') == -1) {
-    proxy?.$modal.msgError('文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件。');
-  } else {
-    const reader = new FileReader();
-    reader.readAsDataURL(file);
-    reader.onload = () => {
-      options.img = reader.result;
-      options.fileName = file.name;
-    };
-  }
-};
-/** 上传图片 */
-const uploadImg = async () => {
-  cropper.value.getCropBlob(async (data: any) => {
-    const formData = new FormData();
-    formData.append('avatarfile', data, options.fileName);
-    const res = await uploadAvatar(formData);
-    open.value = false;
-    options.img = res.data.imgUrl;
-    userStore.setAvatar(options.img);
-    proxy?.$modal.msgSuccess('修改成功');
-    visible.value = false;
-  });
-};
-/** 实时预览 */
-const realTime = (data: any) => {
-  options.previews = data;
-};
-/** 关闭窗口 */
-const closeDialog = () => {
-  options.img = userStore.avatar;
-  options.visible = false;
-};
-</script>
-
-<style lang="scss" scoped>
-.user-info-head {
-  position: relative;
-  display: inline-block;
-  height: 120px;
-}
-
-.user-info-head:hover:after {
-  content: '+';
-  position: absolute;
-  left: 0;
-  right: 0;
-  top: 0;
-  bottom: 0;
-  color: #eee;
-  background: rgba(0, 0, 0, 0.5);
-  font-size: 24px;
-  font-style: normal;
-  -webkit-font-smoothing: antialiased;
-  -moz-osx-font-smoothing: grayscale;
-  cursor: pointer;
-  line-height: 110px;
-  border-radius: 50%;
-}
-</style>

+ 0 - 69
src/views/system/user/profile/userInfo.vue

@@ -1,69 +0,0 @@
-<template>
-  <el-form ref="userRef" :model="userForm" :rules="rules" label-width="80px">
-    <el-form-item label="用户昵称" prop="nickName">
-      <el-input v-model="userForm.nickName" maxlength="30" />
-    </el-form-item>
-    <el-form-item label="手机号码" prop="phonenumber">
-      <el-input v-model="userForm.phonenumber" maxlength="11" />
-    </el-form-item>
-    <el-form-item label="邮箱" prop="email">
-      <el-input v-model="userForm.email" maxlength="50" />
-    </el-form-item>
-    <el-form-item label="性别">
-      <el-radio-group v-model="userForm.sex">
-        <el-radio value="0">男</el-radio>
-        <el-radio value="1">女</el-radio>
-      </el-radio-group>
-    </el-form-item>
-    <el-form-item>
-      <el-button type="primary" @click="submit">保存</el-button>
-      <el-button type="danger" @click="close">关闭</el-button>
-    </el-form-item>
-  </el-form>
-</template>
-
-<script setup lang="ts">
-import { updateUserProfile } from '@/api/system/user';
-import { propTypes } from '@/utils/propTypes';
-
-const props = defineProps({
-  user: propTypes.any.isRequired
-});
-const userForm = computed(() => props.user);
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const userRef = ref<ElFormInstance>();
-const rule: ElFormRules = {
-  nickName: [{ required: true, message: '用户昵称不能为空', trigger: 'blur' }],
-  email: [
-    { required: true, message: '邮箱地址不能为空', trigger: 'blur' },
-    {
-      type: 'email',
-      message: '请输入正确的邮箱地址',
-      trigger: ['blur', 'change']
-    }
-  ],
-  phonenumber: [
-    {
-      required: true,
-      message: '手机号码不能为空',
-      trigger: 'blur'
-    },
-    { pattern: /^1[3456789][0-9]\d{8}$/, message: '请输入正确的手机号码', trigger: 'blur' }
-  ]
-};
-const rules = ref<ElFormRules>(rule);
-
-/** 提交按钮 */
-const submit = () => {
-  userRef.value?.validate(async (valid: boolean) => {
-    if (valid) {
-      await updateUserProfile(props.user);
-      proxy?.$modal.msgSuccess('修改成功');
-    }
-  });
-};
-/** 关闭按钮 */
-const close = () => {
-  proxy?.$tab.closePage();
-};
-</script>

+ 0 - 49
src/views/tool/gen/basicInfoForm.vue

@@ -1,49 +0,0 @@
-<template>
-  <el-form ref="basicInfoForm" :model="infoForm" :rules="rules" label-width="150px">
-    <el-row>
-      <el-col :span="12">
-        <el-form-item label="表名称" prop="tableName">
-          <el-input v-model="infoForm.tableName" placeholder="请输入仓库名称" />
-        </el-form-item>
-      </el-col>
-      <el-col :span="12">
-        <el-form-item label="表描述" prop="tableComment">
-          <el-input v-model="infoForm.tableComment" placeholder="请输入" />
-        </el-form-item>
-      </el-col>
-      <el-col :span="12">
-        <el-form-item label="实体类名称" prop="className">
-          <el-input v-model="infoForm.className" placeholder="请输入" />
-        </el-form-item>
-      </el-col>
-      <el-col :span="12">
-        <el-form-item label="作者" prop="functionAuthor">
-          <el-input v-model="infoForm.functionAuthor" placeholder="请输入" />
-        </el-form-item>
-      </el-col>
-      <el-col :span="24">
-        <el-form-item label="备注" prop="remark">
-          <el-input v-model="infoForm.remark" type="textarea" :rows="3"></el-input>
-        </el-form-item>
-      </el-col>
-    </el-row>
-  </el-form>
-</template>
-
-<script setup lang="ts">
-import { propTypes } from '@/utils/propTypes';
-
-const prop = defineProps({
-  info: propTypes.any.def({})
-});
-
-const infoForm = computed(() => prop.info);
-
-// 表单校验
-const rules = ref({
-  tableName: [{ required: true, message: '请输入表名称', trigger: 'blur' }],
-  tableComment: [{ required: true, message: '请输入表描述', trigger: 'blur' }],
-  className: [{ required: true, message: '请输入实体类名称', trigger: 'blur' }],
-  functionAuthor: [{ required: true, message: '请输入作者', trigger: 'blur' }]
-});
-</script>

+ 0 - 198
src/views/tool/gen/editTable.vue

@@ -1,198 +0,0 @@
-<template>
-  <el-card>
-    <el-tabs v-model="activeName">
-      <el-tab-pane label="基本信息" name="basic">
-        <basic-info-form ref="basicInfo" :info="info" />
-      </el-tab-pane>
-      <el-tab-pane label="字段信息" name="columnInfo">
-        <el-table ref="dragTable" border :data="columns" row-key="columnId" :max-height="tableHeight">
-          <el-table-column label="序号" type="index" min-width="5%" />
-          <el-table-column label="字段列名" prop="columnName" min-width="10%" :show-overflow-tooltip="true" />
-          <el-table-column label="字段描述" min-width="10%">
-            <template #default="scope">
-              <el-input v-model="scope.row.columnComment"></el-input>
-            </template>
-          </el-table-column>
-          <el-table-column label="物理类型" prop="columnType" min-width="10%" :show-overflow-tooltip="true" />
-          <el-table-column label="Java类型" min-width="11%">
-            <template #default="scope">
-              <el-select v-model="scope.row.javaType">
-                <el-option label="Long" value="Long" />
-                <el-option label="String" value="String" />
-                <el-option label="Integer" value="Integer" />
-                <el-option label="Double" value="Double" />
-                <el-option label="BigDecimal" value="BigDecimal" />
-                <el-option label="Date" value="Date" />
-                <el-option label="Boolean" value="Boolean" />
-              </el-select>
-            </template>
-          </el-table-column>
-          <el-table-column label="java属性" min-width="10%">
-            <template #default="scope">
-              <el-input v-model="scope.row.javaField"></el-input>
-            </template>
-          </el-table-column>
-
-          <el-table-column label="插入" min-width="5%">
-            <template #default="scope">
-              <el-checkbox v-model="scope.row.isInsert" true-value="1" false-value="0"></el-checkbox>
-            </template>
-          </el-table-column>
-          <el-table-column label="编辑" min-width="5%">
-            <template #default="scope">
-              <el-checkbox v-model="scope.row.isEdit" true-value="1" false-value="0"></el-checkbox>
-            </template>
-          </el-table-column>
-          <el-table-column label="列表" min-width="5%">
-            <template #default="scope">
-              <el-checkbox v-model="scope.row.isList" true-value="1" false-value="0"></el-checkbox>
-            </template>
-          </el-table-column>
-          <el-table-column label="查询" min-width="5%">
-            <template #default="scope">
-              <el-checkbox v-model="scope.row.isQuery" true-value="1" false-value="0"></el-checkbox>
-            </template>
-          </el-table-column>
-          <el-table-column label="查询方式" min-width="10%">
-            <template #default="scope">
-              <el-select v-model="scope.row.queryType">
-                <el-option label="=" value="EQ" />
-                <el-option label="!=" value="NE" />
-                <el-option label=">" value="GT" />
-                <el-option label=">=" value="GE" />
-                <el-option label="<" value="LT" />
-                <el-option label="<=" value="LE" />
-                <el-option label="LIKE" value="LIKE" />
-                <el-option label="BETWEEN" value="BETWEEN" />
-              </el-select>
-            </template>
-          </el-table-column>
-          <el-table-column label="必填" min-width="5%">
-            <template #default="scope">
-              <el-checkbox v-model="scope.row.isRequired" true-value="1" false-value="0"></el-checkbox>
-            </template>
-          </el-table-column>
-          <el-table-column label="显示类型" min-width="12%">
-            <template #default="scope">
-              <el-select v-model="scope.row.htmlType">
-                <el-option label="文本框" value="input" />
-                <el-option label="文本域" value="textarea" />
-                <el-option label="下拉框" value="select" />
-                <el-option label="单选框" value="radio" />
-                <el-option label="复选框" value="checkbox" />
-                <el-option label="日期控件" value="datetime" />
-                <el-option label="图片上传" value="imageUpload" />
-                <el-option label="文件上传" value="fileUpload" />
-                <el-option label="富文本控件" value="editor" />
-              </el-select>
-            </template>
-          </el-table-column>
-          <el-table-column label="字典类型" min-width="12%">
-            <template #default="scope">
-              <el-select v-model="scope.row.dictType" clearable filterable placeholder="请选择" value-on-clear="">
-                <el-option v-for="dict in dictOptions" :key="dict.dictType" :label="dict.dictName" :value="dict.dictType">
-                  <span style="float: left">{{ dict.dictName }}</span>
-                  <span style="float: right; color: #8492a6; font-size: 13px">{{ dict.dictType }}</span>
-                </el-option>
-              </el-select>
-            </template>
-          </el-table-column>
-        </el-table>
-      </el-tab-pane>
-      <el-tab-pane label="生成信息" name="genInfo">
-        <gen-info-form ref="genInfo" :info="info" :tables="tables" />
-      </el-tab-pane>
-    </el-tabs>
-    <el-form label-width="100px">
-      <div style="text-align: center; margin-left: -100px; margin-top: 10px">
-        <el-button type="primary" @click="submitForm()">提交</el-button>
-        <el-button @click="close()">返回</el-button>
-      </div>
-    </el-form>
-  </el-card>
-</template>
-
-<script setup name="GenEdit" lang="ts">
-import { getGenTable, updateGenTable } from '@/api/tool/gen';
-import { DbColumnVO, DbTableVO } from '@/api/tool/gen/types';
-import { optionselect as getDictOptionselect } from '@/api/system/dict/type';
-import { DictTypeVO } from '@/api/system/dict/type/types';
-import BasicInfoForm from './basicInfoForm.vue';
-import GenInfoForm from './genInfoForm.vue';
-import { RouteLocationNormalized } from 'vue-router';
-
-const route = useRoute();
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const activeName = ref('columnInfo');
-const tableHeight = ref(document.documentElement.scrollHeight - 245 + 'px');
-const tables = ref<DbTableVO[]>([]);
-const columns = ref<DbColumnVO[]>([]);
-const dictOptions = ref<DictTypeVO[]>([]);
-const info = ref<Partial<DbTableVO>>({});
-
-const basicInfo = ref<InstanceType<typeof BasicInfoForm>>();
-const genInfo = ref<InstanceType<typeof GenInfoForm>>();
-
-/** 提交按钮 */
-const submitForm = () => {
-  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('表单校验未通过,请重新检查提交内容');
-    }
-  });
-};
-const getFormPromise = (form: any) => {
-  return new Promise((resolve) => {
-    form.validate((res: any) => {
-      resolve(res);
-    });
-  });
-};
-const close = () => {
-  const obj: RouteLocationNormalized = {
-    path: '/tool/gen',
-    fullPath: '',
-    hash: '',
-    matched: [],
-    meta: undefined,
-    name: undefined,
-    params: undefined,
-    redirectedFrom: undefined,
-    query: { t: Date.now().toString(), 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);
-    columns.value = res.data.rows;
-    info.value = res.data.info;
-    tables.value = res.data.tables;
-    /** 查询字典下拉列表 */
-    const response = await getDictOptionselect();
-    dictOptions.value = response.data;
-  }
-})();
-</script>

+ 0 - 294
src/views/tool/gen/genInfoForm.vue

@@ -1,294 +0,0 @@
-<template>
-  <el-form ref="genInfoForm" :model="infoForm" :rules="rules" label-width="150px">
-    <el-row>
-      <el-col :span="12">
-        <el-form-item prop="tplCategory">
-          <template #label>生成模板</template>
-          <el-select v-model="infoForm.tplCategory" @change="tplSelectChange">
-            <el-option label="单表(增删改查)" value="crud" />
-            <el-option label="树表(增删改查)" value="tree" />
-          </el-select>
-        </el-form-item>
-      </el-col>
-
-      <el-col :span="12">
-        <el-form-item prop="packageName">
-          <template #label>
-            生成包路径
-            <el-tooltip content="生成在哪个java包下,例如 com.ruoyi.system" placement="top">
-              <el-icon><question-filled /></el-icon>
-            </el-tooltip>
-          </template>
-          <el-input v-model="infoForm.packageName" />
-        </el-form-item>
-      </el-col>
-
-      <el-col :span="12">
-        <el-form-item prop="moduleName">
-          <template #label>
-            生成模块名
-            <el-tooltip content="可理解为子系统名,例如 system" placement="top">
-              <el-icon><question-filled /></el-icon>
-            </el-tooltip>
-          </template>
-          <el-input v-model="infoForm.moduleName" />
-        </el-form-item>
-      </el-col>
-
-      <el-col :span="12">
-        <el-form-item prop="businessName">
-          <template #label>
-            生成业务名
-            <el-tooltip content="可理解为功能英文名,例如 user" placement="top">
-              <el-icon><question-filled /></el-icon>
-            </el-tooltip>
-          </template>
-          <el-input v-model="infoForm.businessName" />
-        </el-form-item>
-      </el-col>
-
-      <el-col :span="12">
-        <el-form-item prop="functionName">
-          <template #label>
-            生成功能名
-            <el-tooltip content="用作类描述,例如 用户" placement="top">
-              <el-icon><question-filled /></el-icon>
-            </el-tooltip>
-          </template>
-          <el-input v-model="infoForm.functionName" />
-        </el-form-item>
-      </el-col>
-
-      <el-col :span="12">
-        <el-form-item>
-          <template #label>
-            上级菜单
-            <el-tooltip content="分配到指定菜单下,例如 系统管理" placement="top">
-              <el-icon><question-filled /></el-icon>
-            </el-tooltip>
-          </template>
-          <el-tree-select
-            v-model="infoForm.parentMenuId"
-            :data="menuOptions"
-            :props="{ value: 'menuId', label: 'menuName', children: 'children' } as any"
-            value-key="menuId"
-            node-key="menuId"
-            placeholder="选择上级菜单"
-            check-strictly
-            filterable
-            clearable
-            highlight-current
-          />
-        </el-form-item>
-      </el-col>
-
-      <el-col :span="12">
-        <el-form-item prop="genType">
-          <template #label>
-            生成代码方式
-            <el-tooltip content="默认为zip压缩包下载,也可以自定义生成路径" placement="top">
-              <el-icon><question-filled /></el-icon>
-            </el-tooltip>
-          </template>
-          <el-radio v-model="infoForm.genType" value="0">zip压缩包</el-radio>
-          <el-radio v-model="infoForm.genType" value="1">自定义路径</el-radio>
-        </el-form-item>
-      </el-col>
-
-      <el-col v-if="infoForm.genType == '1'" :span="24">
-        <el-form-item prop="genPath">
-          <template #label>
-            自定义路径
-            <el-tooltip content="填写磁盘绝对路径,若不填写,则生成到当前Web项目下" placement="top">
-              <el-icon><question-filled /></el-icon>
-            </el-tooltip>
-          </template>
-          <el-input v-model="infoForm.genPath">
-            <template #append>
-              <el-dropdown>
-                <el-button type="primary">
-                  最近路径快速选择
-                  <i class="el-icon-arrow-down el-icon--right"></i>
-                </el-button>
-                <template #dropdown>
-                  <el-dropdown-menu>
-                    <el-dropdown-item @click="infoForm.genPath = '/'">恢复默认的生成基础路径</el-dropdown-item>
-                  </el-dropdown-menu>
-                </template>
-              </el-dropdown>
-            </template>
-          </el-input>
-        </el-form-item>
-      </el-col>
-    </el-row>
-
-    <template v-if="info.tplCategory == 'tree'">
-      <h4 class="form-header">其他信息</h4>
-      <el-row v-show="info.tplCategory == 'tree'">
-        <el-col :span="12">
-          <el-form-item>
-            <template #label>
-              树编码字段
-              <el-tooltip content="树显示的编码字段名, 如:dept_id" placement="top">
-                <el-icon><question-filled /></el-icon>
-              </el-tooltip>
-            </template>
-            <el-select v-model="infoForm.treeCode" placeholder="请选择">
-              <el-option
-                v-for="(column, index) in info.columns"
-                :key="index"
-                :label="column.columnName + ':' + column.columnComment"
-                :value="column.columnName"
-              ></el-option>
-            </el-select>
-          </el-form-item>
-        </el-col>
-        <el-col :span="12">
-          <el-form-item>
-            <template #label>
-              树父编码字段
-              <el-tooltip content="树显示的父编码字段名, 如:parent_Id" placement="top">
-                <el-icon><question-filled /></el-icon>
-              </el-tooltip>
-            </template>
-            <el-select v-model="infoForm.treeParentCode" placeholder="请选择">
-              <el-option
-                v-for="(column, index) in infoForm.columns"
-                :key="index"
-                :label="column.columnName + ':' + column.columnComment"
-                :value="column.columnName"
-              ></el-option>
-            </el-select>
-          </el-form-item>
-        </el-col>
-        <el-col :span="12">
-          <el-form-item>
-            <template #label>
-              树名称字段
-              <el-tooltip content="树节点的显示名称字段名, 如:dept_name" placement="top">
-                <el-icon><question-filled /></el-icon>
-              </el-tooltip>
-            </template>
-            <el-select v-model="infoForm.treeName" placeholder="请选择">
-              <el-option
-                v-for="(column, index) in info.columns"
-                :key="index"
-                :label="column.columnName + ':' + column.columnComment"
-                :value="column.columnName"
-              ></el-option>
-            </el-select>
-          </el-form-item>
-        </el-col>
-      </el-row>
-    </template>
-
-    <template v-if="info.tplCategory == 'sub'">
-      <h4 class="form-header">关联信息</h4>
-      <el-row>
-        <el-col :span="12">
-          <el-form-item>
-            <template #label>
-              关联子表的表名
-              <el-tooltip content="关联子表的表名, 如:sys_user" placement="top">
-                <el-icon><question-filled /></el-icon>
-              </el-tooltip>
-            </template>
-            <el-select v-model="infoForm.subTableName" placeholder="请选择" @change="subSelectChange">
-              <el-option v-for="(t, index) in table" :key="index" :label="t.tableName + ':' + t.tableComment" :value="t.tableName"></el-option>
-            </el-select>
-          </el-form-item>
-        </el-col>
-        <el-col :span="12">
-          <el-form-item>
-            <template #label>
-              子表关联的外键名
-              <el-tooltip content="子表关联的外键名, 如:user_id" placement="top">
-                <el-icon><question-filled /></el-icon>
-              </el-tooltip>
-            </template>
-            <el-select v-model="infoForm.subTableFkName" placeholder="请选择">
-              <el-option
-                v-for="(column, index) in subColumns"
-                :key="index"
-                :label="column.columnName + ':' + column.columnComment"
-                :value="column.columnName"
-              ></el-option>
-            </el-select>
-          </el-form-item>
-        </el-col>
-      </el-row>
-    </template>
-  </el-form>
-</template>
-
-<script setup lang="ts">
-import { listMenu } from '@/api/system/menu';
-import { propTypes } from '@/utils/propTypes';
-
-interface MenuOptionsType {
-  menuId: number | string;
-  menuName: string;
-  children?: MenuOptionsType[];
-}
-const { proxy } = getCurrentInstance();
-
-const subColumns = ref<any>([]);
-const menuOptions = ref<Array<MenuOptionsType>>([]);
-
-const props = defineProps({
-  info: propTypes.any.isRequired,
-  tables: propTypes.any.isRequired
-});
-
-const infoForm = computed(() => props.info);
-
-const table = computed(() => props.tables);
-
-// 表单校验
-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' }]
-});
-const subSelectChange = () => {
-  infoForm.value.subTableFkName = '';
-};
-const tplSelectChange = (value: string) => {
-  if (value !== 'sub') {
-    infoForm.value.subTableName = '';
-    infoForm.value.subTableFkName = '';
-  }
-};
-const setSubTableColumns = (value: string) => {
-  table.value.forEach((item: any) => {
-    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');
-
-  if (data) {
-    menuOptions.value = data;
-  }
-};
-
-watch(
-  () => props.info.subTableName,
-  (val) => {
-    setSubTableColumns(val);
-  }
-);
-
-onMounted(() => {
-  getMenuTreeselect();
-});
-</script>

+ 0 - 122
src/views/tool/gen/importTable.vue

@@ -1,122 +0,0 @@
-<template>
-  <!-- 导入表 -->
-  <el-dialog v-model="visible" title="导入表" width="1100px" top="5vh" append-to-body>
-    <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-      <el-form-item label="数据源" prop="dataName">
-        <el-select v-model="queryParams.dataName" filterable placeholder="请选择/输入数据源名称">
-          <el-option v-for="item in dataNameList" :key="item" :label="item" :value="item"> </el-option>
-        </el-select>
-      </el-form-item>
-      <el-form-item label="表名称" prop="tableName">
-        <el-input v-model="queryParams.tableName" placeholder="请输入表名称" clearable @keyup.enter="handleQuery" />
-      </el-form-item>
-      <el-form-item label="表描述" prop="tableComment">
-        <el-input v-model="queryParams.tableComment" placeholder="请输入表描述" clearable @keyup.enter="handleQuery" />
-      </el-form-item>
-      <el-form-item>
-        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-      </el-form-item>
-    </el-form>
-    <el-row>
-      <el-table ref="tableRef" border :data="dbTableList" height="260px" @row-click="clickRow" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55"></el-table-column>
-        <el-table-column prop="tableName" label="表名称" :show-overflow-tooltip="true"></el-table-column>
-        <el-table-column prop="tableComment" label="表描述" :show-overflow-tooltip="true"></el-table-column>
-        <el-table-column prop="createTime" label="创建时间"></el-table-column>
-        <el-table-column prop="updateTime" label="更新时间"></el-table-column>
-      </el-table>
-      <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
-    </el-row>
-    <template #footer>
-      <div class="dialog-footer">
-        <el-button type="primary" @click="handleImportTable">确 定</el-button>
-        <el-button @click="visible = false">取 消</el-button>
-      </div>
-    </template>
-  </el-dialog>
-</template>
-
-<script setup lang="ts">
-import { listDbTable, importTable, getDataNames } from '@/api/tool/gen';
-import { DbTableQuery, DbTableVO } from '@/api/tool/gen/types';
-
-const total = ref(0);
-const visible = ref(false);
-const tables = ref<Array<string>>([]);
-const dbTableList = ref<Array<DbTableVO>>([]);
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const tableRef = ref<ElTableInstance>();
-const queryFormRef = ref<ElFormInstance>();
-
-const queryParams = reactive<DbTableQuery>({
-  pageNum: 1,
-  pageSize: 10,
-  dataName: '',
-  tableName: '',
-  tableComment: ''
-});
-const dataNameList = ref<Array<string>>([]);
-
-const emit = defineEmits(['ok']);
-
-/** 查询参数列表 */
-const show = (dataName: string) => {
-  getDataNames().then((res) => {
-    if (res.code == 200) {
-      dataNameList.value = res.data;
-      if (dataName) {
-        queryParams.dataName = dataName;
-      } else {
-        queryParams.dataName = dataNameList.value[0];
-      }
-      getList();
-      visible.value = true;
-    }
-  });
-};
-/** 单击选择行 */
-const clickRow = (row: DbTableVO) => {
-  // ele bug
-  tableRef.value?.toggleRowSelection(row, false);
-};
-/** 多选框选中数据 */
-const handleSelectionChange = (selection: DbTableVO[]) => {
-  tables.value = selection.map((item) => item.tableName);
-};
-/** 查询表数据 */
-const getList = async () => {
-  const res = await listDbTable(queryParams);
-  dbTableList.value = res.rows;
-  total.value = res.total;
-};
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.pageNum = 1;
-  getList();
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  handleQuery();
-};
-/** 导入按钮操作 */
-const handleImportTable = async () => {
-  const tableNames = tables.value.join(',');
-  if (tableNames == '') {
-    proxy?.$modal.msgError('请选择要导入的表');
-    return;
-  }
-  const res = await importTable({ tables: tableNames, dataName: queryParams.dataName });
-  proxy?.$modal.msgSuccess(res.msg);
-  if (res.code === 200) {
-    visible.value = false;
-    emit('ok');
-  }
-};
-
-defineExpose({
-  show
-});
-</script>

+ 0 - 259
src/views/tool/gen/index.vue

@@ -1,259 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
-        <el-card shadow="hover">
-          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="数据源" prop="dataName">
-              <el-select v-model="queryParams.dataName" filterable clearable placeholder="请选择/输入数据源名称">
-                <el-option key="" label="全部" value="" />
-                <el-option v-for="item in dataNameList" :key="item" :label="item" :value="item"> </el-option>
-              </el-select>
-            </el-form-item>
-            <el-form-item label="表名称" prop="tableName">
-              <el-input v-model="queryParams.tableName" placeholder="请输入表名称" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="表描述" prop="tableComment">
-              <el-input v-model="queryParams.tableComment" placeholder="请输入表描述" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="创建时间" style="width: 308px">
-              <el-date-picker
-                v-model="dateRange"
-                value-format="YYYY-MM-DD"
-                type="daterange"
-                range-separator="-"
-                start-placeholder="开始日期"
-                end-placeholder="结束日期"
-              ></el-date-picker>
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
-      </div>
-    </transition>
-
-    <el-card shadow="hover">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['tool:gen:code']" type="primary" plain icon="Download" @click="handleGenTable()">生成</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['tool:gen:import']" type="info" plain icon="Upload" @click="openImportTable">导入</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['tool:gen:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleEditTable()">修改</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['tool:gen:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">
-              删除
-            </el-button>
-          </el-col>
-          <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
-        </el-row>
-      </template>
-
-      <el-table v-loading="loading" border :data="tableList" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" align="center" width="55"></el-table-column>
-        <el-table-column label="序号" type="index" width="50" align="center">
-          <template #default="scope">
-            <span>{{ (queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1 }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="数据源" align="center" prop="dataName" :show-overflow-tooltip="true" />
-        <el-table-column label="表名称" align="center" prop="tableName" :show-overflow-tooltip="true" />
-        <el-table-column label="表描述" align="center" prop="tableComment" :show-overflow-tooltip="true" />
-        <el-table-column label="实体" align="center" prop="className" :show-overflow-tooltip="true" />
-        <el-table-column label="创建时间" align="center" prop="createTime" width="160" />
-        <el-table-column label="更新时间" align="center" prop="updateTime" width="160" />
-        <el-table-column label="操作" align="center" width="330" class-name="small-padding fixed-width">
-          <template #default="scope">
-            <el-tooltip content="预览" placement="top">
-              <el-button v-hasPermi="['tool:gen:preview']" link type="primary" icon="View" @click="handlePreview(scope.row)"></el-button>
-            </el-tooltip>
-            <el-tooltip content="编辑" placement="top">
-              <el-button v-hasPermi="['tool:gen:edit']" link type="primary" icon="Edit" @click="handleEditTable(scope.row)"></el-button>
-            </el-tooltip>
-            <el-tooltip content="删除" placement="top">
-              <el-button v-hasPermi="['tool:gen:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
-            </el-tooltip>
-            <el-tooltip content="同步" placement="top">
-              <el-button v-hasPermi="['tool:gen:edit']" link type="primary" icon="Refresh" @click="handleSynchDb(scope.row)"></el-button>
-            </el-tooltip>
-            <el-tooltip content="生成代码" placement="top">
-              <el-button v-hasPermi="['tool:gen:code']" link type="primary" icon="Download" @click="handleGenTable(scope.row)"></el-button>
-            </el-tooltip>
-          </template>
-        </el-table-column>
-      </el-table>
-      <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
-    </el-card>
-
-    <!-- 预览界面 -->
-    <el-dialog v-model="dialog.visible" :title="dialog.title" width="80%" top="5vh" append-to-body class="scrollbar">
-      <el-tabs v-model="preview.activeName">
-        <el-tab-pane
-          v-for="(value, key) in preview.data"
-          :key="value"
-          :label="key.substring(key.lastIndexOf('/') + 1, key.indexOf('.vm'))"
-          :name="key.substring(key.lastIndexOf('/') + 1, key.indexOf('.vm'))"
-        >
-          <el-link v-copyText="value" v-copyText:callback="copyTextSuccess" :underline="false" icon="DocumentCopy" style="float: right">
-            &nbsp;复制
-          </el-link>
-          <highlightjs :code="value" />
-        </el-tab-pane>
-      </el-tabs>
-    </el-dialog>
-    <import-table ref="importRef" @ok="handleQuery" />
-  </div>
-</template>
-
-<script setup name="Gen" lang="ts">
-import { delTable, genCode, getDataNames, listTable, previewTable, synchDb } from '@/api/tool/gen';
-import { TableQuery, TableVO } from '@/api/tool/gen/types';
-import router from '@/router';
-import ImportTable from './importTable.vue';
-
-const route = useRoute();
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const tableList = ref<TableVO[]>([]);
-const loading = ref(true);
-const showSearch = ref(true);
-const ids = ref<Array<string | number>>([]);
-const single = ref(true);
-const multiple = ref(true);
-const total = ref(0);
-const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
-const uniqueId = ref('');
-const dataNameList = ref<Array<string>>([]);
-
-const queryFormRef = ref<ElFormInstance>();
-const importRef = ref<InstanceType<typeof ImportTable>>();
-
-const queryParams = ref<TableQuery>({
-  pageNum: 1,
-  pageSize: 10,
-  tableName: '',
-  tableComment: '',
-  dataName: ''
-});
-
-const preview = ref<{
-  data: Record<string, string>;
-  activeName: string;
-}>({
-  data: {},
-  activeName: 'domain.java'
-});
-const dialog = reactive<DialogOption>({
-  visible: false,
-  title: '代码预览'
-});
-
-/** 查询多数据源名称 */
-const getDataNameList = async () => {
-  const res = await getDataNames();
-  dataNameList.value = res.data;
-};
-
-/** 查询表集合 */
-const getList = async () => {
-  loading.value = true;
-  const res = await listTable(proxy?.addDateRange(queryParams.value, dateRange.value));
-  tableList.value = res.rows;
-  total.value = res.total;
-  loading.value = false;
-};
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.value.pageNum = 1;
-  getList();
-};
-/** 生成代码操作 */
-const handleGenTable = async (row?: TableVO) => {
-  const tbIds = row?.tableId || ids.value;
-  if (tbIds == '') {
-    proxy?.$modal.msgError('请选择要生成的数据');
-    return;
-  }
-  if (row?.genType === '1') {
-    await genCode(row.tableId);
-    proxy?.$modal.msgSuccess('成功生成到自定义路径:' + row.genPath);
-  } else {
-    proxy?.$download.zip('/tool/gen/batchGenCode?tableIdStr=' + tbIds, 'ruoyi.zip');
-  }
-};
-/** 同步数据库操作 */
-const handleSynchDb = async (row: TableVO) => {
-  const tableId = row.tableId;
-  await proxy?.$modal.confirm('确认要强制同步"' + row.tableName + '"表结构吗?');
-  await synchDb(tableId);
-  proxy?.$modal.msgSuccess('同步成功');
-};
-/** 打开导入表弹窗 */
-const openImportTable = () => {
-  importRef.value?.show(queryParams.value.dataName);
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  dateRange.value = ['', ''];
-  queryFormRef.value?.resetFields();
-  handleQuery();
-};
-/** 预览按钮 */
-const handlePreview = async (row: TableVO) => {
-  const res = await previewTable(row.tableId);
-  preview.value.data = res.data;
-  dialog.visible = true;
-  preview.value.activeName = 'domain.java';
-};
-/** 复制代码成功 */
-const copyTextSuccess = () => {
-  proxy?.$modal.msgSuccess('复制成功');
-};
-// 多选框选中数据
-const handleSelectionChange = (selection: TableVO[]) => {
-  ids.value = selection.map((item) => item.tableId);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
-};
-/** 修改按钮操作 */
-const handleEditTable = (row?: TableVO) => {
-  const tableId = row?.tableId || ids.value[0];
-  router.push({ path: '/tool/gen-edit/index/' + tableId, query: { pageNum: queryParams.value.pageNum } });
-};
-/** 删除按钮操作 */
-const handleDelete = async (row?: TableVO) => {
-  const tableIds = row?.tableId || ids.value;
-  await proxy?.$modal.confirm('是否确认删除表编号为"' + tableIds + '"的数据项?');
-  await delTable(tableIds);
-  await getList();
-  proxy?.$modal.msgSuccess('删除成功');
-};
-
-onMounted(() => {
-  const time = route.query.t;
-  if (time != null && time != uniqueId.value) {
-    uniqueId.value = time as string;
-    queryParams.value.pageNum = Number(route.query.pageNum);
-    dateRange.value = ['', ''];
-    queryFormRef.value?.resetFields();
-  }
-  getList();
-  getDataNameList();
-});
-</script>
-
-<style lang="scss" scoped>
-.el-tab-pane {
-  background-color: #282c34;
-  .el-link {
-    color: #fff;
-  }
-}
-</style>

+ 0 - 254
src/views/workflow/category/index.vue

@@ -1,254 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="search">
-        <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-          <el-form-item label="分类名称" prop="categoryName">
-            <el-input v-model="queryParams.categoryName" placeholder="请输入分类名称" clearable @keyup.enter="handleQuery" />
-          </el-form-item>
-          <el-form-item>
-            <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-            <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-          </el-form-item>
-        </el-form>
-      </div>
-    </transition>
-
-    <el-card shadow="never">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button type="primary" plain icon="Plus" @click="handleAdd()" v-hasPermi="['workflow:category:add']">新增</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="info" plain icon="Sort" @click="handleToggleExpandAll">展开/折叠</el-button>
-          </el-col>
-          <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-        </el-row>
-      </template>
-      <el-table
-        ref="categoryTableRef"
-        v-loading="loading"
-        :data="categoryList"
-        row-key="categoryId"
-        border
-        :default-expand-all="isExpandAll"
-        :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
-      >
-        <el-table-column label="分类名称" prop="categoryName" width="260" />
-        <el-table-column label="显示顺序" align="center" prop="orderNum" width="200" />
-        <el-table-column label="创建时间" align="center" prop="createTime" width="180" />
-        <el-table-column label="操作" fixed="right" align="center" class-name="small-padding fixed-width">
-          <template #default="scope">
-            <el-tooltip content="修改" placement="top">
-              <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['workflow:category:edit']" />
-            </el-tooltip>
-            <el-tooltip content="新增" placement="top">
-              <el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['workflow:category:add']" />
-            </el-tooltip>
-            <el-tooltip content="删除" placement="top">
-              <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['workflow:category:remove']" />
-            </el-tooltip>
-          </template>
-        </el-table-column>
-      </el-table>
-    </el-card>
-    <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
-      <el-form ref="categoryFormRef" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="上级分类" prop="parentId">
-          <el-tree-select
-            v-model="form.parentId"
-            :data="categoryOptions"
-            :props="{ value: 'categoryId', label: 'categoryName', children: 'children' } as any"
-            value-key="categoryId"
-            placeholder="请选择上级分类"
-            check-strictly
-          />
-        </el-form-item>
-        <el-row :gutter="20">
-          <el-col :span="12">
-            <el-form-item label="分类名称" prop="categoryName">
-              <el-input v-model="form.categoryName" placeholder="请输入分类名称" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="排序" prop="orderNum">
-              <el-input-number v-model="form.orderNum" controls-position="right" :min="0" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
-          <el-button @click="cancel">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup name="Category" lang="ts">
-import { listCategory, getCategory, delCategory, addCategory, updateCategory } from '@/api/workflow/category';
-import { CategoryVO, CategoryQuery, CategoryForm } from '@/api/workflow/category/types';
-
-type CategoryOption = {
-  categoryId: number;
-  categoryName: string;
-  children?: CategoryOption[];
-};
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const categoryList = ref<CategoryVO[]>([]);
-const categoryOptions = ref<CategoryOption[]>([]);
-const buttonLoading = ref(false);
-const showSearch = ref(true);
-const isExpandAll = ref(true);
-const loading = ref(false);
-
-const queryFormRef = ref<ElFormInstance>();
-const categoryFormRef = ref<ElFormInstance>();
-const categoryTableRef = ref<ElTableInstance>();
-
-const dialog = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-const initFormData: CategoryForm = {
-  categoryId: undefined,
-  categoryName: '',
-  parentId: undefined,
-  orderNum: 0
-};
-
-const data = reactive<PageData<CategoryForm, CategoryQuery>>({
-  form: { ...initFormData },
-  queryParams: {
-    categoryName: undefined
-  },
-  rules: {
-    categoryId: [{ required: true, message: '流程分类ID不能为空', trigger: 'blur' }],
-    parentId: [{ required: true, message: '请选择上级分类', trigger: 'change' }],
-    categoryName: [{ required: true, message: '请输入分类名称', trigger: 'blur' }]
-  }
-});
-
-const { queryParams, form, rules } = toRefs(data);
-
-/** 查询流程分类列表 */
-const getList = async () => {
-  loading.value = true;
-  const res = await listCategory(queryParams.value);
-  const data = proxy?.handleTree<CategoryVO>(res.data, 'categoryId', 'parentId');
-  if (data) {
-    categoryList.value = data;
-    loading.value = false;
-  }
-};
-
-/** 查询流程分类下拉树结构 */
-const getTreeselect = async () => {
-  const res = await listCategory();
-  categoryOptions.value = [];
-  // 处理树形数据
-  const data = proxy?.handleTree<CategoryOption>(res.data, 'categoryId', 'parentId');
-  if (data) {
-    categoryOptions.value = data; // 将处理后的树形数据赋值
-  }
-};
-
-// 取消按钮
-const cancel = () => {
-  reset();
-  dialog.visible = false;
-};
-
-// 表单重置
-const reset = () => {
-  form.value = { ...initFormData };
-  categoryFormRef.value?.resetFields();
-};
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  getList();
-};
-
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  handleQuery();
-};
-
-/** 新增按钮操作 */
-const handleAdd = (row?: CategoryVO) => {
-  reset();
-  getTreeselect();
-  if (row?.categoryId) {
-    form.value.parentId = row.categoryId;
-  } else {
-    form.value.parentId = undefined;
-  }
-  dialog.visible = true;
-  dialog.title = '添加流程分类';
-};
-
-/** 展开/折叠操作 */
-const handleToggleExpandAll = () => {
-  isExpandAll.value = !isExpandAll.value;
-  toggleExpandAll(categoryList.value, isExpandAll.value);
-};
-
-/** 展开/折叠操作 */
-const toggleExpandAll = (data: CategoryVO[], status: boolean) => {
-  data.forEach((item) => {
-    categoryTableRef.value?.toggleRowExpansion(item, status);
-    if (item.children && item.children.length > 0) toggleExpandAll(item.children, status);
-  });
-};
-
-/** 修改按钮操作 */
-const handleUpdate = async (row: CategoryVO) => {
-  reset();
-  await getTreeselect();
-  if (row != null) {
-    form.value.parentId = row.parentId;
-  }
-  const res = await getCategory(row.categoryId);
-  Object.assign(form.value, res.data);
-  dialog.visible = true;
-  dialog.title = '修改流程分类';
-};
-
-/** 提交按钮 */
-const submitForm = () => {
-  categoryFormRef.value?.validate(async (valid: boolean) => {
-    if (valid) {
-      buttonLoading.value = true;
-      if (form.value.categoryId) {
-        await updateCategory(form.value).finally(() => (buttonLoading.value = false));
-      } else {
-        await addCategory(form.value).finally(() => (buttonLoading.value = false));
-      }
-      proxy?.$modal.msgSuccess('操作成功');
-      dialog.visible = false;
-      getList();
-    }
-  });
-};
-
-/** 删除按钮操作 */
-const handleDelete = async (row: CategoryVO) => {
-  await proxy?.$modal.confirm('是否确认删除"' + row.categoryName + '"的分类?');
-  loading.value = true;
-  await delCategory(row.categoryId).finally(() => (loading.value = false));
-  await getList();
-  proxy?.$modal.msgSuccess('删除成功');
-};
-
-onMounted(() => {
-  getList();
-});
-</script>

+ 0 - 236
src/views/workflow/leave/index.vue

@@ -1,236 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="search">
-        <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-          <el-form-item label="请假天数" prop="startLeaveDays">
-            <el-input v-model="queryParams.startLeaveDays" placeholder="请输入请假天数" clearable @keyup.enter="handleQuery" />
-          </el-form-item>
-          <el-form-item prop="endLeaveDays"> 至 </el-form-item>
-          <el-form-item prop="endLeaveDays">
-            <el-input v-model="queryParams.endLeaveDays" placeholder="请输入请假天数" clearable @keyup.enter="handleQuery" />
-          </el-form-item>
-          <el-form-item>
-            <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-            <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-          </el-form-item>
-        </el-form>
-      </div>
-    </transition>
-
-    <el-card shadow="never">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['workflow:leave:add']" type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button v-hasPermi="['workflow:leave:export']" type="warning" plain icon="Download" @click="handleExport">导出</el-button>
-          </el-col>
-          <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
-        </el-row>
-      </template>
-
-      <el-table v-loading="loading" border :data="leaveList" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column v-if="false" label="主键" align="center" prop="id" />
-        <el-table-column label="请假类型" align="center">
-          <template #default="scope">
-            <el-tag>{{ options.find((e) => e.value === scope.row.leaveType)?.label }}</el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column label="开始时间" align="center" prop="startDate">
-          <template #default="scope">
-            <span>{{ proxy.parseTime(scope.row.startDate, '{y}-{m}-{d}') }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="结束时间" align="center" prop="endDate">
-          <template #default="scope">
-            <span>{{ proxy.parseTime(scope.row.endDate, '{y}-{m}-{d}') }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="请假天数" align="center" prop="leaveDays" />
-        <el-table-column label="请假原因" align="center" prop="remark" />
-        <el-table-column align="center" label="流程状态" min-width="70">
-          <template #default="scope">
-            <dict-tag :options="wf_business_status" :value="scope.row.status"></dict-tag>
-          </template>
-        </el-table-column>
-        <el-table-column label="操作" align="center" width="162">
-          <template #default="scope">
-            <el-row :gutter="10" class="mb8">
-              <el-col :span="1.5" v-if="scope.row.status === 'draft' || scope.row.status === 'cancel' || scope.row.status === 'back'">
-                <el-button v-hasPermi="['workflow:leave:edit']" size="small" type="primary" icon="Edit" @click="handleUpdate(scope.row)"
-                  >修改</el-button
-                >
-              </el-col>
-              <el-col :span="1.5" v-if="scope.row.status === 'draft' || scope.row.status === 'cancel' || scope.row.status === 'back'">
-                <el-button v-hasPermi="['workflow:leave:remove']" size="small" type="primary" icon="Delete" @click="handleDelete(scope.row)"
-                  >删除</el-button
-                >
-              </el-col>
-            </el-row>
-            <el-row :gutter="10" class="mb8">
-              <el-col :span="1.5">
-                <el-button type="primary" size="small" icon="View" @click="handleView(scope.row)">查看</el-button>
-              </el-col>
-              <el-col :span="1.5" v-if="scope.row.status === 'waiting'">
-                <el-button size="small" type="primary" icon="Notification" @click="handleCancelProcessApply(scope.row.id)">撤销</el-button>
-              </el-col>
-            </el-row>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
-    </el-card>
-  </div>
-</template>
-
-<script setup name="Leave" lang="ts">
-import { delLeave, listLeave } from '@/api/workflow/leave';
-import { cancelProcessApply } from '@/api/workflow/instance';
-import { LeaveForm, LeaveQuery, LeaveVO } from '@/api/workflow/leave/types';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status'));
-const leaveList = ref<LeaveVO[]>([]);
-const loading = ref(true);
-const showSearch = ref(true);
-const ids = ref<Array<string | number>>([]);
-const single = ref(true);
-const multiple = ref(true);
-const total = ref(0);
-const options = [
-  {
-    value: '1',
-    label: '事假'
-  },
-  {
-    value: '2',
-    label: '调休'
-  },
-  {
-    value: '3',
-    label: '病假'
-  },
-  {
-    value: '4',
-    label: '婚假'
-  }
-];
-
-const queryFormRef = ref<ElFormInstance>();
-
-const data = reactive<PageData<LeaveForm, LeaveQuery>>({
-  form: {},
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    startLeaveDays: undefined,
-    endLeaveDays: undefined
-  },
-  rules: {}
-});
-
-const { queryParams } = toRefs(data);
-
-/** 查询请假列表 */
-const getList = async () => {
-  loading.value = true;
-  const res = await listLeave(queryParams.value);
-  leaveList.value = res.rows;
-  total.value = res.total;
-  loading.value = false;
-};
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.value.pageNum = 1;
-  getList();
-};
-
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  handleQuery();
-};
-
-/** 多选框选中数据 */
-const handleSelectionChange = (selection: LeaveVO[]) => {
-  ids.value = selection.map((item) => item.id);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
-};
-
-/** 新增按钮操作 */
-const handleAdd = () => {
-  proxy.$tab.closePage(proxy.$route);
-  proxy.$router.push({
-    path: `/workflow/leaveEdit/index`,
-    query: {
-      type: 'add'
-    }
-  });
-};
-
-/** 修改按钮操作 */
-const handleUpdate = (row?: LeaveVO) => {
-  proxy.$tab.closePage(proxy.$route);
-  proxy.$router.push({
-    path: `/workflow/leaveEdit/index`,
-    query: {
-      id: row.id,
-      type: 'update'
-    }
-  });
-};
-
-/** 查看按钮操作 */
-const handleView = (row?: LeaveVO) => {
-  proxy.$tab.closePage(proxy.$route);
-  proxy.$router.push({
-    path: `/workflow/leaveEdit/index`,
-    query: {
-      id: row.id,
-      type: 'view'
-    }
-  });
-};
-
-/** 删除按钮操作 */
-const handleDelete = async (row?: LeaveVO) => {
-  const _ids = row?.id || ids.value;
-  await proxy?.$modal.confirm('是否确认删除请假编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
-  await delLeave(_ids);
-  proxy?.$modal.msgSuccess('删除成功');
-  await getList();
-};
-
-/** 导出按钮操作 */
-const handleExport = () => {
-  proxy?.download(
-    'workflow/leave/export',
-    {
-      ...queryParams.value
-    },
-    `leave_${new Date().getTime()}.xlsx`
-  );
-};
-
-/** 撤销按钮操作 */
-const handleCancelProcessApply = async (id: string) => {
-  await proxy?.$modal.confirm('是否确认撤销当前单据?');
-  loading.value = true;
-  const data = {
-    businessId: id,
-    message: '申请人撤销流程!'
-  };
-  await cancelProcessApply(data).finally(() => (loading.value = false));
-  await getList();
-  proxy?.$modal.msgSuccess('撤销成功');
-};
-onMounted(() => {
-  getList();
-});
-</script>

+ 0 - 286
src/views/workflow/leave/leaveEdit.vue

@@ -1,286 +0,0 @@
-<template>
-  <div class="p-2">
-    <el-card shadow="never">
-      <!-- mode用于直接后端发起流程 不同接口实现方式可查看具体后端代码 -->
-      <!-- 默认前端发起 前端发起更多样性 比如可以选审批人 选抄送人 上传附件等等 后端发起需要用户自行编写代码传这些参数 -->
-      <approvalButton
-        @submitForm="submitForm"
-        @approvalVerifyOpen="approvalVerifyOpen"
-        @handleApprovalRecord="handleApprovalRecord"
-        :buttonLoading="buttonLoading"
-        :id="form.id"
-        :status="form.status"
-        :pageType="routeParams.type"
-        :mode="false"
-      />
-    </el-card>
-    <el-card shadow="never" style="height: 78vh; overflow-y: auto">
-      <el-form ref="leaveFormRef" v-loading="loading" :disabled="routeParams.type === 'view'" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="流程定义" v-if="routeParams.type === 'add'">
-          <el-select v-model="flowCode" placeholder="选择流程定义" style="width: 100%">
-            <el-option v-for="item in flowCodeOptions" :key="item.value" :label="item.label" :value="item.value" />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="请假类型" prop="leaveType">
-          <el-select v-model="form.leaveType" placeholder="请选择请假类型" style="width: 100%">
-            <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="请假时间" required>
-          <el-date-picker
-            v-model="leaveTime"
-            value-format="YYYY-MM-DD HH:mm:ss"
-            type="daterange"
-            range-separator="To"
-            start-placeholder="开始时间"
-            end-placeholder="结束时间"
-            :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
-            @change="changeLeaveTime()"
-          />
-        </el-form-item>
-        <el-form-item label="请假天数" prop="leaveDays">
-          <el-input v-model="form.leaveDays" disabled type="number" placeholder="请输入请假天数" />
-        </el-form-item>
-        <el-form-item label="请假原因" prop="remark">
-          <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="请输入请假原因" />
-        </el-form-item>
-      </el-form>
-    </el-card>
-    <!-- 提交组件 -->
-    <submitVerify ref="submitVerifyRef" :task-variables="taskVariables" @submit-callback="submitCallback" />
-    <!-- 审批记录 -->
-    <approvalRecord ref="approvalRecordRef" />
-  </div>
-</template>
-
-<script setup name="Leave" lang="ts">
-import { addLeave, getLeave, submitAndFlowStart, updateLeave } from '@/api/workflow/leave';
-import { LeaveForm, LeaveQuery, LeaveVO } from '@/api/workflow/leave/types';
-import { startWorkFlow } from '@/api/workflow/task';
-import SubmitVerify from '@/components/Process/submitVerify.vue';
-import ApprovalRecord from '@/components/Process/approvalRecord.vue';
-import ApprovalButton from '@/components/Process/approvalButton.vue';
-import { AxiosResponse } from 'axios';
-import { StartProcessBo } from '@/api/workflow/workflowCommon/types';
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const buttonLoading = ref(false);
-const loading = ref(true);
-const leaveTime = ref<Array<string>>([]);
-//路由参数
-const routeParams = ref<Record<string, any>>({});
-const options = [
-  {
-    value: '1',
-    label: '事假'
-  },
-  {
-    value: '2',
-    label: '调休'
-  },
-  {
-    value: '3',
-    label: '病假'
-  },
-  {
-    value: '4',
-    label: '婚假'
-  }
-];
-const flowCodeOptions = [
-  {
-    value: 'leave1',
-    label: '请假申请-普通'
-  },
-  {
-    value: 'leave2',
-    label: '请假申请-排他网关'
-  },
-  {
-    value: 'leave3',
-    label: '请假申请-并行网关'
-  },
-  {
-    value: 'leave4',
-    label: '请假申请-会签'
-  },
-  {
-    value: 'leave5',
-    label: '请假申请-并行会签网关'
-  },
-  {
-    value: 'leave6',
-    label: '请假申请-排他并行会签'
-  }
-];
-// 自定义流程可不选择 直接填写flowCode 例如 'leave1'
-const flowCode = ref<string>('leave1');
-
-//提交组件
-const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>();
-//审批记录组件
-const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
-
-const leaveFormRef = ref<ElFormInstance>();
-
-const submitFormData = ref<StartProcessBo>({
-  businessId: '',
-  flowCode: '',
-  variables: {},
-  bizExt: {}
-});
-const taskVariables = ref<Record<string, any>>({});
-const bizExt = ref<Record<string, any>>({});
-
-const initFormData: LeaveForm = {
-  id: undefined,
-  leaveType: undefined,
-  startDate: undefined,
-  endDate: undefined,
-  leaveDays: undefined,
-  remark: undefined,
-  status: undefined
-};
-const data = reactive<PageData<LeaveForm, LeaveQuery>>({
-  form: { ...initFormData },
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    startLeaveDays: undefined,
-    endLeaveDays: undefined
-  },
-  rules: {
-    id: [{ required: true, message: '主键不能为空', trigger: 'blur' }],
-    leaveType: [{ required: true, message: '请假类型不能为空', trigger: 'blur' }],
-    leaveTime: [{ required: true, message: '请假时间不能为空', trigger: 'blur' }],
-    leaveDays: [{ required: true, message: '请假天数不能为空', trigger: 'blur' }]
-  }
-});
-
-const { form, rules } = toRefs(data);
-
-/** 表单重置 */
-const reset = () => {
-  form.value = { ...initFormData };
-  leaveTime.value = [];
-  leaveFormRef.value?.resetFields();
-};
-
-const changeLeaveTime = () => {
-  const startDate = new Date(leaveTime.value[0]).getTime();
-  const endDate = new Date(leaveTime.value[1]).getTime();
-  const diffInMilliseconds = endDate - startDate;
-  form.value.leaveDays = Math.floor(diffInMilliseconds / (1000 * 60 * 60 * 24)) + 1;
-};
-/** 获取详情 */
-const getInfo = () => {
-  loading.value = true;
-  buttonLoading.value = false;
-  nextTick(async () => {
-    const res = await getLeave(routeParams.value.id);
-    Object.assign(form.value, res.data);
-    leaveTime.value = [];
-    leaveTime.value.push(form.value.startDate);
-    leaveTime.value.push(form.value.endDate);
-    loading.value = false;
-    buttonLoading.value = false;
-  });
-};
-
-/** 提交按钮 */
-const submitForm = (status: string, mode: boolean) => {
-  if (leaveTime.value.length === 0) {
-    proxy?.$modal.msgError('请假时间不能为空');
-    return;
-  }
-  try {
-    leaveFormRef.value?.validate(async (valid: boolean) => {
-      form.value.startDate = leaveTime.value[0];
-      form.value.endDate = leaveTime.value[1];
-      if (valid) {
-        buttonLoading.value = true;
-        // 设置后端发起和不等于草稿状态 直接走流程发起
-        if (mode && status != 'draft') {
-          const res = await submitAndFlowStart(form.value).finally(() => (buttonLoading.value = false));
-          form.value = res.data;
-          buttonLoading.value = false;
-          proxy?.$modal.msgSuccess('操作成功');
-          proxy.$tab.closePage(proxy.$route);
-          proxy.$router.go(-1);
-        } else {
-          let res;
-          if (form.value.id) {
-            res = await updateLeave(form.value).finally(() => (buttonLoading.value = false));
-          } else {
-            res = await addLeave(form.value).finally(() => (buttonLoading.value = false));
-          }
-          form.value = res.data;
-          if (status === 'draft') {
-            buttonLoading.value = false;
-            proxy?.$modal.msgSuccess('暂存成功');
-            proxy.$tab.closePage(proxy.$route);
-            proxy.$router.go(-1);
-          } else {
-            await handleStartWorkFlow(res.data);
-          }
-        }
-      }
-    });
-  } finally {
-    buttonLoading.value = false;
-  }
-};
-
-//提交申请
-const handleStartWorkFlow = async (data: LeaveForm) => {
-  try {
-    submitFormData.value.flowCode = flowCode.value;
-    submitFormData.value.businessId = data.id;
-    //流程变量
-    taskVariables.value = {
-      // leave2/6 使用的流程变量
-      leaveDays: data.leaveDays,
-      // leave4/5 使用的流程变量
-      userList: ['1', '3', '4']
-    };
-    //流程实例业务扩展字段
-    bizExt.value = {
-      businessTitle: '请假申请',
-      businessCode: data.applyCode
-    };
-    submitFormData.value.variables = taskVariables.value;
-    submitFormData.value.bizExt = bizExt.value;
-    const resp = await startWorkFlow(submitFormData.value);
-    if (submitVerifyRef.value) {
-      buttonLoading.value = false;
-      submitVerifyRef.value.openDialog(resp.data.taskId);
-    }
-  } finally {
-    buttonLoading.value = false;
-  }
-};
-//审批记录
-const handleApprovalRecord = () => {
-  approvalRecordRef.value.init(form.value.id);
-};
-//提交回调
-const submitCallback = async () => {
-  await proxy.$tab.closePage(proxy.$route);
-  proxy.$router.go(-1);
-};
-//审批
-const approvalVerifyOpen = async () => {
-  submitVerifyRef.value.openDialog(routeParams.value.taskId);
-};
-
-onMounted(() => {
-  nextTick(async () => {
-    routeParams.value = proxy.$route.query;
-    reset();
-    loading.value = false;
-    if (routeParams.value.type === 'update' || routeParams.value.type === 'view' || routeParams.value.type === 'approval') {
-      getInfo();
-    }
-  });
-});
-</script>

+ 0 - 46
src/views/workflow/processDefinition/design.vue

@@ -1,46 +0,0 @@
-<template>
-  <div ref="container" class="w-full h-[calc(100vh-88px)]">
-    <iframe ref="iframe" :src="iframeUrl" frameborder="0" height="100%" style="height: 100%; width: inherit"></iframe>
-  </div>
-</template>
-
-<script setup name="WarmFlow" lang="ts">
-const { proxy } = getCurrentInstance();
-import { onMounted } from 'vue';
-import { getToken } from '@/utils/auth';
-
-// definitionId为需要查询的流程定义id,
-// disabled为是否可编辑, 例如:查看的时候不可编辑,不可保存
-const iframeUrl = ref('');
-const baseUrl = import.meta.env.VITE_APP_BASE_API;
-const iframeLoaded = () => {
-  // iframe监听组件内设计器保存事件
-  window.onmessage = (event) => {
-    switch (event.data.method) {
-      case 'close':
-        close();
-        break;
-    }
-  };
-};
-const open = async (definitionId, disabled) => {
-  const url = baseUrl + `/warm-flow-ui/index.html?id=${definitionId}&onlyDesignShow=true`;
-  iframeUrl.value = url + '&Authorization=Bearer ' + getToken() + '&clientid=' + import.meta.env.VITE_APP_CLIENT_ID;
-};
-/** 关闭按钮 */
-function close() {
-  const obj = { path: '/workflow/processDefinition', query: { activeName: proxy.$route.query.activeName } };
-  proxy.$tab.closeOpenPage(obj);
-}
-
-onMounted(() => {
-  iframeLoaded();
-  open(proxy.$route.query.definitionId, proxy.$route.query.disabled);
-});
-/**
- * 对外暴露子组件方法
- */
-defineExpose({
-  open
-});
-</script>

+ 0 - 562
src/views/workflow/processDefinition/index.vue

@@ -1,562 +0,0 @@
-<template>
-  <div class="p-2">
-    <el-row :gutter="20">
-      <!-- 流程分类树 -->
-      <el-col :lg="4" :xs="24" style="">
-        <el-card shadow="hover">
-          <el-input v-model="categoryName" placeholder="请输入流程分类名" prefix-icon="Search" clearable />
-          <el-tree
-            ref="categoryTreeRef"
-            class="mt-2"
-            node-key="id"
-            :data="categoryOptions"
-            :props="{ label: 'label', children: 'children' } as any"
-            :expand-on-click-node="false"
-            :filter-node-method="filterNode"
-            highlight-current
-            default-expand-all
-            @node-click="handleNodeClick"
-          ></el-tree>
-        </el-card>
-      </el-col>
-      <el-col :lg="20" :xs="24">
-        <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-          <div v-show="showSearch" class="mb-[10px]">
-            <el-card shadow="hover">
-              <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true" label-width="120px">
-                <el-form-item label="流程定义名称" prop="flowName">
-                  <el-input v-model="queryParams.flowName" placeholder="请输入流程定义名称" clearable @keyup.enter="handleQuery" />
-                </el-form-item>
-                <el-form-item label="流程定义编码" prop="flowCode">
-                  <el-input v-model="queryParams.flowCode" placeholder="请输入流程定义编码" clearable @keyup.enter="handleQuery" />
-                </el-form-item>
-                <el-form-item>
-                  <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-                  <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-                </el-form-item>
-              </el-form>
-            </el-card>
-          </div>
-        </transition>
-        <el-card shadow="hover">
-          <template #header>
-            <el-row :gutter="10" class="mb8">
-              <el-col :span="1.5">
-                <el-button type="primary" icon="Plus" @click="handleAdd()">添加</el-button>
-              </el-col>
-              <el-col :span="1.5">
-                <el-button type="success" icon="Edit" :disabled="single" @click="handleUpdate()">修改</el-button>
-              </el-col>
-              <el-col :span="1.5">
-                <el-button type="danger" icon="Delete" :disabled="multiple" @click="handleDelete()">删除</el-button>
-              </el-col>
-              <el-col :span="1.5">
-                <el-button type="primary" icon="UploadFilled" @click="uploadDialog.visible = true">部署流程文件</el-button>
-              </el-col>
-              <el-col :span="1.5">
-                <el-button type="warning" icon="Download" :disabled="single" @click="handleExportDef">导出</el-button>
-              </el-col>
-              <right-toolbar v-model:show-search="showSearch" @query-table="handleQuery"></right-toolbar>
-            </el-row>
-          </template>
-          <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
-            <el-tab-pane label="已发布" name="0"></el-tab-pane>
-            <el-tab-pane label="未发布" name="1"></el-tab-pane>
-            <el-table v-loading="loading" border :data="processDefinitionList" @selection-change="handleSelectionChange">
-              <el-table-column type="selection" width="55" align="center" />
-              <el-table-column align="center" prop="id" label="主键" v-if="false"></el-table-column>
-              <el-table-column align="center" prop="flowName" label="流程定义名称" :show-overflow-tooltip="true"></el-table-column>
-              <el-table-column align="center" prop="flowCode" label="标识KEY" :show-overflow-tooltip="true"></el-table-column>
-              <el-table-column align="center" prop="categoryName" label="流程分类" :show-overflow-tooltip="true"></el-table-column>
-              <el-table-column align="center" prop="version" label="版本号" width="80">
-                <template #default="scope"> v{{ scope.row.version }}.0</template>
-              </el-table-column>
-              <el-table-column align="center" prop="activityStatus" label="激活状态" width="130">
-                <template #default="scope">
-                  <el-switch
-                    v-model="scope.row.activityStatus"
-                    :active-value="1"
-                    :inactive-value="0"
-                    @change="(status) => handleProcessDefState(scope.row, status)"
-                  />
-                </template>
-              </el-table-column>
-              <el-table-column align="center" prop="isPublish" label="发布状态" width="100">
-                <template #default="scope">
-                  <el-tag v-if="scope.row.isPublish == 0" type="danger">未发布</el-tag>
-                  <el-tag v-else-if="scope.row.isPublish == 1" type="success">已发布</el-tag>
-                  <el-tag v-else type="danger">失效</el-tag>
-                </template>
-              </el-table-column>
-              <el-table-column fixed="right" label="操作" align="center" width="170" class-name="small-padding fixed-width">
-                <template #default="scope">
-                  <el-row :gutter="10" class="mb8">
-                    <el-col :span="1.5">
-                      <el-button link type="primary" size="small" icon="Delete" @click="handleDelete(scope.row)">删除流程</el-button>
-                    </el-col>
-                    <el-col :span="1.5">
-                      <el-button link type="primary" size="small" icon="CopyDocument" @click="handleCopyDef(scope.row)">复制流程</el-button>
-                    </el-col>
-                  </el-row>
-                  <el-row :gutter="10" class="mb8">
-                    <el-col :span="1.5">
-                      <el-button link type="primary" v-if="scope.row.isPublish === 0" icon="Pointer" size="small" @click="design(scope.row)"
-                        >流程设计</el-button
-                      >
-                      <el-button link type="primary" v-else icon="View" size="small" @click="designView(scope.row)">查看流程</el-button>
-                    </el-col>
-                    <el-col v-if="scope.row.isPublish !== 1" :span="1.5">
-                      <el-button link type="primary" size="small" icon="CircleCheck" @click="handlePublish(scope.row)">发布流程</el-button>
-                    </el-col>
-                  </el-row>
-                </template>
-              </el-table-column>
-            </el-table>
-            <pagination
-              v-show="total > 0"
-              v-model:page="queryParams.pageNum"
-              v-model:limit="queryParams.pageSize"
-              :total="total"
-              @pagination="getPageList"
-            />
-          </el-tabs>
-        </el-card>
-      </el-col>
-    </el-row>
-
-    <!-- 部署文件 -->
-    <el-dialog v-if="uploadDialog.visible" v-model="uploadDialog.visible" :title="uploadDialog.title" width="30%">
-      <div v-loading="uploadDialogLoading">
-        <div class="mb5">
-          <el-text class="mx-1" size="large"><span class="text-danger">*</span>请选择部署流程分类:</el-text>
-          <el-tree-select
-            v-model="selectCategory"
-            :data="categoryOptions"
-            :props="{ value: 'id', label: 'label', children: 'children' } as any"
-            filterable
-            value-key="id"
-            :render-after-expand="false"
-            check-strictly
-            style="width: 240px"
-          />
-        </div>
-        <el-upload
-          class="upload-demo"
-          drag
-          multiple
-          accept="application/json,application/text"
-          :before-upload="handlerBeforeUpload"
-          :http-request="handlerImportDefinition"
-        >
-          <el-icon class="UploadFilled"><upload-filled /></el-icon>
-          <div class="el-upload__text"><em>点击上传,选择JSON流程文件</em></div>
-          <div class="el-upload__text">仅支持json格式文件</div>
-          <div class="el-upload__text">PS:如若部署请部署从本项目模型管理导出的数据</div>
-        </el-upload>
-      </div>
-    </el-dialog>
-
-    <!-- 新增/编辑流程定义 -->
-    <el-dialog v-model="modelDialog.visible" :title="modelDialog.title" width="650px" append-to-body :close-on-click-modal="false">
-      <template #footer>
-        <el-form ref="defFormRef" :model="form" :rules="rules" label-width="120px">
-          <el-form-item label="流程类别" prop="category">
-            <el-tree-select
-              v-model="form.category"
-              :data="categoryOptions"
-              :props="{ value: 'id', label: 'label', children: 'children' } as any"
-              filterable
-              value-key="id"
-              :render-after-expand="false"
-              check-strictly
-              style="width: 100%"
-            />
-          </el-form-item>
-          <el-form-item label="流程编码" prop="flowCode">
-            <el-input v-model="form.flowCode" placeholder="请输入流程编码" maxlength="40" show-word-limit />
-          </el-form-item>
-          <el-form-item label="流程名称" prop="flowName">
-            <el-input v-model="form.flowName" placeholder="请输入流程名称" maxlength="100" show-word-limit />
-          </el-form-item>
-          <el-form-item label="设计器模式" prop="modelValue">
-            <el-radio-group v-model="form.modelValue" :disabled="!!form.id">
-              <el-radio value="CLASSICS" size="large" border>经典模式</el-radio>
-              <el-radio value="MIMIC" size="large" border>仿钉钉模式</el-radio>
-            </el-radio-group>
-          </el-form-item>
-          <el-form-item label="流程配置">
-            <el-checkbox v-model="autoPass" label="下一节点执行人是当前任务处理人自动审批" />
-          </el-form-item>
-          <el-form-item label="是否动态表单" prop="formCustom">
-            <el-radio-group v-model="form.formCustom">
-              <el-radio value="Y" size="large" border disabled>是</el-radio>
-              <el-radio value="N" size="large" border>否</el-radio>
-            </el-radio-group>
-          </el-form-item>
-          <el-form-item label="表单路径" prop="formPath">
-            <el-input v-model="form.formPath" placeholder="请输入表单路径" maxlength="100" show-word-limit />
-          </el-form-item>
-        </el-form>
-        <div class="dialog-footer">
-          <el-button @click="modelDialog.visible = false">取消</el-button>
-          <el-button type="primary" @click="handleSubmit">保存</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup name="processDefinition" lang="ts">
-import { listDefinition, deleteDefinition, active, importDef, unPublishList, publish, add, edit, getInfo, copy } from '@/api/workflow/definition';
-import { categoryTree } from '@/api/workflow/category';
-import { CategoryTreeVO } from '@/api/workflow/category/types';
-import { FlowDefinitionQuery, FlowDefinitionVo, FlowDefinitionForm } from '@/api/workflow/definition/types';
-import { UploadRequestOptions, TabsPaneContext } from 'element-plus';
-import { ElMessageBoxOptions } from 'element-plus/es/components/message-box/src/message-box.type';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const queryFormRef = ref<ElFormInstance>();
-const categoryTreeRef = ref<ElTreeInstance>();
-
-const loading = ref(true);
-const ids = ref<Array<any>>([]);
-const flowCodeList = ref<Array<any>>([]);
-const single = ref(true);
-const multiple = ref(true);
-const showSearch = ref(true);
-const total = ref(0);
-const uploadDialogLoading = ref(false);
-const processDefinitionList = ref<FlowDefinitionVo[]>([]);
-const categoryOptions = ref<CategoryTreeVO[]>([]);
-const categoryName = ref('');
-const autoPass = ref(false);
-/** 部署文件分类选择 */
-const selectCategory = ref();
-const defFormRef = ref<ElFormInstance>();
-const activeName = ref('0');
-const uploadDialog = reactive<DialogOption>({
-  visible: false,
-  title: '部署流程文件'
-});
-
-const processDefinitionDialog = reactive<DialogOption>({
-  visible: false,
-  title: '历史版本'
-});
-
-const modelDialog = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-// 查询参数
-const queryParams = ref<FlowDefinitionQuery>({
-  pageNum: 1,
-  pageSize: 10,
-  flowName: undefined,
-  flowCode: undefined,
-  category: undefined
-});
-const rules = {
-  category: [{ required: true, message: '分类名称不能为空', trigger: 'blur' }],
-  flowName: [{ required: true, message: '流程定义名称不能为空', trigger: 'blur' }],
-  formCustom: [{ required: true, message: '请选择是否动态表单', trigger: 'change' }],
-  modelValue: [{ required: true, message: '设计器模式不能为空', trigger: 'change' }],
-  flowCode: [{ required: true, message: '流程定义编码不能为空', trigger: 'blur' }]
-};
-const initFormData: FlowDefinitionForm = {
-  id: '',
-  flowName: '',
-  flowCode: '',
-  category: '',
-  ext: '',
-  formPath: '',
-  formCustom: '',
-  modelValue: ''
-};
-//流程定义参数
-const form = ref<FlowDefinitionForm>({
-  id: '',
-  flowName: '',
-  flowCode: '',
-  category: '',
-  ext: '',
-  formPath: '',
-  formCustom: '',
-  modelValue: ''
-});
-onMounted(() => {
-  getPageList();
-  getTreeselect();
-});
-
-/** 节点单击事件 */
-const handleNodeClick = (data: CategoryTreeVO) => {
-  queryParams.value.category = data.id;
-  if (data.id === '0') {
-    queryParams.value.category = '';
-  }
-  handleQuery();
-};
-/** 通过条件过滤节点  */
-const filterNode = (value: string, data: any) => {
-  if (!value) return true;
-  return data.categoryName.indexOf(value) !== -1;
-};
-/** 根据名称筛选部门树 */
-watchEffect(
-  () => {
-    categoryTreeRef.value.filter(categoryName.value);
-  },
-  {
-    flush: 'post' // watchEffect会在DOM挂载或者更新之前就会触发,此属性控制在DOM元素更新后运行
-  }
-);
-
-/** 查询流程分类下拉树结构 */
-const getTreeselect = async () => {
-  const res = await categoryTree();
-  categoryOptions.value = res.data;
-};
-const handleClick = (tab: TabsPaneContext, event: Event) => {
-  // v-model处理有延迟 需要手动处理
-  activeName.value = tab.index;
-  handleQuery();
-};
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.value.pageNum = 1;
-  if (activeName.value === '0') {
-    getList();
-  } else {
-    getUnPublishList();
-  }
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  queryParams.value.category = '';
-  queryParams.value.pageNum = 1;
-  queryParams.value.pageSize = 10;
-  handleQuery();
-};
-// 多选框选中数据
-const handleSelectionChange = (selection: any) => {
-  ids.value = selection.map((item: any) => item.id);
-  flowCodeList.value = selection.map((item: any) => item.flowCode);
-  single.value = selection.length !== 1;
-  multiple.value = !selection.length;
-};
-//分页
-const getPageList = async () => {
-  const query = proxy.$route.query;
-  if (query.activeName) {
-    activeName.value = query.activeName;
-    proxy.$route.query.activeName = '';
-  }
-  if (activeName.value === '0') {
-    getList();
-  } else {
-    getUnPublishList();
-  }
-};
-//分页
-const getList = async () => {
-  loading.value = true;
-  const resp = await listDefinition(queryParams.value);
-  processDefinitionList.value = resp.rows;
-  total.value = resp.total;
-  loading.value = false;
-};
-//查询未发布的流程定义列表
-const getUnPublishList = async () => {
-  loading.value = true;
-  const resp = await unPublishList(queryParams.value);
-  processDefinitionList.value = resp.rows;
-  total.value = resp.total;
-  loading.value = false;
-};
-
-/** 删除按钮操作 */
-const handleDelete = async (row?: FlowDefinitionVo) => {
-  const id = row?.id || ids.value;
-  const defList = processDefinitionList.value.filter((x) => id.indexOf(x.id) != -1).map((x) => x.flowCode);
-  await proxy?.$modal.confirm('是否确认删除流程定义编码为【' + defList + '】的数据项?');
-  loading.value = true;
-  await deleteDefinition(id).finally(() => (loading.value = false));
-  await handleQuery();
-  proxy?.$modal.msgSuccess('删除成功');
-};
-
-/** 发布流程定义 */
-const handlePublish = async (row?: FlowDefinitionVo) => {
-  await proxy?.$modal.confirm(
-    '是否确认发布流程定义编码为【' + row.flowCode + '】版本为【' + row.version + '】的数据项?,发布后会将已发布流程定义改为失效!'
-  );
-  loading.value = true;
-  await publish(row.id).finally(() => (loading.value = false));
-  processDefinitionDialog.visible = false;
-  activeName.value = '0';
-  await handleQuery();
-  proxy?.$modal.msgSuccess('发布成功');
-};
-/** 挂起/激活 */
-const handleProcessDefState = async (row: FlowDefinitionVo, status: number | string | boolean) => {
-  let msg: string;
-  if (status === 0) {
-    msg = `暂停后,此流程下的所有任务都不允许往后流转,您确定挂起【${row.flowName || row.flowCode}】吗?`;
-  } else {
-    msg = `启动后,此流程下的所有任务都允许往后流转,您确定激活【${row.flowName || row.flowCode}】吗?`;
-  }
-  try {
-    loading.value = true;
-    await proxy?.$modal.confirm(msg);
-    await active(row.id, !!status);
-    await handleQuery();
-    proxy?.$modal.msgSuccess('操作成功');
-  } catch (error) {
-    row.activityStatus = status === 0 ? 1 : 0;
-    console.error(error);
-  } finally {
-    loading.value = false;
-  }
-};
-
-//上传文件前的钩子
-const handlerBeforeUpload = () => {
-  if (selectCategory.value === 'ALL') {
-    proxy?.$modal.msgError('顶级节点不可作为分类!');
-    return false;
-  }
-  if (!selectCategory.value) {
-    proxy?.$modal.msgError('请选择左侧要上传的分类!');
-    return false;
-  }
-};
-//部署文件
-const handlerImportDefinition = (data: UploadRequestOptions): XMLHttpRequest => {
-  const formData = new FormData();
-  uploadDialogLoading.value = true;
-  formData.append('file', data.file);
-  formData.append('category', selectCategory.value);
-  importDef(formData)
-    .then(() => {
-      uploadDialog.visible = false;
-      proxy?.$modal.msgSuccess('部署成功');
-      activeName.value = '1';
-      handleQuery();
-    })
-    .finally(() => {
-      uploadDialogLoading.value = false;
-    });
-  return;
-};
-/**
- * 设计流程
- * @param row
- */
-const design = async (row: FlowDefinitionVo) => {
-  proxy.$router.push({
-    path: `/workflow/design/index`,
-    query: {
-      definitionId: row.id,
-      disabled: false,
-      activeName: activeName.value
-    }
-  });
-};
-
-/**
- * 查看流程
- * @param row
- */
-const designView = async (row: FlowDefinitionVo) => {
-  proxy.$router.push({
-    path: `/workflow/design/index`,
-    query: {
-      definitionId: row.id,
-      disabled: true,
-      activeName: activeName.value
-    }
-  });
-};
-/** 表单重置 */
-const reset = () => {
-  form.value = { ...initFormData };
-  defFormRef.value?.resetFields();
-};
-/**
- * 新增
- */
-const handleAdd = async () => {
-  reset();
-  if (queryParams.value.category != '') {
-    form.value.category = queryParams.value.category;
-  }
-  form.value.modelValue = 'CLASSICS';
-  form.value.formCustom = 'N';
-  modelDialog.visible = true;
-  modelDialog.title = '新增流程';
-};
-/** 修改按钮操作 */
-const handleUpdate = async (row?: FlowDefinitionVo) => {
-  reset();
-  const id = row?.id || ids.value[0];
-  const res = await getInfo(id);
-  Object.assign(form.value, res.data);
-  autoPass.value = false;
-  if (form.value.ext != null && form.value.ext != '') {
-    const extJson = JSON.parse(form.value.ext);
-    if (extJson.autoPass != null && extJson.autoPass != '') {
-      autoPass.value = extJson.autoPass;
-    }
-  }
-  modelDialog.visible = true;
-  modelDialog.title = '修改流程';
-};
-
-const handleSubmit = async () => {
-  defFormRef.value.validate(async (valid: boolean) => {
-    if (valid) {
-      loading.value = true;
-      const ext = {};
-      ext.autoPass = autoPass.value;
-      form.value.ext = JSON.stringify(ext);
-      if (form.value.id) {
-        await edit(form.value).finally(() => (loading.value = false));
-      } else {
-        await add(form.value).finally(() => (loading.value = false));
-        activeName.value = '1';
-      }
-      proxy?.$modal.msgSuccess('操作成功');
-      modelDialog.visible = false;
-      handleQuery();
-    }
-  });
-};
-//复制
-const handleCopyDef = async (row: FlowDefinitionVo) => {
-  ElMessageBox.confirm(`是否确认复制【${row.flowCode}】版本为【${row.version}】的流程定义!`, '提示', {
-    confirmButtonText: '确认',
-    cancelButtonText: '取消',
-    type: 'warning'
-  } as ElMessageBoxOptions).then(() => {
-    loading.value = true;
-    copy(row.id)
-      .then((resp) => {
-        if (resp.code === 200) {
-          proxy?.$modal.msgSuccess('操作成功');
-          activeName.value = '1';
-          handleQuery();
-        }
-      })
-      .finally(() => (loading.value = false));
-  });
-};
-
-/** 导出按钮操作 */
-const handleExportDef = () => {
-  proxy?.download(`/workflow/definition/exportDef/${ids.value[0]}`, {}, `${flowCodeList.value[0]}.json`);
-};
-</script>

+ 0 - 478
src/views/workflow/processInstance/index.vue

@@ -1,478 +0,0 @@
-<template>
-  <div class="p-2">
-    <el-row :gutter="20">
-      <!-- 流程分类树 -->
-      <el-col :lg="4" :xs="24" style="">
-        <el-card shadow="hover">
-          <el-input v-model="categoryName" placeholder="请输入流程分类名" prefix-icon="Search" clearable />
-          <el-tree
-            ref="categoryTreeRef"
-            class="mt-2"
-            node-key="id"
-            :data="categoryOptions"
-            :props="{ label: 'label', children: 'children' } as any"
-            :expand-on-click-node="false"
-            :filter-node-method="filterNode"
-            highlight-current
-            default-expand-all
-            @node-click="handleNodeClick"
-          ></el-tree>
-        </el-card>
-      </el-col>
-      <el-col :lg="20" :xs="24">
-        <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-          <div v-show="showSearch" class="mb-[10px]">
-            <el-card shadow="hover">
-              <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true">
-                <el-form-item>
-                  <el-badge :value="userSelectCount" :max="10" class="item">
-                    <el-button type="primary" @click="openUserSelect">选择申请人</el-button>
-                  </el-badge>
-                </el-form-item>
-                <el-form-item label="任务名称" prop="nodeName">
-                  <el-input v-model="queryParams.nodeName" placeholder="请输入任务名称" @keyup.enter="handleQuery" />
-                </el-form-item>
-                <el-form-item label="流程定义名称" label-width="100" prop="flowName">
-                  <el-input v-model="queryParams.flowName" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" />
-                </el-form-item>
-                <el-form-item label="流程定义编码" label-width="100" prop="flowCode">
-                  <el-input v-model="queryParams.flowCode" placeholder="请输入流程定义编码" @keyup.enter="handleQuery" />
-                </el-form-item>
-                <el-form-item>
-                  <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-                  <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-                </el-form-item>
-              </el-form>
-            </el-card>
-          </div>
-        </transition>
-        <el-card shadow="hover">
-          <template #header>
-            <el-row :gutter="10" class="mb8">
-              <el-col :span="1.5">
-                <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
-              </el-col>
-              <right-toolbar v-model:show-search="showSearch" @query-table="handleQuery"></right-toolbar>
-            </el-row>
-          </template>
-          <el-tabs v-model="tab" @tab-click="changeTab">
-            <el-tab-pane name="running" label="运行中"></el-tab-pane>
-            <el-tab-pane name="finish" label="已完成"></el-tab-pane>
-            <el-table v-loading="loading" border :data="processInstanceList" @selection-change="handleSelectionChange">
-              <el-table-column type="selection" width="55" align="center" />
-              <el-table-column align="center" type="index" label="序号" width="60"></el-table-column>
-              <el-table-column :show-overflow-tooltip="true" prop="businessCode" align="center" label="业务编码"></el-table-column>
-              <el-table-column :show-overflow-tooltip="true" prop="businessTitle" align="center" label="业务标题"></el-table-column>
-              <el-table-column :show-overflow-tooltip="true" align="center" width="120" label="流程定义名称">
-                <template #default="scope">
-                  <span>{{ scope.row.flowName }}v{{ scope.row.version }}</span>
-                </template>
-              </el-table-column>
-              <el-table-column align="center" prop="flowCode" width="120" label="流程定义编码"></el-table-column>
-              <el-table-column align="center" prop="categoryName" label="流程分类"></el-table-column>
-              <el-table-column align="center" prop="nodeName" label="任务名称"></el-table-column>
-              <el-table-column align="center" prop="createByName" :show-overflow-tooltip="true" label="申请人"></el-table-column>
-              <el-table-column align="center" prop="version" label="版本号" width="90">
-                <template #default="scope"> v{{ scope.row.version }}.0</template>
-              </el-table-column>
-              <el-table-column v-if="tab === 'running'" align="center" prop="isSuspended" label="状态" min-width="70">
-                <template #default="scope">
-                  <el-tag v-if="!scope.row.isSuspended" type="success">激活</el-tag>
-                  <el-tag v-else type="danger">挂起</el-tag>
-                </template>
-              </el-table-column>
-              <el-table-column align="center" label="流程状态" min-width="80">
-                <template #default="scope">
-                  <dict-tag :options="wf_business_status" :value="scope.row.flowStatus"></dict-tag>
-                </template>
-              </el-table-column>
-              <el-table-column align="center" prop="createTime" label="启动时间" width="160"></el-table-column>
-              <el-table-column v-if="tab === 'finish'" align="center" prop="updateTime" label="结束时间" width="160"></el-table-column>
-              <el-table-column label="操作" align="center" :width="165" fixed="right">
-                <template #default="scope">
-                  <el-row v-if="tab === 'running'" :gutter="10" class="mb8">
-                    <el-col :span="1.5">
-                      <el-popover :ref="`popoverRef${scope.$index}`" trigger="click" placement="left" :width="300">
-                        <el-input v-model="deleteReason" resize="none" :rows="3" type="textarea" placeholder="请输入作废原因" />
-                        <div style="text-align: right; margin: 5px 0px 0px 0px">
-                          <el-button size="small" text @click="cancelPopover(scope.$index)">取消</el-button>
-                          <el-button size="small" type="primary" @click="handleInvalid(scope.row)">确认</el-button>
-                        </div>
-                        <template #reference>
-                          <el-button type="danger" size="small" icon="CircleClose">作废</el-button>
-                        </template>
-                      </el-popover>
-                    </el-col>
-                    <el-col :span="1.5">
-                      <el-button type="danger" size="small" icon="Delete" @click="handleDelete(scope.row)">删除 </el-button>
-                    </el-col>
-                  </el-row>
-                  <el-row :gutter="10" class="mb8">
-                    <el-col :span="1.5">
-                      <el-button type="primary" size="small" icon="View" @click="handleView(scope.row)">查看</el-button>
-                    </el-col>
-                    <el-col :span="1.5">
-                      <el-button type="primary" size="small" icon="Document" @click="handleInstanceVariable(scope.row)"> 变量 </el-button>
-                    </el-col>
-                  </el-row>
-                </template>
-              </el-table-column>
-            </el-table>
-            <pagination
-              v-show="total > 0"
-              v-model:page="queryParams.pageNum"
-              v-model:limit="queryParams.pageSize"
-              :total="total"
-              @pagination="handleQuery"
-            />
-          </el-tabs>
-        </el-card>
-      </el-col>
-    </el-row>
-    <el-dialog v-if="processDefinitionDialog.visible" v-model="processDefinitionDialog.visible" :title="processDefinitionDialog.title" width="70%">
-      <el-table v-loading="loading" :data="processDefinitionHistoryList">
-        <el-table-column fixed align="center" type="index" label="序号" width="60"></el-table-column>
-        <el-table-column fixed align="center" prop="name" label="流程定义名称"></el-table-column>
-        <el-table-column fixed align="center" prop="nodeName" label="任务名称"></el-table-column>
-        <el-table-column align="center" prop="key" label="标识Key"></el-table-column>
-        <el-table-column align="center" prop="version" label="版本号" width="90">
-          <template #default="scope"> v{{ scope.row.version }}.0</template>
-        </el-table-column>
-        <el-table-column align="center" prop="suspensionState" label="状态" min-width="70">
-          <template #default="scope">
-            <el-tag v-if="scope.row.suspensionState == 1" type="success">激活</el-tag>
-            <el-tag v-else type="danger">挂起</el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column align="center" prop="deploymentTime" label="部署时间" :show-overflow-tooltip="true"></el-table-column>
-      </el-table>
-    </el-dialog>
-    <!-- 流程变量开始 -->
-    <el-dialog v-model="variableVisible" v-if="variableVisible" draggable title="流程变量" width="60%" :close-on-click-modal="false">
-      <el-card v-loading="variableLoading">
-        <template #header>
-          <div class="clearfix">
-            <span
-              >流程定义名称:<el-tag>{{ processDefinitionName }}</el-tag></span
-            >
-          </div>
-        </template>
-        <div class="max-h-500px overflow-y-auto">
-          <VueJsonPretty :data="formatToJsonObject(variables)" />
-        </div>
-      </el-card>
-      <el-card v-loading="variableLoading">
-        <el-form ref="ruleFormRef" :model="form" :inline="true" :rules="rules" label-width="120px">
-          <el-form-item label="变量KEY" prop="key">
-            <el-input v-model="form.key" placeholder="请输入变量KEY" />
-          </el-form-item>
-          <el-form-item label="变量值" prop="value">
-            <el-input v-model="form.value" placeholder="请输入变量值" />
-          </el-form-item>
-          <el-form-item>
-            <el-button type="primary" @click="handleVariable(ruleFormRef)">确认</el-button>
-          </el-form-item>
-        </el-form>
-      </el-card>
-    </el-dialog>
-    <!-- 流程变量结束 -->
-
-    <!-- 申请人 -->
-    <UserSelect ref="userSelectRef" :multiple="true" :data="selectUserIds" @confirm-call-back="userSelectCallBack"></UserSelect>
-  </div>
-</template>
-
-<script setup lang="ts">
-import {
-  pageByRunning,
-  pageByFinish,
-  deleteByInstanceIds,
-  deleteHisByInstanceIds,
-  instanceVariable,
-  invalid,
-  updateVariable
-} from '@/api/workflow/instance';
-import { categoryTree } from '@/api/workflow/category';
-import { CategoryTreeVO } from '@/api/workflow/category/types';
-import { FlowInstanceQuery, FlowInstanceVO } from '@/api/workflow/instance/types';
-import workflowCommon from '@/api/workflow/workflowCommon';
-import { RouterJumpVo } from '@/api/workflow/workflowCommon/types';
-import VueJsonPretty from 'vue-json-pretty';
-import 'vue-json-pretty/lib/styles.css';
-import UserSelect from '@/components/UserSelect/index.vue';
-import { ElForm, FormInstance } from 'element-plus';
-//审批记录组件
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status'));
-const queryFormRef = ref<ElFormInstance>();
-const categoryTreeRef = ref<ElTreeInstance>();
-import { ref } from 'vue';
-import { UserVO } from '@/api/system/user/types';
-const form = ref<Record<string, any>>({
-  instanceId: undefined,
-  key: undefined,
-  value: undefined
-});
-const ruleFormRef = ref<FormInstance>();
-const userSelectRef = ref<InstanceType<typeof UserSelect>>();
-// 遮罩层
-const loading = ref(true);
-// 选中数组
-const ids = ref<Array<any>>([]);
-// 选中实例id数组
-const instanceIds = ref<Array<number | string>>([]);
-// 非单个禁用
-const single = ref(true);
-// 非多个禁用
-const multiple = ref(true);
-// 显示搜索条件
-const showSearch = ref(true);
-// 总条数
-const total = ref(0);
-// 实例id
-const instanceId = ref(undefined);
-
-// 流程变量是否显示
-const variableVisible = ref(false);
-const variableLoading = ref(true);
-const variables = ref<string>('');
-//流程定义名称
-const processDefinitionName = ref();
-// 模型定义表格数据
-const processInstanceList = ref<FlowInstanceVO[]>([]);
-const processDefinitionHistoryList = ref<Array<any>>([]);
-const categoryOptions = ref<CategoryOption[]>([]);
-const categoryName = ref('');
-
-const processDefinitionDialog = reactive<DialogOption>({
-  visible: false,
-  title: '流程定义'
-});
-
-type CategoryOption = {
-  id: string;
-  categoryName: string;
-  children?: CategoryOption[];
-};
-
-const tab = ref('running');
-// 作废原因
-const deleteReason = ref('');
-
-//申请人id
-const selectUserIds = ref<Array<number | string>>([]);
-//申请人选择数量
-const userSelectCount = ref(0);
-// 查询参数
-const queryParams = ref<FlowInstanceQuery>({
-  pageNum: 1,
-  pageSize: 10,
-  nodeName: undefined,
-  flowName: undefined,
-  flowCode: undefined,
-  createByIds: [],
-  category: undefined
-});
-
-/** 节点单击事件 */
-const handleNodeClick = (data: CategoryTreeVO) => {
-  queryParams.value.category = data.id;
-  if (data.id === '0') {
-    queryParams.value.category = '';
-  }
-  handleQuery();
-};
-/** 通过条件过滤节点  */
-const filterNode = (value: string, data: any) => {
-  if (!value) return true;
-  return data.categoryName.indexOf(value) !== -1;
-};
-/** 根据名称筛选部门树 */
-watchEffect(
-  () => {
-    categoryTreeRef.value.filter(categoryName.value);
-  },
-  {
-    flush: 'post' // watchEffect会在DOM挂载或者更新之前就会触发,此属性控制在DOM元素更新后运行
-  }
-);
-
-/** 查询流程分类下拉树结构 */
-const getTreeselect = async () => {
-  const res = await categoryTree();
-  categoryOptions.value = res.data;
-};
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  if ('running' === tab.value) {
-    getProcessInstanceRunningList();
-  } else {
-    getProcessInstanceFinishList();
-  }
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  queryParams.value.category = '';
-  queryParams.value.pageNum = 1;
-  queryParams.value.pageSize = 10;
-  queryParams.value.createByIds = [];
-  userSelectCount.value = 0;
-  handleQuery();
-};
-// 多选框选中数据
-const handleSelectionChange = (selection: FlowInstanceVO[]) => {
-  ids.value = selection.map((item: any) => item.id);
-  instanceIds.value = selection.map((item: FlowInstanceVO) => item.id);
-  single.value = selection.length !== 1;
-  multiple.value = !selection.length;
-};
-//分页
-const getProcessInstanceRunningList = () => {
-  loading.value = true;
-  pageByRunning(queryParams.value).then((resp) => {
-    processInstanceList.value = resp.rows;
-    total.value = resp.total;
-    loading.value = false;
-  });
-};
-//分页
-const getProcessInstanceFinishList = () => {
-  loading.value = true;
-  pageByFinish(queryParams.value).then((resp) => {
-    processInstanceList.value = resp.rows;
-    total.value = resp.total;
-    loading.value = false;
-  });
-};
-
-/** 删除按钮操作 */
-const handleDelete = async (row: FlowInstanceVO) => {
-  const instanceIdList = row.id || instanceIds.value;
-  await proxy?.$modal.confirm('是否确认删除?');
-  loading.value = true;
-  if ('running' === tab.value) {
-    await deleteByInstanceIds(instanceIdList).finally(() => (loading.value = false));
-    getProcessInstanceRunningList();
-  } else {
-    await deleteHisByInstanceIds(instanceIdList).finally(() => (loading.value = false));
-    getProcessInstanceFinishList();
-  }
-  proxy?.$modal.msgSuccess('删除成功');
-};
-const changeTab = async (data: string) => {
-  processInstanceList.value = [];
-  queryParams.value.pageNum = 1;
-  if ('running' === data.paneName) {
-    getProcessInstanceRunningList();
-  } else {
-    getProcessInstanceFinishList();
-  }
-};
-/** 作废按钮操作 */
-const handleInvalid = async (row: FlowInstanceVO) => {
-  await proxy?.$modal.confirm('是否确认作废?');
-  loading.value = true;
-  if ('running' === tab.value) {
-    const param = {
-      id: row.id,
-      comment: deleteReason.value
-    };
-    await invalid(param).finally(() => (loading.value = false));
-    getProcessInstanceRunningList();
-    proxy?.$modal.msgSuccess('操作成功');
-  }
-};
-const cancelPopover = async (index: any) => {
-  (proxy?.$refs[`popoverRef${index}`] as any).hide(); //关闭弹窗
-};
-/** 查看按钮操作 */
-const handleView = (row) => {
-  const routerJumpVo = reactive<RouterJumpVo>({
-    businessId: row.businessId,
-    taskId: row.id,
-    type: 'view',
-    formCustom: row.formCustom,
-    formPath: row.formPath
-  });
-  workflowCommon.routerJump(routerJumpVo, proxy);
-};
-
-//查询流程变量
-const handleInstanceVariable = async (row: FlowInstanceVO) => {
-  instanceId.value = row.id;
-  variableLoading.value = true;
-  variableVisible.value = true;
-  processDefinitionName.value = row.flowName;
-  const data = await instanceVariable(row.id);
-  variables.value = data.data.variable;
-  variableLoading.value = false;
-  form.value.instanceId = undefined;
-  form.value.key = undefined;
-  form.value.value = undefined;
-};
-
-/**
- * json转为对象
- * @param data 原始数据
- */
-function formatToJsonObject(data: string) {
-  try {
-    return JSON.parse(data);
-  } catch (error) {
-    return data;
-  }
-}
-
-//打开申请人选择
-const openUserSelect = () => {
-  userSelectRef.value.open();
-};
-//确认选择申请人
-const userSelectCallBack = (data: UserVO[]) => {
-  userSelectCount.value = 0;
-  selectUserIds.value = [];
-  queryParams.value.createByIds = [];
-
-  if (data && data.length > 0) {
-    userSelectCount.value = data.length;
-    selectUserIds.value = data.map((item) => item.userId);
-    queryParams.value.createByIds = selectUserIds.value;
-  }
-};
-const rules = reactive<Record<string, any>>({
-  key: [
-    {
-      required: true,
-      message: '请输入KEY',
-      trigger: 'blur'
-    }
-  ],
-  value: [
-    {
-      required: true,
-      message: '请输入变量值',
-      trigger: 'blur'
-    }
-  ]
-});
-
-const handleVariable = async (formEl: FormInstance | undefined) => {
-  await formEl.validate(async (valid, fields) => {
-    if (valid) {
-      form.value.instanceId = instanceId.value;
-      await proxy?.$modal.confirm('是否确认提交?');
-      await updateVariable(form.value);
-      proxy?.$modal.msgSuccess('操作成功');
-      const data = await instanceVariable(instanceId.value);
-      variables.value = data.data.variable;
-    }
-  });
-};
-
-onMounted(() => {
-  getProcessInstanceRunningList();
-  getTreeselect();
-});
-</script>

+ 0 - 360
src/views/workflow/spel/index.vue

@@ -1,360 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
-        <el-card shadow="hover">
-          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="组件名称" prop="componentName">
-              <el-input v-model="queryParams.componentName" placeholder="请输入组件名称" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="方法名" prop="methodName">
-              <el-input v-model="queryParams.methodName" placeholder="请输入方法名" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
-      </div>
-    </transition>
-
-    <el-card shadow="never">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['workflow:spel:add']">新增</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['workflow:spel:edit']">修改</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['workflow:spel:remove']">删除</el-button>
-          </el-col>
-          <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-        </el-row>
-      </template>
-
-      <el-table v-loading="loading" border :data="spelList" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column label="序号" type="index" width="60" align="center">
-          <template #default="scope">
-            <span>{{ (queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1 }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="组件名称" align="center">
-          <template #default="scope">
-            {{ scope.row.componentName || '-' }}
-          </template>
-        </el-table-column>
-        <el-table-column label="方法名称" align="center">
-          <template #default="scope">
-            {{ scope.row.methodName || '-' }}
-          </template>
-        </el-table-column>
-        <el-table-column label="参数名称" align="center">
-          <template #default="scope">
-            {{ scope.row.methodParams || '-' }}
-          </template>
-        </el-table-column>
-        <el-table-column label="SPEL表达式" align="center" prop="viewSpel" />
-        <el-table-column label="状态" align="center" prop="status">
-          <template #default="scope">
-            <el-tag v-if="scope.row.status === '0'">正常</el-tag>
-            <el-tag v-else>停用</el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column label="备注" align="center">
-          <template #default="scope">
-            {{ scope.row.remark || '-' }}
-          </template>
-        </el-table-column>
-        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
-          <template #default="scope">
-            <el-tooltip content="修改" placement="top">
-              <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['workflow:spel:edit']"></el-button>
-            </el-tooltip>
-            <el-tooltip content="删除" placement="top">
-              <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['workflow:spel:remove']"></el-button>
-            </el-tooltip>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
-    </el-card>
-    <!-- 添加或修改流程spel表达式定义对话框 -->
-    <el-dialog :title="dialog.title" v-model="dialog.visible" width="550px" append-to-body>
-      <el-form ref="spelFormRef" :model="form" :rules="rules" label-width="100px">
-        <!-- 组件名称 -->
-        <el-form-item label="组件名称" prop="componentName">
-          <el-input v-model="form.componentName" placeholder="请输入组件名称" @input="updateViewSpel" />
-          <template #label>
-            <span>
-              <el-tooltip content="注册到Spring容器中的组件名,如:spelRuleComponent" placement="top">
-                <el-icon><question-filled /></el-icon>
-              </el-tooltip>
-              组件名称
-            </span>
-          </template>
-        </el-form-item>
-        <el-form-item label="方法名称" prop="methodName">
-          <el-input v-model="form.methodName" placeholder="请输入方法名称" @input="updateViewSpel" />
-          <template #label>
-            <span>
-              <el-tooltip content="组件中的方法名称,如:selectDeptLeaderById" placement="top">
-                <el-icon><question-filled /></el-icon>
-              </el-tooltip>
-              方法名称
-            </span>
-          </template>
-        </el-form-item>
-        <el-form-item label="方法参数" prop="methodParams">
-          <el-input v-model="form.methodParams" placeholder="请输入方法参数" @input="updateViewSpel" />
-          <template #label>
-            <span>
-              <el-tooltip content="方法参数,如:deptId, 多个使用 ',' 分隔,单参数变量仅支持单个方法参数" placement="top">
-                <el-icon><question-filled /></el-icon>
-              </el-tooltip>
-              方法参数
-            </span>
-          </template>
-        </el-form-item>
-
-        <!-- 改为只读文本展示 -->
-        <el-form-item label="SPEL表达式">
-          <span class="preview-box">
-            {{ form.viewSpel || '例如:#{@组件名.方法名(#方法参数)} 或 ${方法参数}' }}
-          </span>
-        </el-form-item>
-        <el-form-item label="状态" prop="status">
-          <el-radio-group v-model="form.status">
-            <el-radio v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.value">
-              {{ dict.label }}
-            </el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label="备注" prop="remark">
-          <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="请输入备注" />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
-          <el-button @click="cancel">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup name="Spel" lang="ts">
-import { listSpel, getSpel, delSpel, addSpel, updateSpel } from '@/api/workflow/spel';
-import { SpelVO, SpelQuery, SpelForm } from '@/api/workflow/spel/types';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { sys_show_hide, sys_normal_disable } = toRefs<any>(proxy?.useDict('sys_show_hide', 'sys_normal_disable'));
-
-const spelList = ref<SpelVO[]>([]);
-const buttonLoading = ref(false);
-const loading = ref(true);
-const showSearch = ref(true);
-const ids = ref<Array<string | number>>([]);
-const single = ref(true);
-const multiple = ref(true);
-const total = ref(0);
-
-const queryFormRef = ref<ElFormInstance>();
-const spelFormRef = ref<ElFormInstance>();
-
-const dialog = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-const initFormData: SpelForm = {
-  id: undefined,
-  componentName: undefined,
-  methodName: undefined,
-  methodParams: undefined,
-  viewSpel: undefined,
-  status: '0',
-  remark: undefined,
-}
-const data = reactive<PageData<SpelForm, SpelQuery>>({
-  form: {...initFormData},
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    componentName: undefined,
-    methodName: undefined,
-    methodParams: undefined,
-    viewSpel: undefined,
-    status: '0',
-    params: {
-    }
-  },
-  rules: {
-    status: [
-      { required: true, message: "状态不能为空", trigger: "change" }
-    ],
-  }
-});
-
-const { queryParams, form, rules } = toRefs(data);
-
-/** 查询流程spel表达式定义列表 */
-const getList = async () => {
-  loading.value = true;
-  const res = await listSpel(queryParams.value);
-  spelList.value = res.rows;
-  total.value = res.total;
-  loading.value = false;
-}
-
-/** 取消按钮 */
-const cancel = () => {
-  reset();
-  dialog.visible = false;
-}
-
-/** 表单重置 */
-const reset = () => {
-  form.value = {...initFormData};
-  spelFormRef.value?.resetFields();
-}
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.value.pageNum = 1;
-  getList();
-}
-
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  handleQuery();
-}
-
-/** 多选框选中数据 */
-const handleSelectionChange = (selection: SpelVO[]) => {
-  ids.value = selection.map(item => item.id);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
-}
-
-/** 新增按钮操作 */
-const handleAdd = () => {
-  reset();
-  dialog.visible = true;
-  dialog.title = "添加流程spel表达式定义";
-}
-
-/** 修改按钮操作 */
-const handleUpdate = async (row?: SpelVO) => {
-  reset();
-  const _id = row?.id || ids.value[0]
-  const res = await getSpel(_id);
-  Object.assign(form.value, res.data);
-  dialog.visible = true;
-  dialog.title = "修改流程spel表达式定义";
-}
-
-/** 提交按钮 */
-const submitForm = () => {
-  spelFormRef.value?.validate(async (valid: boolean) => {
-    if (valid) {
-      buttonLoading.value = true;
-      if (form.value.id) {
-        await updateSpel(form.value).finally(() =>  buttonLoading.value = false);
-      } else {
-        await addSpel(form.value).finally(() =>  buttonLoading.value = false);
-      }
-      proxy?.$modal.msgSuccess("操作成功");
-      dialog.visible = false;
-      await getList();
-    }
-  });
-}
-
-/** 删除按钮操作 */
-const handleDelete = async (row?: SpelVO) => {
-  const _ids = row?.id || ids.value;
-  await proxy?.$modal.confirm('是否确认删除流程spel表达式定义编号为"' + _ids + '"的数据项?').finally(() => loading.value = false);
-  await delSpel(_ids);
-  proxy?.$modal.msgSuccess("删除成功");
-  await getList();
-}
-
-/** 控制是否显示 viewSpel 输入框 */
-const showViewSpelInput = ref(false);
-
-/** 更新 spel 预览值并决定是否显示输入框 */
-const updateViewSpel = () => {
-  const comp = (form.value.componentName || '').trim();
-  const method = (form.value.methodName || '').trim();
-  const paramStr = (form.value.methodParams || '').trim();
-
-  if (!comp && !method && !paramStr) {
-    form.value.viewSpel = '';
-    return;
-  }
-
-  // 替换变量值:只有参数存在,组件和方法都不存在
-  if (!comp && !method && paramStr) {
-    const paramList = paramStr.split(',')
-      .map(p => p.trim())
-      .filter(p => p.length > 0);
-
-    if (paramList.length === 1) {
-      form.value.viewSpel = `\${${paramList[0]}}`;
-      return;
-    }
-  }
-
-  // 如果缺少组件或方法,提示填写
-  if (!comp || !method) {
-    form.value.viewSpel = '请填写组件名称和方法名';
-    return;
-  }
-
-  let paramList = [];
-
-  if (paramStr) {
-    // 分割并过滤掉空参数
-    paramList = paramStr.split(',')
-      .map(p => p.trim())
-      .filter(p => p.length > 0);
-  }
-
-  const paramPart = paramList.length > 0
-    ? '(' + paramList.map(p => `#${p}`).join(',') + ')'
-    : '()';
-
-  form.value.viewSpel = `#{@${comp}.${method}${paramPart}}`;
-};
-
-/** 监听所有字段变化 */
-watch(
-  () => [form.value.componentName, form.value.methodName, form.value.methodParams],
-  updateViewSpel
-);
-
-onMounted(() => {
-  getList();
-});
-</script>
-<style lang="scss">
-.preview-box {
-  width: 100%;
-  padding: 10px 12px;
-  background-color: #f5f7fa;
-  border-radius: 4px;
-  color: #333;
-  font-family: monospace; /* 等宽字体更清晰 */
-  white-space: nowrap;    /* 禁止换行 */
-  overflow-x: auto;       /* 超出宽度时显示水平滚动条 */
-  min-height: 36px;       /* 与 el-input 高度对齐 */
-  line-height: 1.5;
-}
-</style>

+ 0 - 279
src/views/workflow/task/allTaskWaiting.vue

@@ -1,279 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
-        <el-card shadow="hover">
-          <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item>
-              <el-badge :value="userSelectCount" :max="10" class="item">
-                <el-button type="primary" @click="openUserSelect">选择申请人</el-button>
-              </el-badge>
-            </el-form-item>
-            <el-form-item label="任务名称" prop="nodeName">
-              <el-input v-model="queryParams.nodeName" placeholder="请输入任务名称" @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="流程定义名称" label-width="100" prop="flowName">
-              <el-input v-model="queryParams.flowName" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
-      </div>
-    </transition>
-    <el-card shadow="hover">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5" v-if="tab === 'waiting'">
-            <el-button type="primary" plain icon="Edit" :disabled="multiple" @click="handleUserOpen()">修改办理人 </el-button>
-            <el-button type="primary" plain icon="Bell" :disabled="multiple" @click="handleUrgeTaskOpen()">催办 </el-button>
-          </el-col>
-          <right-toolbar v-model:show-search="showSearch" @query-table="handleQuery"></right-toolbar>
-        </el-row>
-      </template>
-      <el-tabs v-model="tab" @tab-click="changeTab">
-        <el-tab-pane name="waiting" label="待办任务"> </el-tab-pane>
-        <el-tab-pane name="finish" label="已办任务"> </el-tab-pane>
-        <el-table v-loading="loading" border :data="taskList" @selection-change="handleSelectionChange">
-          <el-table-column type="selection" width="55" align="center" />
-          <el-table-column align="center" type="index" label="序号" width="60"></el-table-column>
-          <el-table-column :show-overflow-tooltip="true" prop="businessCode" align="center" label="业务编码"></el-table-column>
-          <el-table-column :show-overflow-tooltip="true" prop="businessTitle" align="center" label="业务标题"></el-table-column>
-          <el-table-column :show-overflow-tooltip="true" prop="flowName" align="center" width="120" label="流程定义名称"></el-table-column>
-          <el-table-column align="center" prop="flowCode" width="120" label="流程定义编码"></el-table-column>
-          <el-table-column align="center" prop="categoryName" label="流程分类"></el-table-column>
-          <el-table-column align="center" prop="version" label="版本号" width="90">
-            <template #default="scope"> v{{ scope.row.version }}.0</template>
-          </el-table-column>
-          <el-table-column align="center" prop="nodeName" :show-overflow-tooltip="true" label="任务名称"></el-table-column>
-          <el-table-column align="center" prop="createByName" :show-overflow-tooltip="true" label="申请人"></el-table-column>
-          <el-table-column align="center" label="办理人">
-            <template #default="scope">
-              <template v-if="tab === 'waiting'">
-                <template v-if="scope.row.assigneeNames">
-                  <el-tag v-for="(name, index) in scope.row.assigneeNames.split(',')" :key="index" type="success">
-                    {{ name }}
-                  </el-tag>
-                </template>
-                <template v-else>
-                  <el-tag type="success"> 无</el-tag>
-                </template>
-              </template>
-              <template v-else>
-                <el-tag type="success"> {{ scope.row.approveName }}</el-tag>
-              </template>
-            </template>
-          </el-table-column>
-          <el-table-column align="center" label="流程状态" prop="flowStatus" min-width="70">
-            <template #default="scope">
-              <dict-tag :options="wf_business_status" :value="scope.row.flowStatus"></dict-tag>
-            </template>
-          </el-table-column>
-          <el-table-column v-if="tab === 'finish'" align="center" label="任务状态" prop="flowTaskStatus" min-width="70">
-            <template #default="scope">
-              <dict-tag :options="wf_task_status" :value="scope.row.flowTaskStatus"></dict-tag>
-            </template>
-          </el-table-column>
-          <el-table-column align="center" prop="createTime" label="创建时间" width="160"></el-table-column>
-          <el-table-column label="操作" align="center" :width="tab === 'finish' ? '88' : '188'">
-            <template #default="scope">
-              <el-row :gutter="10" class="mb8">
-                <el-col :span="1.5" v-if="tab === 'waiting' || tab === 'finish'">
-                  <el-button type="primary" size="small" icon="View" @click="handleView(scope.row)">查看</el-button>
-                </el-col>
-                <el-col :span="1.5" v-if="tab === 'waiting'">
-                  <el-button type="primary" size="small" icon="Setting" @click="handleMeddle(scope.row)">流程干预 </el-button>
-                </el-col>
-              </el-row>
-            </template>
-          </el-table-column>
-        </el-table>
-        <pagination
-          v-show="total > 0"
-          v-model:page="queryParams.pageNum"
-          v-model:limit="queryParams.pageSize"
-          :total="total"
-          @pagination="handleQuery"
-        />
-      </el-tabs>
-    </el-card>
-    <!-- 选人组件 -->
-    <UserSelect ref="userSelectRef" :multiple="userMultiple" @confirm-call-back="submitCallback"></UserSelect>
-    <!-- 流程干预组件 -->
-    <processMeddle ref="processMeddleRef" @submitCallback="getWaitingList"></processMeddle>
-    <!-- 申请人 -->
-    <UserSelect ref="applyUserSelectRef" :multiple="true" :data="selectUserIds" @confirm-call-back="userSelectCallBack"></UserSelect>
-    <!-- 流程干预组件 -->
-    <messageType ref="messageTypeRef" @submitCallback="handleUserTask"></messageType>
-  </div>
-</template>
-
-<script setup lang="ts">
-import { pageByAllTaskWait, pageByAllTaskFinish, updateAssignee, urgeTask } from '@/api/workflow/task';
-import UserSelect from '@/components/UserSelect';
-import { TaskQuery } from '@/api/workflow/task/types';
-import workflowCommon from '@/api/workflow/workflowCommon';
-import { RouterJumpVo } from '@/api/workflow/workflowCommon/types';
-import processMeddle from '@/components/Process/processMeddle';
-import messageType from '@/components/Process/MessageType';
-import { UserVO } from '@/api/system/user/types';
-import { TabsPaneContext } from 'element-plus';
-//选人组件
-const userSelectRef = ref<InstanceType<typeof UserSelect>>();
-//流程干预组件
-const processMeddleRef = ref<InstanceType<typeof processMeddle>>();
-//选人组件
-const applyUserSelectRef = ref<InstanceType<typeof UserSelect>>();
-//消息组件
-const messageTypeRef = ref<InstanceType<typeof messageType>>();
-const queryFormRef = ref<ElFormInstance>();
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status'));
-const { wf_task_status } = toRefs<any>(proxy?.useDict('wf_task_status'));
-// 遮罩层
-const loading = ref(true);
-// 选中数组
-const ids = ref<Array<any>>([]);
-// 非单个禁用
-const single = ref(true);
-// 非多个禁用
-const multiple = ref(true);
-const userMultiple = ref(false);
-// 显示搜索条件
-const showSearch = ref(true);
-// 总条数
-const total = ref(0);
-// 模型定义表格数据
-const taskList = ref([]);
-const buttonType = ref('');
-//申请人id
-const selectUserIds = ref<Array<number | string>>([]);
-//申请人选择数量
-const userSelectCount = ref(0);
-// 查询参数
-const queryParams = ref<TaskQuery>({
-  pageNum: 1,
-  pageSize: 10,
-  nodeName: undefined,
-  flowName: undefined,
-  flowCode: undefined,
-  createByIds: []
-});
-const tab = ref('waiting');
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  if ('waiting' === tab.value) {
-    getWaitingList();
-  } else {
-    getFinishList();
-  }
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  queryParams.value.pageNum = 1;
-  queryParams.value.pageSize = 10;
-  queryParams.value.createByIds = [];
-  userSelectCount.value = 0;
-  selectUserIds.value = [];
-  handleQuery();
-};
-// 多选框选中数据
-const handleSelectionChange = (selection: any) => {
-  ids.value = selection.map((item: any) => item.id);
-  single.value = selection.length !== 1;
-  multiple.value = !selection.length;
-};
-const changeTab = async (data: TabsPaneContext) => {
-  taskList.value = [];
-  queryParams.value.pageNum = 1;
-  if ('waiting' === data.paneName) {
-    getWaitingList();
-  } else {
-    getFinishList();
-  }
-};
-//分页
-const getWaitingList = () => {
-  loading.value = true;
-  pageByAllTaskWait(queryParams.value).then((resp) => {
-    taskList.value = resp.rows;
-    total.value = resp.total;
-    loading.value = false;
-  });
-};
-const getFinishList = () => {
-  loading.value = true;
-  pageByAllTaskFinish(queryParams.value).then((resp) => {
-    taskList.value = resp.rows;
-    total.value = resp.total;
-    loading.value = false;
-  });
-};
-// 打开催办
-const handleUrgeTaskOpen = () => {
-  messageTypeRef.value.open();
-};
-//打开修改选人
-const handleUserOpen = () => {
-  userSelectRef.value.open();
-};
-
-//打开修改选人
-const handleUserTask = async (data) => {
-  await proxy?.$modal.confirm('是否确认提交?');
-  data.taskIdList = ids.value;
-  await urgeTask(data);
-  messageTypeRef.value.close();
-  proxy?.$modal.msgSuccess('操作成功');
-  handleQuery();
-};
-//修改办理人
-const submitCallback = async (data) => {
-  if (data && data.length > 0) {
-    await proxy?.$modal.confirm('是否确认提交?');
-    loading.value = true;
-    await updateAssignee(ids.value, data[0].userId);
-    handleQuery();
-    proxy?.$modal.msgSuccess('操作成功');
-  } else {
-    proxy?.$modal.msgWarning('请选择用户!');
-  }
-};
-/** 查看按钮操作 */
-const handleView = (row) => {
-  const routerJumpVo = reactive<RouterJumpVo>({
-    businessId: row.businessId,
-    taskId: row.id,
-    type: 'view',
-    formCustom: row.formCustom,
-    formPath: row.formPath
-  });
-  workflowCommon.routerJump(routerJumpVo, proxy);
-};
-const handleMeddle = (row) => {
-  processMeddleRef.value.open(row.id);
-};
-//打开申请人选择
-const openUserSelect = () => {
-  applyUserSelectRef.value.open();
-};
-//确认选择申请人
-const userSelectCallBack = (data: UserVO[]) => {
-  userSelectCount.value = 0;
-  selectUserIds.value = [];
-  queryParams.value.createByIds = [];
-
-  if (data && data.length > 0) {
-    userSelectCount.value = data.length;
-    selectUserIds.value = data.map((item) => item.userId);
-    queryParams.value.createByIds = selectUserIds.value;
-  }
-};
-onMounted(() => {
-  getWaitingList();
-});
-</script>

+ 0 - 246
src/views/workflow/task/myDocument.vue

@@ -1,246 +0,0 @@
-<template>
-  <div class="p-2">
-    <el-row :gutter="20">
-      <!-- 流程分类树 -->
-      <el-col :lg="4" :xs="24" style="">
-        <el-card shadow="hover">
-          <el-input v-model="categoryName" placeholder="请输入流程分类名" prefix-icon="Search" clearable />
-          <el-tree
-            ref="categoryTreeRef"
-            class="mt-2"
-            node-key="id"
-            :data="categoryOptions"
-            :props="{ label: 'label', children: 'children' } as any"
-            :expand-on-click-node="false"
-            :filter-node-method="filterNode"
-            highlight-current
-            default-expand-all
-            @node-click="handleNodeClick"
-          ></el-tree>
-        </el-card>
-      </el-col>
-      <el-col :lg="20" :xs="24">
-        <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-          <div v-show="showSearch" class="mb-[10px]">
-            <el-card shadow="hover">
-              <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true" label-width="120px">
-                <el-form-item label="流程定义编码" prop="flowCode">
-                  <el-input v-model="queryParams.flowCode" placeholder="请输入流程定义编码" @keyup.enter="handleQuery" />
-                </el-form-item>
-                <el-form-item>
-                  <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-                  <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-                </el-form-item>
-              </el-form>
-            </el-card>
-          </div>
-        </transition>
-        <el-card shadow="hover">
-          <template #header>
-            <el-row :gutter="10" class="mb8">
-              <right-toolbar v-model:show-search="showSearch" @query-table="handleQuery"></right-toolbar>
-            </el-row>
-          </template>
-
-          <el-table v-loading="loading" border :data="processInstanceList" @selection-change="handleSelectionChange">
-            <el-table-column type="selection" width="55" align="center" />
-            <el-table-column align="center" type="index" label="序号" width="60"></el-table-column>
-            <el-table-column v-if="false" align="center" prop="id" label="id"></el-table-column>
-            <el-table-column :show-overflow-tooltip="true" prop="flowName" align="center" label="流程定义名称"> </el-table-column>
-            <el-table-column align="center" prop="flowCode" label="流程定义编码"></el-table-column>
-            <el-table-column align="center" prop="categoryName" label="流程分类"></el-table-column>
-            <el-table-column align="center" prop="version" label="版本号" width="90">
-              <template #default="scope"> v{{ scope.row.version }}.0</template>
-            </el-table-column>
-            <el-table-column v-if="tab === 'running'" align="center" prop="isSuspended" label="状态" min-width="70">
-              <template #default="scope">
-                <el-tag v-if="!scope.row.isSuspended" type="success">激活</el-tag>
-                <el-tag v-else type="danger">挂起</el-tag>
-              </template>
-            </el-table-column>
-            <el-table-column align="center" label="流程状态" min-width="70">
-              <template #default="scope">
-                <dict-tag :options="wf_business_status" :value="scope.row.flowStatus"></dict-tag>
-              </template>
-            </el-table-column>
-            <el-table-column align="center" prop="createTime" label="启动时间" width="160"></el-table-column>
-            <el-table-column label="操作" align="center" width="162">
-              <template #default="scope">
-                <el-row :gutter="10" class="mb8">
-                  <el-col :span="1.5" v-if="scope.row.flowStatus === 'draft' || scope.row.flowStatus === 'cancel' || scope.row.flowStatus === 'back'">
-                    <el-button type="primary" size="small" icon="Edit" @click="handleOpen(scope.row, 'update')">编辑</el-button>
-                  </el-col>
-                  <el-col :span="1.5" v-if="scope.row.flowStatus === 'draft' || scope.row.flowStatus === 'cancel' || scope.row.flowStatus === 'back'">
-                    <el-button type="primary" size="small" icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
-                  </el-col>
-                </el-row>
-                <el-row :gutter="10" class="mb8">
-                  <el-col :span="1.5">
-                    <el-button type="primary" size="small" icon="View" @click="handleOpen(scope.row, 'view')">查看</el-button>
-                  </el-col>
-                  <el-col :span="1.5" v-if="scope.row.flowStatus === 'waiting'">
-                    <el-button type="primary" size="small" icon="Notification" @click="handleCancelProcessApply(scope.row.businessId)"
-                      >撤销</el-button
-                    >
-                  </el-col>
-                </el-row>
-              </template>
-            </el-table-column>
-          </el-table>
-          <pagination
-            v-show="total > 0"
-            v-model:page="queryParams.pageNum"
-            v-model:limit="queryParams.pageSize"
-            :total="total"
-            @pagination="getList"
-          />
-        </el-card>
-      </el-col>
-    </el-row>
-    <!-- 提交组件 -->
-    <submitVerify ref="submitVerifyRef" @submit-callback="getList" />
-  </div>
-</template>
-
-<script setup lang="ts">
-import { pageByCurrent, deleteByInstanceIds, cancelProcessApply } from '@/api/workflow/instance';
-import { categoryTree } from '@/api/workflow/category';
-import { CategoryTreeVO } from '@/api/workflow/category/types';
-import { FlowInstanceQuery, FlowInstanceVO } from '@/api/workflow/instance/types';
-import workflowCommon from '@/api/workflow/workflowCommon';
-import { RouterJumpVo } from '@/api/workflow/workflowCommon/types';
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status'));
-const queryFormRef = ref<ElFormInstance>();
-const categoryTreeRef = ref<ElTreeInstance>();
-
-// 遮罩层
-const loading = ref(true);
-// 选中数组
-const businessIds = ref<Array<number | string>>([]);
-const instanceIds = ref<Array<number | string>>([]);
-// 非单个禁用
-const single = ref(true);
-// 非多个禁用
-const multiple = ref(true);
-// 显示搜索条件
-const showSearch = ref(true);
-// 总条数
-const total = ref(0);
-// 模型定义表格数据
-const processInstanceList = ref<FlowInstanceVO[]>([]);
-
-const categoryOptions = ref<CategoryTreeVO[]>([]);
-const categoryName = ref('');
-
-const tab = ref('running');
-// 查询参数
-const queryParams = ref<FlowInstanceQuery>({
-  pageNum: 1,
-  pageSize: 10,
-  flowCode: undefined,
-  category: undefined
-});
-
-onMounted(() => {
-  getList();
-  getTreeselect();
-});
-
-/** 节点单击事件 */
-const handleNodeClick = (data: CategoryTreeVO) => {
-  queryParams.value.category = data.id;
-  if (data.id === '0') {
-    queryParams.value.category = '';
-  }
-  handleQuery();
-};
-/** 通过条件过滤节点  */
-const filterNode = (value: string, data: any) => {
-  if (!value) return true;
-  return data.categoryName.indexOf(value) !== -1;
-};
-/** 根据名称筛选部门树 */
-watchEffect(
-  () => {
-    categoryTreeRef.value.filter(categoryName.value);
-  },
-  {
-    flush: 'post' // watchEffect会在DOM挂载或者更新之前就会触发,此属性控制在DOM元素更新后运行
-  }
-);
-
-/** 查询流程分类下拉树结构 */
-const getTreeselect = async () => {
-  const res = await categoryTree();
-  categoryOptions.value = res.data;
-};
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  getList();
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  queryParams.value.category = '';
-  queryParams.value.pageNum = 1;
-  queryParams.value.pageSize = 10;
-  handleQuery();
-};
-// 多选框选中数据
-const handleSelectionChange = (selection: FlowInstanceVO[]) => {
-  businessIds.value = selection.map((item: any) => item.businessId);
-  instanceIds.value = selection.map((item: FlowInstanceVO) => item.id);
-  single.value = selection.length !== 1;
-  multiple.value = !selection.length;
-};
-//分页
-const getList = () => {
-  loading.value = true;
-  pageByCurrent(queryParams.value).then((resp) => {
-    processInstanceList.value = resp.rows;
-    total.value = resp.total;
-    loading.value = false;
-  });
-};
-
-/** 删除按钮操作 */
-const handleDelete = async (row: FlowInstanceVO) => {
-  const instanceIdList = row.id || instanceIds.value;
-  await proxy?.$modal.confirm('是否确认删除?');
-  loading.value = true;
-  if ('running' === tab.value) {
-    await deleteByInstanceIds(instanceIdList).finally(() => (loading.value = false));
-    getList();
-  }
-  proxy?.$modal.msgSuccess('删除成功');
-};
-
-/** 撤销按钮操作 */
-const handleCancelProcessApply = async (businessId: string) => {
-  await proxy?.$modal.confirm('是否确认撤销当前单据?');
-  loading.value = true;
-  if ('running' === tab.value) {
-    const data = {
-      businessId: businessId,
-      message: '申请人撤销流程!'
-    };
-    await cancelProcessApply(data).finally(() => (loading.value = false));
-    getList();
-  }
-  proxy?.$modal.msgSuccess('撤销成功');
-};
-
-//办理
-const handleOpen = async (row, type) => {
-  const routerJumpVo = reactive<RouterJumpVo>({
-    businessId: row.businessId,
-    taskId: row.id,
-    type: type,
-    formCustom: row.formCustom,
-    formPath: row.formPath
-  });
-  workflowCommon.routerJump(routerJumpVo, proxy);
-};
-</script>

+ 0 - 138
src/views/workflow/task/taskCopyList.vue

@@ -1,138 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
-        <el-card shadow="hover">
-          <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item label="任务名称" prop="nodeName">
-              <el-input v-model="queryParams.nodeName" placeholder="请输入任务名称" @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="流程定义名称" label-width="100" prop="flowName">
-              <el-input v-model="queryParams.flowName" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="流程定义编码" label-width="100" prop="flowCode">
-              <el-input v-model="queryParams.flowCode" placeholder="请输入流程定义编码" @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
-      </div>
-    </transition>
-    <el-card shadow="hover">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <right-toolbar v-model:show-search="showSearch" @query-table="handleQuery"></right-toolbar>
-        </el-row>
-      </template>
-
-      <el-table v-loading="loading" border :data="taskList" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column align="center" type="index" label="序号" width="60"></el-table-column>
-        <el-table-column :show-overflow-tooltip="true" prop="businessCode" align="center" label="业务编码"></el-table-column>
-        <el-table-column :show-overflow-tooltip="true" prop="businessTitle" align="center" label="业务标题"></el-table-column>
-        <el-table-column :show-overflow-tooltip="true" prop="flowName" align="center" label="流程定义名称"></el-table-column>
-        <el-table-column align="center" prop="flowCode" label="流程定义编码"></el-table-column>
-        <el-table-column align="center" prop="categoryName" label="流程分类"></el-table-column>
-        <el-table-column align="center" prop="version" label="版本号" width="90">
-          <template #default="scope"> v{{ scope.row.version }}.0</template>
-        </el-table-column>
-        <el-table-column align="center" prop="nodeName" label="任务名称"></el-table-column>
-        <el-table-column align="center" label="流程状态" min-width="70">
-          <template #default="scope">
-            <dict-tag :options="wf_business_status" :value="scope.row.flowStatus"></dict-tag>
-          </template>
-        </el-table-column>
-        <el-table-column label="操作" align="center" width="200">
-          <template #default="scope">
-            <el-button type="primary" size="small" icon="View" @click="handleView(scope.row)">查看</el-button>
-          </template>
-        </el-table-column>
-      </el-table>
-      <pagination
-        v-show="total > 0"
-        v-model:page="queryParams.pageNum"
-        v-model:limit="queryParams.pageSize"
-        :total="total"
-        @pagination="handleQuery"
-      />
-    </el-card>
-  </div>
-</template>
-
-<script setup lang="ts">
-import { pageByTaskCopy } from '@/api/workflow/task';
-import { TaskQuery } from '@/api/workflow/task/types';
-import workflowCommon from '@/api/workflow/workflowCommon';
-import { RouterJumpVo } from '@/api/workflow/workflowCommon/types';
-//审批记录组件
-const queryFormRef = ref<ElFormInstance>();
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status'));
-// 遮罩层
-const loading = ref(true);
-// 选中数组
-const ids = ref<Array<any>>([]);
-// 非单个禁用
-const single = ref(true);
-// 非多个禁用
-const multiple = ref(true);
-// 显示搜索条件
-const showSearch = ref(true);
-// 总条数
-const total = ref(0);
-// 模型定义表格数据
-const taskList = ref([]);
-// 查询参数
-const queryParams = ref<TaskQuery>({
-  pageNum: 1,
-  pageSize: 10,
-  nodeName: undefined,
-  flowName: undefined,
-  flowCode: undefined
-});
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  getTaskCopyList();
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  queryParams.value.pageNum = 1;
-  queryParams.value.pageSize = 10;
-  handleQuery();
-};
-// 多选框选中数据
-const handleSelectionChange = (selection: any) => {
-  ids.value = selection.map((item: any) => item.id);
-  single.value = selection.length !== 1;
-  multiple.value = !selection.length;
-};
-//分页
-const getTaskCopyList = () => {
-  loading.value = true;
-  pageByTaskCopy(queryParams.value).then((resp) => {
-    taskList.value = resp.rows;
-    total.value = resp.total;
-    loading.value = false;
-  });
-};
-
-/** 查看按钮操作 */
-const handleView = (row) => {
-  const routerJumpVo = reactive<RouterJumpVo>({
-    businessId: row.businessId,
-    taskId: row.id,
-    type: 'view',
-    formCustom: row.formCustom,
-    formPath: row.formPath
-  });
-  workflowCommon.routerJump(routerJumpVo, proxy);
-};
-
-onMounted(() => {
-  getTaskCopyList();
-});
-</script>

+ 0 - 186
src/views/workflow/task/taskFinish.vue

@@ -1,186 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
-        <el-card shadow="hover">
-          <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item>
-              <el-badge :value="userSelectCount" :max="10" class="item">
-                <el-button type="primary" @click="openUserSelect">选择申请人</el-button>
-              </el-badge>
-            </el-form-item>
-            <el-form-item label="任务名称" prop="nodeName">
-              <el-input v-model="queryParams.nodeName" placeholder="请输入任务名称" @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="流程定义名称" label-width="100" prop="flowName">
-              <el-input v-model="queryParams.flowName" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="流程定义编码" label-width="100" prop="flowCode">
-              <el-input v-model="queryParams.flowCode" placeholder="请输入流程定义编码" @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
-      </div>
-    </transition>
-    <el-card shadow="hover">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <right-toolbar v-model:show-search="showSearch" @query-table="handleQuery"></right-toolbar>
-        </el-row>
-      </template>
-
-      <el-table v-loading="loading" border :data="taskList" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column align="center" type="index" label="序号" width="60"></el-table-column>
-        <el-table-column :show-overflow-tooltip="true" prop="businessCode" align="center" label="业务编码"></el-table-column>
-        <el-table-column :show-overflow-tooltip="true" prop="businessTitle" align="center" label="业务标题"></el-table-column>
-        <el-table-column align="center" prop="flowName" width="120" label="流程定义名称"></el-table-column>
-        <el-table-column align="center" prop="flowCode" width="120" label="流程定义编码"></el-table-column>
-        <el-table-column align="center" prop="categoryName" label="流程分类"></el-table-column>
-        <el-table-column align="center" prop="version" label="版本号" width="90">
-          <template #default="scope"> v{{ scope.row.version }}.0</template>
-        </el-table-column>
-        <el-table-column align="center" prop="nodeName" :show-overflow-tooltip="true" label="任务名称"></el-table-column>
-        <el-table-column align="center" prop="createByName" :show-overflow-tooltip="true" label="申请人"></el-table-column>
-        <el-table-column align="center" prop="approverName" label="办理人">
-          <template #default="scope">
-            <el-tag type="success">
-              {{ scope.row.approveName || '无' }}
-            </el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column align="center" label="流程状态" prop="flowStatus" min-width="80">
-          <template #default="scope">
-            <dict-tag :options="wf_business_status" :value="scope.row.flowStatus"></dict-tag>
-          </template>
-        </el-table-column>
-        <el-table-column align="center" label="任务状态" prop="flowTaskStatus" min-width="80">
-          <template #default="scope">
-            <dict-tag :options="wf_task_status" :value="scope.row.flowTaskStatus"></dict-tag>
-          </template>
-        </el-table-column>
-        <el-table-column align="center" prop="createTime" label="创建时间" :show-overflow-tooltip="true" width="150"></el-table-column>
-        <el-table-column label="操作" align="center" width="200">
-          <template #default="scope">
-            <el-button type="primary" size="small" icon="View" @click="handleView(scope.row)">查看</el-button>
-          </template>
-        </el-table-column>
-      </el-table>
-      <pagination
-        v-show="total > 0"
-        v-model:page="queryParams.pageNum"
-        v-model:limit="queryParams.pageSize"
-        :total="total"
-        @pagination="handleQuery"
-      />
-    </el-card>
-    <!-- 申请人 -->
-    <UserSelect ref="userSelectRef" :multiple="true" :data="selectUserIds" @confirm-call-back="userSelectCallBack"></UserSelect>
-  </div>
-</template>
-
-<script setup lang="ts">
-import { pageByTaskFinish } from '@/api/workflow/task';
-import { TaskQuery, FlowTaskVO } from '@/api/workflow/task/types';
-import workflowCommon from '@/api/workflow/workflowCommon';
-import { RouterJumpVo } from '@/api/workflow/workflowCommon/types';
-//审批记录组件
-const queryFormRef = ref<ElFormInstance>();
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status'));
-const { wf_task_status } = toRefs<any>(proxy?.useDict('wf_task_status'));
-import UserSelect from '@/components/UserSelect';
-import { ref } from 'vue';
-import { UserVO } from '@/api/system/user/types';
-
-const userSelectRef = ref<InstanceType<typeof UserSelect>>();
-// 遮罩层
-const loading = ref(true);
-// 选中数组
-const ids = ref<Array<any>>([]);
-// 非单个禁用
-const single = ref(true);
-// 非多个禁用
-const multiple = ref(true);
-// 显示搜索条件
-const showSearch = ref(true);
-// 总条数
-const total = ref(0);
-// 模型定义表格数据
-const taskList = ref([]);
-// 查询参数
-const queryParams = ref<TaskQuery>({
-  pageNum: 1,
-  pageSize: 10,
-  nodeName: undefined,
-  flowName: undefined,
-  flowCode: undefined,
-  createByIds: []
-});
-//申请人id
-const selectUserIds = ref<Array<number | string>>([]);
-//申请人选择数量
-const userSelectCount = ref(0);
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  getFinishList();
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  queryParams.value.pageNum = 1;
-  queryParams.value.pageSize = 10;
-  queryParams.value.createByIds = [];
-  userSelectCount.value = 0;
-  selectUserIds.value = [];
-  handleQuery();
-};
-// 多选框选中数据
-const handleSelectionChange = (selection: any) => {
-  ids.value = selection.map((item: any) => item.id);
-  single.value = selection.length !== 1;
-  multiple.value = !selection.length;
-};
-const getFinishList = () => {
-  loading.value = true;
-  pageByTaskFinish(queryParams.value).then((resp) => {
-    taskList.value = resp.rows;
-    total.value = resp.total;
-    loading.value = false;
-  });
-};
-/** 查看按钮操作 */
-const handleView = (row: FlowTaskVO) => {
-  const routerJumpVo = reactive<RouterJumpVo>({
-    businessId: row.businessId,
-    taskId: row.id,
-    type: 'view',
-    formCustom: row.formCustom,
-    formPath: row.formPath
-  });
-  workflowCommon.routerJump(routerJumpVo, proxy);
-};
-//打开申请人选择
-const openUserSelect = () => {
-  userSelectRef.value.open();
-};
-//确认选择申请人
-const userSelectCallBack = (data: UserVO[]) => {
-  userSelectCount.value = 0;
-  selectUserIds.value = [];
-  queryParams.value.createByIds = [];
-
-  if (data && data.length > 0) {
-    userSelectCount.value = data.length;
-    selectUserIds.value = data.map((item) => item.userId);
-    queryParams.value.createByIds = selectUserIds.value;
-  }
-};
-onMounted(() => {
-  getFinishList();
-});
-</script>

+ 0 - 185
src/views/workflow/task/taskWaiting.vue

@@ -1,185 +0,0 @@
-<template>
-  <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
-        <el-card shadow="hover">
-          <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-form-item>
-              <el-badge :value="userSelectCount" :max="10" class="item">
-                <el-button type="primary" @click="openUserSelect">选择申请人</el-button>
-              </el-badge>
-            </el-form-item>
-            <el-form-item label="任务名称" prop="nodeName">
-              <el-input v-model="queryParams.nodeName" placeholder="请输入任务名称" @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="流程定义名称" label-width="100" prop="flowName">
-              <el-input v-model="queryParams.flowName" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item label="流程定义编码" label-width="100" prop="flowCode">
-              <el-input v-model="queryParams.flowCode" placeholder="请输入流程定义编码" @keyup.enter="handleQuery" />
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-card>
-      </div>
-    </transition>
-    <el-card shadow="hover">
-      <template #header>
-        <el-row :gutter="10" class="mb8">
-          <right-toolbar v-model:show-search="showSearch" @query-table="handleQuery"></right-toolbar>
-        </el-row>
-      </template>
-
-      <el-table v-loading="loading" border :data="taskList" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column align="center" type="index" label="序号" width="60"></el-table-column>
-        <el-table-column :show-overflow-tooltip="true" prop="businessCode" align="center" label="业务编码"></el-table-column>
-        <el-table-column :show-overflow-tooltip="true" prop="businessTitle" align="center" label="业务标题"></el-table-column>
-        <el-table-column :show-overflow-tooltip="true" prop="flowName" align="center" label="流程定义名称"></el-table-column>
-        <el-table-column align="center" prop="flowCode" label="流程定义编码"></el-table-column>
-        <el-table-column align="center" prop="categoryName" label="流程分类"></el-table-column>
-        <el-table-column align="center" prop="nodeName" label="任务名称"></el-table-column>
-        <el-table-column align="center" prop="createByName" label="申请人"></el-table-column>
-        <el-table-column align="center" label="办理人">
-          <template #default="scope">
-            <template v-if="scope.row.assigneeNames">
-              <el-tag v-for="(name, index) in scope.row.assigneeNames.split(',')" :key="index" type="success">
-                {{ name }}
-              </el-tag>
-            </template>
-            <template v-else>
-              <el-tag type="success"> 无</el-tag>
-            </template>
-          </template>
-        </el-table-column>
-        <el-table-column align="center" label="流程状态" prop="flowStatusName" min-width="70">
-          <template #default="scope">
-            <dict-tag :options="wf_business_status" :value="scope.row.flowStatus"></dict-tag>
-          </template>
-        </el-table-column>
-        <el-table-column align="center" prop="createTime" label="创建时间" width="160"></el-table-column>
-        <el-table-column label="操作" align="center" width="200">
-          <template #default="scope">
-            <el-button type="primary" size="small" icon="Edit" @click="handleOpen(scope.row)">办理</el-button>
-          </template>
-        </el-table-column>
-      </el-table>
-      <pagination
-        v-show="total > 0"
-        v-model:page="queryParams.pageNum"
-        v-model:limit="queryParams.pageSize"
-        :total="total"
-        @pagination="handleQuery"
-      />
-    </el-card>
-    <!-- 申请人 -->
-    <UserSelect ref="userSelectRef" :multiple="true" :data="selectUserIds" @confirm-call-back="userSelectCallBack"></UserSelect>
-  </div>
-</template>
-
-<script setup lang="ts">
-import { pageByTaskWait } from '@/api/workflow/task';
-import { TaskQuery, FlowTaskVO } from '@/api/workflow/task/types';
-import workflowCommon from '@/api/workflow/workflowCommon';
-import { RouterJumpVo } from '@/api/workflow/workflowCommon/types';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status'));
-import UserSelect from '@/components/UserSelect';
-import { ref } from 'vue';
-import { UserVO } from '@/api/system/user/types';
-
-const userSelectRef = ref<InstanceType<typeof UserSelect>>();
-//提交组件
-const queryFormRef = ref<ElFormInstance>();
-// 遮罩层
-const loading = ref(true);
-// 选中数组
-const ids = ref<Array<any>>([]);
-// 非单个禁用
-const single = ref(true);
-// 非多个禁用
-const multiple = ref(true);
-// 显示搜索条件
-const showSearch = ref(true);
-// 总条数
-const total = ref(0);
-// 模型定义表格数据
-const taskList = ref([]);
-
-//申请人id
-const selectUserIds = ref<Array<number | string>>([]);
-//申请人选择数量
-const userSelectCount = ref(0);
-// 查询参数
-const queryParams = ref<TaskQuery>({
-  pageNum: 1,
-  pageSize: 10,
-  nodeName: undefined,
-  flowName: undefined,
-  flowCode: undefined,
-  createByIds: []
-});
-onMounted(() => {
-  getWaitingList();
-});
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  getWaitingList();
-};
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  queryParams.value.pageNum = 1;
-  queryParams.value.pageSize = 10;
-  queryParams.value.createByIds = [];
-  userSelectCount.value = 0;
-  selectUserIds.value = [];
-  handleQuery();
-};
-// 多选框选中数据
-const handleSelectionChange = (selection: any) => {
-  ids.value = selection.map((item: any) => item.id);
-  single.value = selection.length !== 1;
-  multiple.value = !selection.length;
-};
-//分页
-const getWaitingList = () => {
-  loading.value = true;
-  pageByTaskWait(queryParams.value).then((resp) => {
-    taskList.value = resp.rows;
-    total.value = resp.total;
-    loading.value = false;
-  });
-};
-//办理
-const handleOpen = async (row: FlowTaskVO) => {
-  const routerJumpVo = reactive<RouterJumpVo>({
-    businessId: row.businessId,
-    taskId: row.id,
-    type: 'approval',
-    formCustom: row.formCustom,
-    formPath: row.formPath
-  });
-  workflowCommon.routerJump(routerJumpVo, proxy);
-};
-//打开申请人选择
-const openUserSelect = () => {
-  userSelectRef.value.open();
-};
-//确认选择申请人
-const userSelectCallBack = (data: UserVO[]) => {
-  userSelectCount.value = 0;
-  selectUserIds.value = [];
-  queryParams.value.createByIds = [];
-
-  if (data && data.length > 0) {
-    userSelectCount.value = data.length;
-    selectUserIds.value = data.map((item) => item.userId);
-    queryParams.value.createByIds = selectUserIds.value;
-  }
-};
-</script>