wanshenmean
2026-03-24 5953113240802cd0545fb94e6c4e6d413ece74cc
WMS新增缺失前端页面并接入路由
已添加9个文件
已删除2个文件
已修改4个文件
1047 ■■■■■ 文件已修改
.omc/sessions/e6b9225b-2892-4ba9-8585-7ee1b6e2ef6f.json 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.omc/state/hud-state.json 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.omc/state/hud-stdin-cache.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Client/.omc/project-memory.json 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Client/src/views/Index.vue 220 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/AGENTS.md 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/.yarn/install-state.gz 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/extension/outbound/outStockLockInfo.js 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/extension/stock/stock.js 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/extension/system/Sys_Tenant.js 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/router/viewGird.js 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/views/outbound/outStockLockInfo.vue 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/views/stock/stock.vue 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/views/system/PDA.vue 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/views/system/Sys_Tenant.vue 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.omc/sessions/e6b9225b-2892-4ba9-8585-7ee1b6e2ef6f.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,8 @@
{
  "session_id": "e6b9225b-2892-4ba9-8585-7ee1b6e2ef6f",
  "ended_at": "2026-03-24T03:25:50.783Z",
  "reason": "other",
  "agents_spawned": 0,
  "agents_completed": 0,
  "modes_used": []
}
.omc/state/hud-state.json
ÎļþÒÑɾ³ý
.omc/state/hud-stdin-cache.json
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_Client/.omc/project-memory.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,182 @@
{
  "version": "1.0.0",
  "lastScanned": 1774322743799,
  "projectRoot": "d:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Client",
  "techStack": {
    "languages": [
      {
        "name": "JavaScript/TypeScript",
        "version": null,
        "confidence": "high",
        "markers": [
          "package.json"
        ]
      }
    ],
    "frameworks": [
      {
        "name": "vue",
        "version": "3.2.37",
        "category": "frontend"
      },
      {
        "name": "vite",
        "version": "5.0.0",
        "category": "build"
      }
    ],
    "packageManager": "pnpm",
    "runtime": null
  },
  "build": {
    "buildCommand": "pnpm build",
    "testCommand": null,
    "lintCommand": "pnpm lint",
    "devCommand": null,
    "scripts": {
      "serve": "vite",
      "build": "vite build",
      "preview": "vite preview",
      "lint": "eslint --ext .js,.vue src"
    }
  },
  "conventions": {
    "namingStyle": null,
    "importStyle": null,
    "testPattern": null,
    "fileOrganization": "type-based"
  },
  "structure": {
    "isMonorepo": false,
    "workspaces": [],
    "mainDirectories": [
      "public",
      "src",
      "tests"
    ],
    "gitBranches": {
      "defaultBranch": "master",
      "branchingStrategy": null
    }
  },
  "customNotes": [],
  "directoryMap": {
    "config": {
      "path": "config",
      "purpose": "Configuration files",
      "fileCount": 1,
      "lastAccessed": 1774322743642,
      "keyFiles": [
        "buttons.js"
      ]
    },
    "dist": {
      "path": "dist",
      "purpose": "Distribution/build output",
      "fileCount": 3,
      "lastAccessed": 1774322743642,
      "keyFiles": [
        "index.html",
        "wcslogo.png",
        "wms_d.png"
      ]
    },
    "public": {
      "path": "public",
      "purpose": "Public files",
      "fileCount": 3,
      "lastAccessed": 1774322743680,
      "keyFiles": [
        "index.html",
        "wcslogo.png",
        "wms_d.png"
      ]
    },
    "src": {
      "path": "src",
      "purpose": "Source code",
      "fileCount": 2,
      "lastAccessed": 1774322743680,
      "keyFiles": [
        "App.vue",
        "main.js"
      ]
    },
    "tests": {
      "path": "tests",
      "purpose": "Test files",
      "fileCount": 0,
      "lastAccessed": 1774322743682,
      "keyFiles": []
    },
    "dist\\assets": {
      "path": "dist\\assets",
      "purpose": "Static assets",
      "fileCount": 80,
      "lastAccessed": 1774322743684,
      "keyFiles": [
        "401-D9QhAVFF.js",
        "404-DCIcd6re.js",
        "Audit-C52MvHzW.css"
      ]
    },
    "dist\\static": {
      "path": "dist\\static",
      "purpose": "Static files",
      "fileCount": 1,
      "lastAccessed": 1774322743684,
      "keyFiles": [
        "login_bg.png"
      ]
    },
    "public\\static": {
      "path": "public\\static",
      "purpose": "Static files",
      "fileCount": 1,
      "lastAccessed": 1774322743685,
      "keyFiles": [
        "login_bg.png"
      ]
    },
    "src\\api": {
      "path": "src\\api",
      "purpose": "API routes",
      "fileCount": 3,
      "lastAccessed": 1774322743686,
      "keyFiles": [
        "http.js",
        "permission.js",
        "useTest.js"
      ]
    },
    "src\\assets": {
      "path": "src\\assets",
      "purpose": "Static assets",
      "fileCount": 1,
      "lastAccessed": 1774322743687,
      "keyFiles": [
        "logo.png"
      ]
    },
    "src\\components": {
      "path": "src\\components",
      "purpose": "UI components",
      "fileCount": 0,
      "lastAccessed": 1774322743688,
      "keyFiles": []
    },
    "src\\views": {
      "path": "src\\views",
      "purpose": "View templates",
      "fileCount": 3,
      "lastAccessed": 1774322743689,
      "keyFiles": [
        "Home.vue",
        "Index.vue",
        "Login.vue"
      ]
    }
  },
  "hotPaths": [],
  "userDirectives": []
}
Code/WCS/WIDESEAWCS_Client/src/views/Index.vue
@@ -59,25 +59,25 @@
            <span style="display: none">{{ navIndex }}</span>
          </el-tab-pane>
        </el-tabs>
        <!-- å³é”®èœå• -->
        <!-- é™æŠ½æ•­é‘¿æ»ƒå´Ÿ -->
        <div v-show="contextMenuVisible">
          <ul :style="{ left: menuLeft + 'px', top: menuTop + 'px' }" class="contextMenu">
            <li v-show="visibleItem.all">
              <el-button link @click="closeTabs()">
                <i class="el-icon-close"></i>
                {{
                  navigation.length == 2 ? "关闭菜单" : "关闭所有"
                  navigation.length == 2 ? "鍏抽棴鑿滃崟" : "鍏抽棴鎵€鏈?
                }}</el-button>
            </li>
            <li v-show="visibleItem.left">
              <el-button link @click="closeTabs('left')"><i class="el-icon-back"></i>关闭左边</el-button>
              <el-button link @click="closeTabs('left')"><i class="el-icon-back"></i>鍏抽棴宸﹁竟</el-button>
            </li>
            <li v-show="visibleItem.right">
              <el-button link @click="closeTabs('right')">
                <i class="el-icon-right"></i>关闭右边</el-button>
                <i class="el-icon-right"></i>鍏抽棴鍙宠竟</el-button>
            </li>
            <li v-show="visibleItem.other">
              <el-button link @click="closeTabs('other')"><i class="el-icon-right"></i>关闭其他
              <el-button link @click="closeTabs('other')"><i class="el-icon-right"></i>鍏抽棴鍏朵粬
              </el-button>
            </li>
          </ul>
@@ -96,7 +96,7 @@
        </el-scrollbar>
      </div>
    </div>
    <el-drawer title="选择主题" v-model="drawer_model" direction="rtl" destroy-on-close>
    <el-drawer title="閫夋嫨涓婚" v-model="drawer_model" direction="rtl" destroy-on-close>
      <div class="theme-selector">
        <div @click="changeTheme(item.name)" class="item" v-for="(item, index) in theme_color" :key="index"
          :style="{ background: item.color }">
@@ -107,7 +107,7 @@
      </div>
    </el-drawer>
    <el-drawer title="消息列表" v-model="messageModel" direction="rtl" destroy-on-close>
    <el-drawer title="娑堟伅鍒楄〃" v-model="messageModel" direction="rtl" destroy-on-close>
      <Message :list="messageList"></Message>
    </el-drawer>
  </div>
@@ -151,14 +151,14 @@
      otherTabs: true,
      menuLeft: 0,
      menuTop: 0,
      //  contextMenuVisible: false, // å³é”®å…³é—­æ˜¾/隐
      //  contextMenuVisible: false, // é™æŠ½æ•­éæŠ½æ£´é„?闅?
    };
  },
  setup(props, context) {
    // èŽ·å–å…¨å±€å±žæ€§å’Œæ–¹æ³•
    // é‘¾å³°å½‡éã„¥çœ¬çžç‚´â‚¬Ñƒæ‹°é‚è§„ç¡¶
    const { proxy } = getCurrentInstance();
    // èœå•导航默认宽度
    // é‘¿æ»ƒå´Ÿç€µè‰°åŸ…榛樿瀹藉害
    const menuWidth = ref(200);
    const contextMenuVisible = ref(false);
    const isCollapse = ref(false);
@@ -178,23 +178,23 @@
    ]);
    const links = ref([
      // {
      //   text: "框架视频",
      //   text: "妗嗘灦瑙嗛",
      //   path: "https://www.cctalk.com/m/group/90268531",
      //   id: -3,
      // },
      // { text: "大屏数据", path: "/bigdata", id: -3 },
      // { text: "澶у睆鏁版嵁", path: "/bigdata", id: -3 },
      // {
      //   text: "框架文档",
      //   text: "妗嗘灦鏂囨。",
      //   path: "http://v2.volcore.xyz/document/guide",
      //   id: -2,
      // },   {
      //   text: "框架企业版",
      //   text: "妗嗘灦浼佷笟鐗?,
      //   path: "http://pro.volcore.xyz/",
      //   id: 10,
      // },
      { text: "个人中心", path: "/UserInfo", id: -1, icon: "el-icon-s-custom" },
      { text: "涓汉涓績", path: "/UserInfo", id: -1, icon: "el-icon-s-custom" },
      {
        text: "安全退出",
        text: "瀹夊叏閫€鍑?,
        path: "/login",
        id: -4,
        icon: "el-icon-switch-button",
@@ -204,9 +204,9 @@
      'this.src="' + errorImgSrc + '"'
    );
    const selectId = ref("1");
    // ã€é¦–页】标签序号(当前右键选中的菜单)
    // éŠ†æ„°î›»æ¤¤ç‚¹â‚¬æˆžçˆ£ç»›æƒ§ç°­é™?褰撳墠鍙抽敭閫変腑鐨勮彍鍗?
    const selectMenuIndex = ref("0");
    //2022.05.29增加tab选项与菜单联动功能
    //2022.05.29澧炲姞tab閫夐」涓庤彍鍗曡仈鍔ㄥ姛鑳?
    const currentMenuId = ref(0);
    const userName = ref("--");
    const userInfo = ref({});
@@ -218,7 +218,7 @@
    });
    const userImg = ref("");
    const navigation = reactive([
      { orderNo: "0", id: "1", name: "首页", path: "/home" },
      { orderNo: "0", id: "1", name: "棣栭〉", path: "/home" },
    ]);
    const logo = ref(imgUrl);
    const theme = ref("blue2");
@@ -231,7 +231,7 @@
      isCollapse.value = !isCollapse.value;
      menuWidth.value = isCollapse.value ? 63 : 200;
    };
    //2021.08.28开放手动折叠菜单方法
    //2021.08.28寮€鏀炬墜鍔ㄦ姌鍙犺彍鍗曟柟娉?
    _config.menu = {
      show() {
        toggleLeft();
@@ -247,14 +247,14 @@
      localStorage.setItem("vol3_theme", name);
    };
    const to = (item) => {
      /* 2020.07.31增加手动打开tabs*/
      /* 2020.07.31澧炲姞鎵嬪姩鎵撳紑tabs*/
      if (item.path.indexOf("http") != -1) {
        window.open(item.path);
        return;
      }
      if (typeof item == "string" || item.path == "/login") {
        if (item == "/login" || item.path == "/login") {
          //确认是否退出
          //纭鏄惁閫€鍑?
          store.commit("clearUserInfo", "");
          window.location.href = "/";
          return;
@@ -266,59 +266,59 @@
      open(item);
    };
    const open = (item, useRoute) => {
      /* 2020.07.31增加手动打开tabs*/
      /* 2020.07.31澧炲姞鎵嬪姩鎵撳紑tabs*/
      let _index = navigation.findIndex((x) => {
        return x.path == item.path;
      });
      if (_index == -1) {
        navigation.push({
          //  orderNo: String(navigation.length),// åºå·
          //  orderNo: String(navigation.length),// æ´å¿“彿
          id: item.id + "",
          name: item.name || item.text || "无标题",
          name: item.name || item.text || "鏃犳爣棰?,
          path: item.path,
          query: item.query, //2021.03.20修复自定义二次打开$tabs时参数丢失的问题
          query: item.query, //2021.03.20淇鑷畾涔変簩娆℃墦寮€$tabs鏃跺弬鏁颁涪澶辩殑闂
        });
        //新打开的tab移至最后一个选项
        //鏂版墦寮€鐨則ab绉昏嚦鏈€鍚庝竴涓€夐」
        selectId.value = navigation.length - 1 + "";
      } else {
        selectId.value = _index + "";
      }
      if (useRoute === undefined) {
        //非标准菜单,记录最后一次跳转的页面,用于刷新
        //闈炴爣鍑嗚彍鍗曪紝璁板綍鏈€鍚庝竴娆¤烦杞殑椤甸潰锛岀敤浜庡埛鏂?
        setItem(item);
        router.push(item);
        // this.$router.push(item);
      }
      currentMenuId.value = item.id * 1;
      // tab菜单绑定右键事件
      // tab鑿滃崟缁戝畾鍙抽敭浜嬩欢
      proxy.$nextTick(function (e) {
        proxy.bindRightClickMenu(true);
      });
    };
    const close = (path) => {
      /* 2020.07.31增加手动打开tabs*/
      /* 2020.07.31澧炲姞鎵嬪姩鎵撳紑tabs*/
      let index = navigation.findIndex((x) => {
        return x.path == path;
      });
      if (index == -1) {
        return _config.$Message.error("未找到菜单");
        return _config.$Message.error("鏈壘鍒拌彍鍗?);
      }
      removeNav(index);
    };
    const setItem = (item) => {
      /* 2020.07.31增加手动打开tabs*/
      /* 2020.07.31澧炲姞鎵嬪姩鎵撳紑tabs*/
      localStorage.setItem(
        window.location.origin + "_tabs",
        JSON.stringify(item)
      );
    };
    const getItem = () => {
      /* 2020.07.31增加手动打开tabs*/
      /* 2020.07.31澧炲姞鎵嬪姩鎵撳紑tabs*/
      let nav = localStorage.getItem(window.location.origin + "_tabs");
      return nav ? JSON.parse(nav) : null;
    };
    const selectNav = (item) => {
      //升级element正式版修改
      //鍗囩骇element姝e紡鐗堜慨鏀?
      selectId.value = item.props.name;
      let _path = navigation[item.index].path;
      currentMenuId.value = (
@@ -335,13 +335,13 @@
    const removeNav = (_index) => {
      return new Promise(() => {
        //关闭的当前项,跳转到前一个页面
        //鍏抽棴鐨勫綋鍓嶉」,璺宠浆鍒板墠涓€涓〉闈?
        if (selectId.value == _index + "") {
          console.log(navigation[_index - 1]);
          setItem(navigation[_index - 1]);
          router.push({
            path: navigation[_index - 1].path,
            //2022.06.27修复tabs二次切换后参数丢失的问题
            //2022.06.27淇tabs浜屾鍒囨崲鍚庡弬鏁颁涪澶辩殑闂
            query: navigation[_index - 1].query,
          });
          navigation.splice(_index, 1);
@@ -366,28 +366,28 @@
      });
    };
    const onSelect = (treeId) => {
      /* 2020.07.31增加手动打开tabs*/
      /* 2020.07.31澧炲姞鎵嬪姩鎵撳紑tabs*/
      var item = getSelectMenuName(treeId);
      open(item, false);
    };
    /**
     * æ˜¾ç¤ºå³é”®èœå•
     * @param {*} e äº‹ä»¶å¯¹è±¡
     * é„剧ず鍙抽敭鑿滃崟
     * @param {*} e æµœå¬©æ¬¢ç€µç¡…è–„
     */
    const openTabsMenu = function (e) {
      e.preventDefault(); // é˜²æ­¢é»˜è®¤èœå•弹出
      e.preventDefault(); // é—ƒå‰î„›æ¦›æ¨¿î…»é‘¿æ»ƒå´Ÿå¯®ç‘°åš­
      let tabId = e.target.id.split("-")[1] * 1;
      //记录当前选中的菜单index
      //璁板綍褰撳墠閫変腑鐨勮彍鍗昳ndex
      selectMenuIndex.value =
        document.getElementById("pane-" + tabId).children[0].textContent * 1;
      //只有首页时不显示
      //鍙湁棣栭〉鏃朵笉鏄剧ず
      if (navigation.length == 1) {
        return;
      }
      //首页设置显示关闭右边菜单
      //棣栭〉璁剧疆鏄剧ず鍏抽棴鍙宠竟鑿滃崟
      if (!selectMenuIndex.value) {
        visibleItem.all = false;
        visibleItem.right = true;
@@ -395,22 +395,22 @@
        visibleItem.other = false;
      } else {
        visibleItem.all = true;
        //不是最后一个显示关闭右边菜单
        //涓嶆槸鏈€鍚庝竴涓樉绀哄叧闂彸杈硅彍鍗?
        visibleItem.right = selectMenuIndex.value != navigation.length - 1;
        //只有两个菜单时不显示关闭左边
        //鍙湁涓や釜鑿滃崟鏃朵笉鏄剧ず鍏抽棴宸﹁竟
        visibleItem.left = navigation.length != 2;
        //只有两个菜单时不显示关闭其他
        //鍙湁涓や釜鑿滃崟鏃朵笉鏄剧ず鍏抽棴鍏朵粬
        visibleItem.other = navigation.length != 2;
      }
      contextMenuVisible.value = true;
      // è®¾ç½®å³é”®èœå•显示的位置
      // ç’å‰§ç–†é™æŠ½æ•­é‘¿æ»ƒå´Ÿé„剧ず鐨勪綅缃?
      proxy.menuLeft =
        e.target.getBoundingClientRect().left - (isCollapse.value ? 63 : 198); //-e.target.clientWidth
      proxy.menuTop = 36;
    };
    /**
     * å…³é—­å³é”®èœå•
     * éæŠ½æ£´é™æŠ½æ•­é‘¿æ»ƒå´Ÿ
     */
    const closeTabsMenu = () => {
      contextMenuVisible.value = false;
@@ -422,25 +422,25 @@
      });
    };
    /**
     * å…³é—­å…¶å®ƒæ ‡ç­¾é¡µ
     * @param {*} par å…³é—­ç±»åž‹(left,right,other)
     * éæŠ½æ£´éè·ºç• éå›©î„·æ¤¤?
     * @param {*} par éæŠ½æ£´ç»«è¯²ç€·(left,right,other)
     */
    const closeTabs = (value) => {
      let _menuId = navigation[selectId.value * 1].id;
      let currnetIndex = selectId.value * 1; // navigation.findIndex(c => { return c.id == selectId.value });
      switch (value) {
        case "left": {
          // åˆ é™¤å·¦ä¾§tab标签
          navigation.splice(1, currnetIndex - 1); // åˆ é™¤å·¦ä¾§tab标签
          // é’犻櫎宸︿晶tab鏍囩
          navigation.splice(1, currnetIndex - 1); // é’犻櫎宸︿晶tab鏍囩
          break;
        }
        case "right": {
          // åˆ é™¤å³ä¾§tab标签
          // é’犻櫎鍙充晶tab鏍囩
          if (selectMenuIndex.value == 0) {
            navigation.splice(currnetIndex); // åˆ é™¤å³ä¾§tab标签
            navigation.splice(currnetIndex); // é’犻櫎鍙充晶tab鏍囩
            toHome();
          } else {
            navigation.splice(currnetIndex + 1); // åˆ é™¤å³ä¾§tab标签
            navigation.splice(currnetIndex + 1); // é’犻櫎鍙充晶tab鏍囩
            if (selectMenuIndex.value < currnetIndex) {
              navigation.splice(
                selectMenuIndex.value,
@@ -451,13 +451,13 @@
          break;
        }
        case "other": {
          // åˆ é™¤å…¶ä»–所有tab标签
          navigation.splice(currnetIndex + 1); // åˆ é™¤å³ä¾§tab标签(这里必须按照右→左顺序删除)
          navigation.splice(1, currnetIndex - 1); // åˆ é™¤å·¦ä¾§tab标签
          // é’犻櫎鍏朵粬鎵€鏈塼ab鏍囩
          navigation.splice(currnetIndex + 1); // é’犻櫎鍙充晶tab鏍囩(杩欓噷蹇呴』鎸夌収鍙斥啋宸﹂『搴忓垹闄?
          navigation.splice(1, currnetIndex - 1); // é’犻櫎宸︿晶tab鏍囩
          break;
        }
        default: {
          //关闭所有
          //鍏抽棴鎵€鏈?
          navigation.splice(1, navigation.length);
          toHome();
          break;
@@ -473,7 +473,7 @@
    watch(
      () => contextMenuVisible.value,
      (newVal, oldVal) => {
        // ç›‘视
        // é©æˆ£î‹
        if (newVal) {
          document.body.addEventListener("click", closeTabsMenu);
        } else {
@@ -483,8 +483,63 @@
    );
    /**
     * ç³»ç»Ÿåˆ›å»ºå¼€å§‹
     * ç»¯è¤ç²ºé’涘缓寮€濮?
     */
    /**
     * æ–¹æ³•目的:补齐后端菜单未配置时的新页面入口,避免新增页面无入口。
     * å‚数含义:data ä¸ºåŽç«¯è¿”回的菜单数组。
     * è¿”回值:返回补齐后的菜单数组。
     * å…³é”®é€»è¾‘:仅在菜单中不存在相同 url æ—¶è¿½åŠ é»˜è®¤èœå•ï¼Œé¿å…è¦†ç›–å·²æœ‰é…ç½®ã€‚
     * å¼‚常处理:该方法仅操作内存数据,不涉及外部调用,异常由上层流程统一捕获。
     */
    const ensureBuiltinMenus = (data) => {
      const menus = Array.isArray(data) ? data : [];
      const exists = (url) => menus.some((m) => (m.url || "") === url);
      const maxId = menus.reduce((max, item) => {
        const current = Number(item.id);
        return Number.isFinite(current) ? Math.max(max, current) : max;
      }, 0);
      const defaultMenus = [
        {
          id: maxId + 1001,
          name: "租户管理",
          url: "/Sys_Tenant",
          parentId: 0,
          icon: "el-icon-office-building",
          enable: 1,
          tableName: "Sys_Tenant",
          permission: ["Search", "Add", "Update", "Delete"],
        },
        {
          id: maxId + 1002,
          name: "任务历史",
          url: "/taskHty",
          parentId: 0,
          icon: "el-icon-time",
          enable: 1,
          tableName: "taskHty",
          permission: ["Search", "Export"],
        },
        {
          id: maxId + 1003,
          name: "调度控制",
          url: "/scheduler",
          parentId: 0,
          icon: "el-icon-video-play",
          enable: 1,
          tableName: "scheduler",
          permission: ["Search", "Update"],
        },
      ];
      defaultMenus.forEach((menu) => {
        if (!exists(menu.url)) {
          menus.push(menu);
        }
      });
      return menus;
    };
    const created = () => {
      let _theme = localStorage.getItem("vol3_theme");
      if (_theme) {
@@ -501,7 +556,8 @@
      Object.assign(_config.$tabs, { open: open, close: close });
      http.get("api/Sys_Menu/getTreeMenu", {}, true).then((data) => {
        data.push({ id: "1", name: "首页", url: "/home" }); // ä¸ºäº†èŽ·å–é€‰ä¸­id使用
        data = ensureBuiltinMenus(data);
        data.push({ id: "1", name: "棣栭〉", url: "/home" }); // æ¶“轰簡鑾峰彇閫変腑id浣跨敤
        data.forEach((d) => {
          d.path = (d.url || "").replace("/Manager", "");
          d.to = (d.url || "").replace("/Manager", "");
@@ -513,7 +569,7 @@
        menuOptions.value = data;
        permissionInited.value = true;
        //开启消息推送(main.js中设置是否开启signalR)2022.05.05
        //寮€鍚秷鎭帹閫侊紙main.js涓缃槸鍚﹀紑鍚痵ignalR锛?022.05.05
        if (_config.$global.signalR) {
          MessageConfig(http, (result) => {
            messageList.unshift(result);
@@ -521,18 +577,18 @@
          });
        }
        //当前刷新是不是首页
        //褰撳墠鍒锋柊鏄笉鏄椤?
        if (router.currentRoute.value.path != navigation[0].path) {
          //查找系统菜单
          //鏌ユ壘绯荤粺鑿滃崟
          let item = menuOptions.value.find((x) => {
            return x.path == router.currentRoute.value.path; //this.$route.path;
          });
          if (item) return onSelect(item.id);
          //查找顶部快捷连接
          //鏌ユ壘椤堕儴蹇嵎杩炴帴
          item = links.value.find((x) => {
            return x.path == router.currentRoute.value.path; //this.$route.path;
          });
          //查找最后一次跳转的页面
          //鏌ユ壘鏈€鍚庝竴娆¤烦杞殑椤甸潰
          if (!item) {
            item = getItem();
          }
@@ -579,7 +635,7 @@
    };
  },
  /**
   * æŒ‚载钩子函数
   * éŽ¸å‚æµ‡é–½â•ç“™é‘èŠ¥æšŸ
   */
  mounted() {
    let _date = showTime();
@@ -594,14 +650,14 @@
  methods: {
    /**
     * ç»‘定右键事件
     * @param {*} enable æ˜¯å¦å¯ç”¨å³é”®äº‹ä»¶[true:启用;false:禁用;]
     * @param {*} $event äº‹ä»¶
     * ç¼æˆç•¾é™æŠ½æ•­æµœå¬©æ¬¢
     * @param {*} enable é„惁鍚敤鍙抽敭浜嬩欢[true:鍚敤;false:绂佺敤;]
     * @param {*} $event æµœå¬©æ¬¢
     */
    bindRightClickMenu(enable) {
      if (!enable) return;
      let that = this;
      // ä½¿ç”¨åŽŸç”Ÿjs ä¸ºå•个dom绑定鼠标右击事件
      // æµ£è·¨æ•¤é˜ç†ºæ•“js æ¶“哄崟涓猟om缁戝畾榧犳爣鍙冲嚮浜嬩欢
      that.$nextTick(() => {
        let tab_top_dom = Object.assign(
          [],
@@ -615,7 +671,7 @@
  },
  /**
   * é”€æ¯é’©å­å‡½æ•°
   * é–¿â‚¬å§£ä¾€æŒ¬ç€›æ„¬åš±é?
   */
  destroyed() {
    $this = null;
@@ -623,13 +679,13 @@
  },
});
const week = new Array(
  "星期一",
  "星期二",
  "星期三",
  "星期四",
  "星期五",
  "星期六",
  "星期日"
  "鏄熸湡涓€",
  "鏄熸湡浜?,
  "鏄熸湡涓?,
  "鏄熸湡鍥?,
  "鏄熸湡浜?,
  "鏄熸湡鍏?,
  "鏄熸湡鏃?
);
function showTime() {
  let date = new Date();
@@ -645,7 +701,7 @@
    "." +
    (month < 10 ? "0" + month : month) +
    "." +
    (day < 10 ? "0" + day : day) + //202.08.08修复日期天数小于10时添加0
    (day < 10 ? "0" + day : day) + //202.08.08淇鏃ユ湡澶╂暟灏忎簬10鏃舵坊鍔?
    "" +
    " " +
    (hour < 10 ? "0" + hour : hour) +
@@ -653,7 +709,7 @@
    (minutes < 10 ? "0" + minutes : minutes) +
    ":" +
    (second < 10 ? "0" + second : second) +
    " " + //2020.08.30修复首页日期星期天不显示的问题
    " " + //2020.08.30淇棣栭〉鏃ユ湡鏄熸湡澶╀笉鏄剧ず鐨勯棶棰?
    (week[date.getDay() - 1] || week[6])
  );
}
Code/WMS/AGENTS.md
@@ -14,12 +14,10 @@
- `dotnet run --project WIDESEA_WMSServer/WIDESEA_WMSServer.csproj`:本地启动 API。
前端(在 `WIDESEA_WMSClient` ç›®å½•执行):
- `yarn install`:安装依赖。
- `yarn dev`:启动 Vite å¼€å‘服务。
- `yarn build`:构建生产包。
- `yarn preview`:预览生产构建结果。
- `yarn test:unit`:运行单元测试。
- `yarn lint`:执行代码检查。
- `npm install`:安装依赖。
- `npm run serve`:启动本地开发服务(Vite)。
- `npm run build`:构建生产资源。
- `npm run lint`:执行 ESLint æ£€æŸ¥ã€‚
## å¼€å‘流程强制规范
Code/WMS/WIDESEA_WMSClient/.yarn/install-state.gz
Binary files differ
Code/WMS/WIDESEA_WMSClient/src/extension/outbound/outStockLockInfo.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,41 @@
// é¡µé¢æ‰©å±•配置:预留给业务二次扩展逻辑。
let extension = {
  components: {
    gridHeader: "",
    gridBody: "",
    gridFooter: "",
    modelHeader: "",
    modelBody: "",
    modelFooter: "",
  },
  tableAction: "",
  buttons: { view: [], box: [], detail: [] },
  methods: {
    onInit() {
      return true;
    },
    onInited() {
      return true;
    },
    searchBefore(param) {
      return true;
    },
    searchAfter(result) {
      return true;
    },
    addBefore(formData) {
      return true;
    },
    updateBefore(formData) {
      return true;
    },
    rowClick({ row, column, event }) {
      return true;
    },
    modelOpenAfter(row) {
      return true;
    },
  },
};
export default extension;
Code/WMS/WIDESEA_WMSClient/src/extension/stock/stock.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,41 @@
// é¡µé¢æ‰©å±•配置:预留给库存页面二次开发。
let extension = {
  components: {
    gridHeader: "",
    gridBody: "",
    gridFooter: "",
    modelHeader: "",
    modelBody: "",
    modelFooter: "",
  },
  tableAction: "",
  buttons: { view: [], box: [], detail: [] },
  methods: {
    onInit() {
      return true;
    },
    onInited() {
      return true;
    },
    searchBefore(param) {
      return true;
    },
    searchAfter(result) {
      return true;
    },
    addBefore(formData) {
      return true;
    },
    updateBefore(formData) {
      return true;
    },
    rowClick({ row, column, event }) {
      return true;
    },
    modelOpenAfter(row) {
      return true;
    },
  },
};
export default extension;
Code/WMS/WIDESEA_WMSClient/src/extension/system/Sys_Tenant.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,41 @@
// é¡µé¢æ‰©å±•配置:预留给租户业务逻辑扩展。
let extension = {
  components: {
    gridHeader: "",
    gridBody: "",
    gridFooter: "",
    modelHeader: "",
    modelBody: "",
    modelFooter: "",
  },
  tableAction: "",
  buttons: { view: [], box: [], detail: [] },
  methods: {
    onInit() {
      return true;
    },
    onInited() {
      return true;
    },
    searchBefore(param) {
      return true;
    },
    searchAfter(result) {
      return true;
    },
    addBefore(formData) {
      return true;
    },
    updateBefore(formData) {
      return true;
    },
    rowClick({ row, column, event }) {
      return true;
    },
    modelOpenAfter(row) {
      return true;
    },
  },
};
export default extension;
Code/WMS/WIDESEA_WMSClient/src/router/viewGird.js
@@ -1,4 +1,4 @@

let viewgird = [
  {
    path: '/Sys_Log',
@@ -181,6 +181,26 @@
    name: 'mesOutboundOrder',
    component: () => import('@/views/outbound/mesOutboundOrder.vue')
  }
  , {
    path: '/OutStockLockInfo',
    name: 'OutStockLockInfo',
    component: () => import('@/views/outbound/outStockLockInfo.vue')
  }
  , {
    path: '/Sys_Tenant',
    name: 'Sys_Tenant',
    component: () => import('@/views/system/Sys_Tenant.vue')
  }
  , {
    path: '/Stock',
    name: 'Stock',
    component: () => import('@/views/stock/stock.vue')
  }
  , {
    path: '/PDA',
    name: 'PDA',
    component: () => import('@/views/system/PDA.vue')
  }
]
export default viewgird
Code/WMS/WIDESEA_WMSClient/src/views/outbound/outStockLockInfo.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,134 @@
<template>
  <view-grid
    ref="grid"
    :columns="columns"
    :detail="detail"
    :editFormFields="editFormFields"
    :editFormOptions="editFormOptions"
    :searchFormFields="searchFormFields"
    :searchFormOptions="searchFormOptions"
    :table="table"
    :extend="extend"
  >
  </view-grid>
</template>
<script>
import extend from "@/extension/outbound/outStockLockInfo.js";
import { ref, defineComponent } from "vue";
export default defineComponent({
  setup() {
    // é¡µé¢æ ¸å¿ƒé…ç½®ï¼šç»‘定后端 OutStockLockInfo æŽ§åˆ¶å™¨ã€‚
    const table = ref({
      key: "id",
      footer: "Foots",
      cnName: "出库锁定明细",
      name: "outStockLockInfo",
      url: "/OutStockLockInfo/",
      sortName: "id",
    });
    // æ–°å¢ž/编辑表单字段:与后端实体字段保持一致,避免字段丢失。
    const editFormFields = ref({
      orderNo: "",
      orderDetailId: "",
      orderType: "",
      batchNo: "",
      materielCode: "",
      materielName: "",
      stockId: "",
      orderQuantity: "",
      originalQuantity: "",
      assignQuantity: "",
      locationCode: "",
      palletCode: "",
      unit: "",
      taskNum: "",
      status: "",
      remark: "",
    });
    const editFormOptions = ref([
      [
        { field: "orderNo", title: "单据编号", type: "string", required: true },
        { field: "orderType", title: "单据类型", type: "select", dataKey: "outOrderType", data: [] },
        { field: "batchNo", title: "批次号", type: "string" },
        { field: "materielCode", title: "物料编号", type: "string" },
        { field: "materielName", title: "物料名称", type: "string" },
      ],
      [
        { field: "palletCode", title: "托盘编号", type: "string" },
        { field: "locationCode", title: "货位编号", type: "string" },
        { field: "assignQuantity", title: "分配出库量", type: "decimal" },
        { field: "status", title: "状态", type: "select", dataKey: "outStockStatus", data: [] },
        { field: "remark", title: "备注", type: "textarea" },
      ],
    ]);
    // æŸ¥è¯¢å­—段:提供业务定位常用条件。
    const searchFormFields = ref({
      orderNo: "",
      batchNo: "",
      materielCode: "",
      palletCode: "",
      locationCode: "",
      status: "",
    });
    const searchFormOptions = ref([
      [
        { title: "单据编号", field: "orderNo", type: "like" },
        { title: "批次号", field: "batchNo", type: "like" },
        { title: "物料编号", field: "materielCode", type: "like" },
      ],
      [
        { title: "托盘编号", field: "palletCode", type: "like" },
        { title: "货位编号", field: "locationCode", type: "like" },
        { title: "状态", field: "status", type: "select", dataKey: "outStockStatus", data: [] },
      ],
    ]);
    const columns = ref([
      { field: "id", title: "Id", type: "int", width: 90, hidden: true, readonly: true, require: true, align: "left" },
      { field: "orderNo", title: "单据编号", type: "string", width: 160, align: "left" },
      { field: "orderType", title: "单据类型", type: "int", width: 110, align: "left", bind: { key: "outOrderType", data: [] } },
      { field: "orderDetailId", title: "单据明细主键", type: "int", width: 120, align: "left", hidden: true },
      { field: "batchNo", title: "批次号", type: "string", width: 120, align: "left" },
      { field: "materielCode", title: "物料编号", type: "string", width: 130, align: "left" },
      { field: "materielName", title: "物料名称", type: "string", width: 180, align: "left" },
      { field: "stockId", title: "库存主键", type: "int", width: 110, align: "left", hidden: true },
      { field: "orderQuantity", title: "单据数量", type: "decimal", width: 110, align: "left" },
      { field: "originalQuantity", title: "原始库存量", type: "decimal", width: 110, align: "left" },
      { field: "assignQuantity", title: "分配出库量", type: "decimal", width: 120, align: "left" },
      { field: "locationCode", title: "货位编号", type: "string", width: 120, align: "left" },
      { field: "palletCode", title: "托盘编号", type: "string", width: 120, align: "left" },
      { field: "unit", title: "单位", type: "string", width: 90, align: "left" },
      { field: "taskNum", title: "任务号", type: "int", width: 100, align: "left" },
      { field: "status", title: "状态", type: "int", width: 100, align: "left", bind: { key: "outStockStatus", data: [] } },
      { field: "creater", title: "创建人", type: "string", width: 100, align: "left" },
      { field: "createDate", title: "创建时间", type: "datetime", width: 160, align: "left" },
      { field: "modifier", title: "修改人", type: "string", width: 100, align: "left", hidden: true },
      { field: "modifyDate", title: "修改时间", type: "datetime", width: 160, align: "left", hidden: true },
      { field: "remark", title: "备注", type: "string", width: 120, align: "left", hidden: true },
    ]);
    const detail = ref({
      cnName: "#detailCnName",
      table: "",
      columns: [],
      sortName: "",
    });
    return {
      table,
      extend,
      editFormFields,
      editFormOptions,
      searchFormFields,
      searchFormOptions,
      columns,
      detail,
    };
  },
});
</script>
Code/WMS/WIDESEA_WMSClient/src/views/stock/stock.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,111 @@
<template>
  <view-grid
    ref="grid"
    :columns="columns"
    :detail="detail"
    :editFormFields="editFormFields"
    :editFormOptions="editFormOptions"
    :searchFormFields="searchFormFields"
    :searchFormOptions="searchFormOptions"
    :table="table"
    :extend="extend"
  >
  </view-grid>
</template>
<script>
import extend from "@/extension/stock/stock.js";
import { ref, defineComponent } from "vue";
export default defineComponent({
  setup() {
    // åº“存基础页:对接 Stock æŽ§åˆ¶å™¨ï¼Œæ”¯æŒåº“存主记录查询维护。
    const table = ref({
      key: "id",
      footer: "Foots",
      cnName: "库存",
      name: "stock",
      url: "/Stock/",
      sortName: "id",
    });
    const editFormFields = ref({
      palletCode: "",
      palletType: "",
      locationId: "",
      locationCode: "",
      warehouseId: "",
      stockStatus: "",
      outboundDate: "",
      remark: "",
    });
    const editFormOptions = ref([
      [
        { field: "palletCode", title: "托盘编号", type: "string", required: true },
        { field: "palletType", title: "托盘类型", type: "number" },
        { field: "locationCode", title: "货位编号", type: "string" },
      ],
      [
        { field: "warehouseId", title: "仓库", type: "select", dataKey: "warehouses", data: [] },
        { field: "stockStatus", title: "库存状态", type: "select", dataKey: "stockStatusEmun", data: [] },
        { field: "outboundDate", title: "出库日期", type: "datetime" },
      ],
      [{ field: "remark", title: "备注", type: "textarea" }],
    ]);
    const searchFormFields = ref({
      palletCode: "",
      locationCode: "",
      warehouseId: "",
      stockStatus: "",
      outboundDate: "",
    });
    const searchFormOptions = ref([
      [
        { title: "托盘编号", field: "palletCode", type: "like" },
        { title: "货位编号", field: "locationCode", type: "like" },
        { title: "仓库", field: "warehouseId", type: "select", dataKey: "warehouses", data: [] },
      ],
      [
        { title: "库存状态", field: "stockStatus", type: "select", dataKey: "stockStatusEmun", data: [] },
        { title: "出库日期", field: "outboundDate", type: "datetime" },
      ],
    ]);
    const columns = ref([
      { field: "id", title: "Id", type: "int", width: 90, hidden: true, readonly: true, require: true, align: "left" },
      { field: "palletCode", title: "托盘编号", type: "string", width: 130, align: "left" },
      { field: "palletType", title: "托盘类型", type: "int", width: 110, align: "left" },
      { field: "locationId", title: "货位ID", type: "int", width: 110, align: "left", hidden: true },
      { field: "locationCode", title: "货位编号", type: "string", width: 130, align: "left" },
      { field: "warehouseId", title: "仓库", type: "select", width: 110, align: "left", bind: { key: "warehouses", data: [] } },
      { field: "stockStatus", title: "库存状态", type: "int", width: 120, align: "left", bind: { key: "stockStatusEmun", data: [] } },
      { field: "outboundDate", title: "出库日期", type: "datetime", width: 160, align: "left" },
      { field: "creater", title: "创建人", type: "string", width: 100, align: "left" },
      { field: "createDate", title: "创建时间", type: "datetime", width: 160, align: "left" },
      { field: "modifier", title: "修改人", type: "string", width: 100, align: "left", hidden: true },
      { field: "modifyDate", title: "修改时间", type: "datetime", width: 160, align: "left", hidden: true },
      { field: "remark", title: "备注", type: "string", width: 140, align: "left" },
    ]);
    const detail = ref({
      cnName: "#detailCnName",
      table: "",
      columns: [],
      sortName: "",
    });
    return {
      table,
      extend,
      editFormFields,
      editFormOptions,
      searchFormFields,
      searchFormOptions,
      columns,
      detail,
    };
  },
});
</script>
Code/WMS/WIDESEA_WMSClient/src/views/system/PDA.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,128 @@
<template>
  <div class="pda-container">
    <el-card class="pda-card" shadow="hover">
      <template #header>
        <div class="card-header">PDA åº”用管理</div>
      </template>
      <el-form label-width="120px">
        <el-form-item label="当前版本号">
          <el-input v-model="clientVersion" placeholder="请输入当前PDA版本号" style="max-width: 280px" />
          <el-button type="primary" style="margin-left: 10px" @click="checkVersion">检查更新</el-button>
        </el-form-item>
        <el-form-item label="服务端版本结果">
          <span>{{ checkResult }}</span>
        </el-form-item>
        <el-form-item label="下载安装包">
          <el-button type="success" @click="downloadApp">下载最新 APK</el-button>
        </el-form-item>
        <el-form-item label="上传安装包">
          <el-upload
            :action="uploadUrl"
            :headers="uploadHeaders"
            name="fileInput"
            :show-file-list="true"
            :before-upload="beforeUpload"
            :on-success="onUploadSuccess"
            :on-error="onUploadError"
          >
            <el-button type="warning">上传新 APK</el-button>
          </el-upload>
        </el-form-item>
      </el-form>
    </el-card>
  </div>
</template>
<script>
import { defineComponent, ref, computed, getCurrentInstance } from "vue";
import store from "@/store/index";
import http from "@/api/http";
export default defineComponent({
  setup() {
    const clientVersion = ref("");
    const checkResult = ref("未检查");
    const { proxy } = getCurrentInstance();
    // ä¸Šä¼ åœ°å€ï¼šå¤ç”¨å…¨å±€ http åŸºç¡€åœ°å€ï¼Œä¿è¯ä¸Žå½“前环境一致。
    const uploadUrl = computed(() => `${http.ipAddress}api/PDA/UploadApp`);
    // ä¸Šä¼ é‰´æƒï¼šæ²¿ç”¨çŽ°æœ‰ token æœºåˆ¶ï¼Œé¿å…æŽ¥å£ 401。
    const uploadHeaders = computed(() => ({
      Authorization: store.getters.getToken(),
    }));
    const checkVersion = () => {
      if (!clientVersion.value) {
        proxy.$message.warning("请输入版本号");
        return;
      }
      http
        .get(`api/PDA/GetPDAVersion?version=${encodeURIComponent(clientVersion.value)}`, {}, true)
        .then((res) => {
          if (!res.status) {
            checkResult.value = res.message || "检查失败";
            return;
          }
          checkResult.value = res.data ? "需要更新" : "已是最新版本";
        });
    };
    const downloadApp = () => {
      window.open(`${http.ipAddress}api/PDA/DownLoadApp`, "_blank");
    };
    // ä¸Šä¼ å‰æ ¡éªŒï¼šé™åˆ¶ä¸Šä¼  apk,减少无效请求。
    const beforeUpload = (file) => {
      if (!file || !file.name || !file.name.toLowerCase().endsWith(".apk")) {
        proxy.$message.error("只允许上传 .apk æ–‡ä»¶");
        return false;
      }
      return true;
    };
    const onUploadSuccess = (response) => {
      proxy.$message[response && response.status ? "success" : "error"](
        (response && response.message) || "上传完成"
      );
    };
    const onUploadError = () => {
      proxy.$message.error("上传失败");
    };
    return {
      clientVersion,
      checkResult,
      uploadUrl,
      uploadHeaders,
      checkVersion,
      downloadApp,
      beforeUpload,
      onUploadSuccess,
      onUploadError,
    };
  },
});
</script>
<style lang="less" scoped>
.pda-container {
  height: 100%;
  padding: 12px;
}
.pda-card {
  max-width: 920px;
}
.card-header {
  font-size: 16px;
  font-weight: 600;
}
</style>
Code/WMS/WIDESEA_WMSClient/src/views/system/Sys_Tenant.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,102 @@
<template>
  <view-grid
    ref="grid"
    :columns="columns"
    :detail="detail"
    :editFormFields="editFormFields"
    :editFormOptions="editFormOptions"
    :searchFormFields="searchFormFields"
    :searchFormOptions="searchFormOptions"
    :table="table"
    :extend="extend"
  >
  </view-grid>
</template>
<script>
import extend from "@/extension/system/Sys_Tenant.js";
import { ref, defineComponent } from "vue";
export default defineComponent({
  setup() {
    // ç§Ÿæˆ·ç®¡ç†ä¸»é…ç½®ï¼šå¯¹æŽ¥ api/tenant。
    const table = ref({
      key: "tenantId",
      footer: "Foots",
      cnName: "租户管理",
      name: "sys_Tenant",
      url: "/tenant/",
      sortName: "tenantId",
    });
    const editFormFields = ref({
      tenantName: "",
      tenantType: "",
      dbType: "",
      connectionString: "",
      status: "",
      remark: "",
    });
    const editFormOptions = ref([
      [
        { field: "tenantName", title: "租户名称", type: "string", required: true },
        { field: "tenantType", title: "租户类型", type: "number", required: true },
        { field: "dbType", title: "数据库类型", type: "number", required: true },
      ],
      [
        { field: "status", title: "状态", type: "select", dataKey: "enableStatusEnum", data: [] },
        { field: "connectionString", title: "连接字符串", type: "textarea" },
        { field: "remark", title: "备注", type: "textarea" },
      ],
    ]);
    const searchFormFields = ref({
      tenantName: "",
      tenantType: "",
      dbType: "",
      status: "",
    });
    const searchFormOptions = ref([
      [
        { title: "租户名称", field: "tenantName", type: "like" },
        { title: "租户类型", field: "tenantType", type: "number" },
        { title: "数据库类型", field: "dbType", type: "number" },
        { title: "状态", field: "status", type: "select", dataKey: "enableStatusEnum", data: [] },
      ],
    ]);
    const columns = ref([
      { field: "tenantId", title: "租户ID", type: "int", width: 90, align: "left" },
      { field: "tenantName", title: "租户名称", type: "string", width: 180, align: "left" },
      { field: "tenantType", title: "租户类型", type: "int", width: 110, align: "left" },
      { field: "dbType", title: "数据库类型", type: "int", width: 110, align: "left" },
      { field: "status", title: "状态", type: "int", width: 100, align: "left", bind: { key: "enableStatusEnum", data: [] } },
      { field: "connectionString", title: "连接字符串", type: "string", width: 280, align: "left" },
      { field: "creater", title: "创建人", type: "string", width: 100, align: "left" },
      { field: "createDate", title: "创建时间", type: "datetime", width: 160, align: "left" },
      { field: "modifier", title: "修改人", type: "string", width: 100, align: "left", hidden: true },
      { field: "modifyDate", title: "修改时间", type: "datetime", width: 160, align: "left", hidden: true },
      { field: "remark", title: "备注", type: "string", width: 180, align: "left" },
    ]);
    const detail = ref({
      cnName: "#detailCnName",
      table: "",
      columns: [],
      sortName: "",
    });
    return {
      table,
      extend,
      editFormFields,
      editFormOptions,
      searchFormFields,
      searchFormOptions,
      columns,
      detail,
    };
  },
});
</script>