-
-
-
-
-
-
-
+
+
+
+
暂无权限
如需查看,请联络管理员为您分配权限
+
-
-
-
diff --git a/src/api/index.js b/src/api/index.js
index f3d1b83..d72243a 100644
--- a/src/api/index.js
+++ b/src/api/index.js
@@ -1,13 +1,14 @@
// 配置API接口地址
// var root = '/api/v1'
// var root = '/api/debugapi'
-var root = "/api";
+// 置空:APIConfig 已带 /api 前缀(生产为绝对地址,dev 为同源相对),避免 baseURL 二次拼接
+var root = "";
// var root = ''
// 引用axios
-var axios = require("axios");
+import axios from "axios";
// import Notice from 'iview/src/components/notice';
-import { Message } from "view-design";
+import { Message } from "view-ui-plus";
// 自定义判断元素类型JS
function toType(obj) {
diff --git a/src/api/index.net.js b/src/api/index.net.js
deleted file mode 100644
index 2e22c1a..0000000
--- a/src/api/index.net.js
+++ /dev/null
@@ -1,180 +0,0 @@
-// 配置API接口地址
-// var root = '/api/v1'
-// var root = '/api/debugapi'
-var root = "/api";
-// var root = ''
-// 引用axios
-var axios = require("axios");
-
-// import Notice from 'iview/src/components/notice';
-import { Message } from "view-design";
-
-// 自定义判断元素类型JS
-function toType(obj) {
- return {}.toString
- .call(obj)
- .match(/\s([a-zA-Z]+)/)[1]
- .toLowerCase();
-}
-// 参数过滤函数
-function filterNull(o) {
- for (var key in o) {
- if (o[key] === null) {
- delete o[key];
- }
- if (toType(o[key]) === "string") {
- o[key] = o[key].trim();
- } else if (toType(o[key]) === "object") {
- o[key] = filterNull(o[key]);
- } else if (toType(o[key]) === "array") {
- o[key] = filterNull(o[key]);
- }
- }
- return o;
-}
-/*
- 接口处理函数
- 这个函数每个项目都是不一样的,我现在调整的是适用于
- https://cnodejs.org/api/v1 的接口,如果是其他接口
- 需要根据接口的参数进行调整。参考说明文档地址:
- https://cnodejs.org/topic/5378720ed6e2d16149fa16bd
- 主要是,不同的接口的成功标识和失败提示是不一致的。
- 另外,不同的项目的处理方法也是不一致的,这里出错就是简单的alert
-*/
-
-function apiAxios(method, url, params, success, failure) {
- let conentTypeIsJosn = false;
- if (params && typeof params != "string") {
- params = filterNull(params);
- } else conentTypeIsJosn = true;
-
- // if (!window.location.origin) {
- // window.location.origin = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '');
- // }
- // let redirectUrl=window.location.origin + window.location.hash.replace('#','/xiaoxi/#');
-
- // console.log(window.location);
-
- axios({
- method: method,
- url: url,
- data: method === "POST" || method === "PUT" ? params : null,
- params: method === "GET" || method === "DELETE" ? params : null,
- baseURL: root,
- // withCredentials: true,
- crossDomain: true,
- transformRequest: [
- function(data) {
- // Do whatever you want to transform the data
- if (conentTypeIsJosn) return data;
- let ret = "";
- for (let it in data) {
- ret +=
- encodeURIComponent(it) + "=" + encodeURIComponent(data[it]) + "&";
- }
- return ret;
- },
- ],
- headers: {
- // 'Content-Type': 'application/x-www-form-urlencoded',
- "Content-Type": conentTypeIsJosn
- ? "application/json"
- : "application/x-www-form-urlencoded",
- },
- })
- .then(function(res) {
- let response = res.data;
- if (response.State) {
- if (success) {
- success(response);
- }
- } else {
- if (failure) {
- failure(response.Data);
- } else {
- if (response.Data == 2) {
- Message.error(response.Message); //错误处理
- setTimeout(() => {
- location.reload();
- }, 1000);
- } else {
- Message.info(response.Message); //错误处理
- }
- }
- }
- })
- .catch(function(err) {
- let res = err.response;
- console.error(res || err);
- if (res) {
- Message.destroy();
- clearTimeout(tiemObj);
- // if(res.status===401&&res.data.OtherData.ErrorCode==2){
- if (res.status === 401) {
- window.location.reload();
- // if(process.env.NODE_ENV === 'production')
- // Message.error(res.data.Message);//错误处理
- // setTimeout(() => {
- // location.reload();
- // }, 0);
- } else if (res.data.Message) {
- Message.error(res.data.Message); //错误处理
- } else {
- Message.error("网络请求出错"); //错误处理
- }
- return;
- }
- });
-}
-
-let requestCount = 0,
- tiemObj;
-// http request 拦截器
-axios.interceptors.request.use((config) => {
- requestCount++;
- if (requestCount == 1) {
- tiemObj = setTimeout(() => {
- Message.loading({ content: "加载中...", duration: 0 });
- }, 800);
- }
- if (localStorage.getItem("currentRole"))
- config.headers["currentRole"] = localStorage.getItem("currentRole");
-
- if (process.env.NODE_ENV !== "production") {
- //如果是开发环境
- config.headers["DebugUser"] = "zhd";
- config.headers["DebugAppType"] = true;
- }
- return config;
-});
-
-// http response 拦截器
-axios.interceptors.response.use((response) => {
- requestCount--;
- if (requestCount === 0) {
- setTimeout(() => {
- Message.destroy();
- }, 1500);
- clearTimeout(tiemObj);
- }
- return response;
-});
-// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
-// axios.defaults.headers.post['Content-Type'] = 'application/json; charset=utf-8';
-// axios.defaults.withCredentials = true
-
-// 返回在vue模板中的调用接口
-export default {
- get: function(url, params, success, failure) {
- return apiAxios("GET", url, params, success, failure);
- },
- post: function(url, params, success, failure) {
- return apiAxios("POST", url, params, success, failure);
- },
- put: function(url, params, success, failure) {
- return apiAxios("PUT", url, params, success, failure);
- },
- delete: function(url, params, success, failure) {
- return apiAxios("DELETE", url, params, success, failure);
- },
-};
diff --git a/src/assets/config/host.config.ts b/src/assets/config/host.config.ts
new file mode 100644
index 0000000..7d0afd3
--- /dev/null
+++ b/src/assets/config/host.config.ts
@@ -0,0 +1,72 @@
+/**
+ * 宿主配置(对齐 NoticeFront @/assets/config/host.config)。
+ * 优先级:__APP_CONFIG__(线上运行时下发)> VITE_*(仅本地 dev)> 同域推导兜底。
+ */
+const env = import.meta.env;
+
+const seg = window.location.pathname.split("/").filter(Boolean);
+const origin = window.location.origin;
+// 部署在 /{contextPath}/front/ → 上下文段即首段;本地 dev 根路径段数不足 → 留空走同源相对
+const ctx = seg.length >= 2 ? `/${seg[0]}` : "";
+
+export interface BaseConf {
+ baseHost: string;
+ ssoHost: string;
+ serviceHost: string;
+ serviceUrl: string;
+ fileHost: string;
+ flowHost: string;
+ isLayoutOld: boolean;
+ isMock: boolean;
+ isDebug: boolean;
+}
+
+const conf: BaseConf = {
+ baseHost: origin,
+ ssoHost: "",
+ serviceHost: ctx ? origin + ctx : "",
+ serviceUrl: ctx ? origin + ctx : "",
+ fileHost: ctx ? origin + ctx : "",
+ flowHost: "",
+ isLayoutOld: false,
+ isMock: false,
+ isDebug: env.DEV,
+};
+
+const applyConf = (target: any, source: any) => {
+ if (!source || typeof source !== "object") return;
+ Object.keys(source).forEach(key => {
+ if (source[key] !== undefined && source[key] !== null && source[key] !== "") {
+ target[key] = source[key];
+ }
+ });
+};
+
+// 本地开发/演示(build 产物中 VITE_* 恒 undefined → 自动跳过)
+applyConf(conf, {
+ baseHost: env.VITE_BASE_HOST,
+ ssoHost: env.VITE_SSO_HOST,
+ serviceHost: env.VITE_IS_MOCK === "true" ? "" : env.VITE_SERVICE_HOST,
+ serviceUrl: env.VITE_IS_MOCK === "true" ? "" : env.VITE_SERVICE_HOST,
+ fileHost: env.VITE_IS_MOCK === "true" ? "" : env.VITE_SERVICE_HOST,
+ isMock: env.VITE_IS_MOCK === "true",
+});
+
+// 线上运行时配置(最高优先)
+try {
+ const runtime: any = (window as any).__APP_CONFIG__;
+ if (runtime && typeof runtime === "object") {
+ applyConf(conf, {
+ baseHost: runtime.baseHost,
+ ssoHost: runtime.ssoHost,
+ serviceHost: runtime.serviceHost,
+ serviceUrl: runtime.serviceHost,
+ fileHost: runtime.serviceHost,
+ flowHost: runtime.flowHost,
+ });
+ }
+} catch {
+ /* 无运行时配置时沿用兜底 */
+}
+
+export default conf;
diff --git a/src/assets/image/yunhai-logo.svg b/src/assets/image/yunhai-logo.svg
new file mode 100644
index 0000000..7d1d358
--- /dev/null
+++ b/src/assets/image/yunhai-logo.svg
@@ -0,0 +1,7 @@
+
diff --git a/src/components/UserCheck/index.scss b/src/components/UserCheck/index.scss
deleted file mode 100644
index ade376f..0000000
--- a/src/components/UserCheck/index.scss
+++ /dev/null
@@ -1,473 +0,0 @@
-$tabBtnColor: #577ae9;//tab主题色
-$treeCheckColor: #577ae9;//树主题色
-$treeCheckBorderColor: #dddee1;//边框色
-$treeCheckGroupColor: #f7f7f7;
-
-.fix {
- *zoom: 1;
- &::before,
- &::after {
- display: table;
- content: "";
- line-height: 0;
- }
- &::after {
- clear: both;
- }
-}
-.fl {
- float: left;
-}
-.fr {
- float: right;
-}
-.align-middle {
- position: relative;
- top: 50%;
- transform: translateY(-50%);
-}
-
-.my-tab_btn {
- margin: 10px auto;
- position: relative;
- .item-tab_btn {
- font-size: 16px;
- font-weight: 550;
- color: #656667;
- float: left;
- text-align: center;
- position: relative;
- box-sizing: border-box;
- height: 32px;
- line-height: 32px;
- margin-left: 15px;
- }
-
- .item-tab_btn.active {
- color: #272829;
- }
-
- .my-tab_slider {
- width: 42px;
- position: absolute;
- left: 0px;
- bottom: -1px;
- z-index: 1;
- transition: transform 0.3s ease-in-out;
- transform-origin: 0 0;
- & > .indicator {
- height: 2px;
- width: 17px;
- background: $tabBtnColor;
- margin: 0 auto;
- }
- }
-}
-
-.my-tab_card {
- margin: 15px 0 15px 10px;
- padding-right: 30px;
- position: relative;
- .item-wrap{
- white-space: nowrap;
- display: flex;
- align-items: center;
- overflow: hidden;
- overflow-x: scroll;
- }
- .item-tab_card {
- float: left;
- font-size: 13px;
- padding: 0px 15px;
- color: #808080;
- height: 27px;
- line-height: 27px;
- transition: all 200ms;
- }
- .item-tab_card.active {
- color: #272829;
- background: #f7f7f7;
- border-radius: 27px;
- }
-}
-
-.my-modal {
- position: fixed;
- left: 0;
- top: 0;
- width: 100%;
- height: 100%;
- opacity: 0.5;
- background: #000;
- z-index: 100;
-}
-
-.tree-popup {
- position: fixed;
- background: #fff;
- top: 100%;
- left: 0;
- transform: translateY(0);
- backface-visibility: hidden;
- transition: 0.2s ease-in;
- width: 100%;
- height: 85%;
- z-index: 101;
- border-radius: 8px 8px 0 0;
- &_show {
- transform: translateY(-100%);
- }
- &_hide {
- transform: translateY(0%);
- }
-
- &_header {
- position: relative;
- overflow: hidden;
- @extend .my-border_bottom;
-
- & .close-btn {
- position: absolute;
- padding: 5px;
- right: 3%;
- top: 10px;
- }
- }
- &_body {
- overflow-y: auto;
- min-height: 250px;
- }
-
- &_footer {
- height: 60px;
- width: 100%;
- box-sizing: border-box;
- background: #fff;
- position: relative;
- padding: 0 10px 0 20px;
- @extend .my-border_top;
- .check-box {
- float: left;
- &_text {
- margin-left: 3px;
- margin-right: 30px;
- vertical-align: middle;
- font-size: 16px;
- }
- }
-
- & p {
- font-size: 16px;
- color: #808080;
-
- span {
- font-size: 18px;
- color: $treeCheckColor;
- }
- }
- & button {
- width: 80px;
- height: 40px;
- color: #fff;
- background: $treeCheckColor;
- border-radius: 5px;
- outline: none;
- }
- }
-}
-
-.search-list {
- background: #f7f7f7;
- height: calc(100% - 46px);
- margin-top:46px;
- box-sizing: border-box;
- overflow-y: auto;
- .search-head {
- height: 46px;
- line-height: 46px;
- padding: 0 10px 0 15px;
- width: 100%;
- position: fixed;
- box-sizing: border-box;
- background: #f7f7f7;
- input {
- background: #efefef;
- -webkit-appearance: none;
- outline: none;
- width: calc(100% - 70px);
- height: 30px;
- line-height: 30px;
- padding: 0 15px;
- border-radius: 28px;
- font-size: 14px;
- &::-webkit-input-placeholder {
- font-size: 14px;
- }
- }
- span {
- margin-left: 5px;
- color: #272829;
- font-size: 14px;
- }
-
- .close-icon {
- width: 18px;
- line-height: 18px;
- height: 18px;
- position: absolute;
- right: 60px;
- top: 15px;
- }
- }
- .search-item {
- background: #fff;
- height: 46px;
- line-height: 46px;
- padding-left: 12px;
- a {
- position: relative;
- display: block;
- width: 100%;
- color: #333;
- outline: none;
- @extend .my-border_bottom;
- }
- &_text {
- margin-left: 2px;
- vertical-align: middle;
- }
- &_group {
- float: right;
- color: #808080;
- font-size: 12px;
- margin-right: 15px;
- }
- }
-}
-
-.user-popup {
- position: fixed;
- background: #fff;
- top: 100%;
- left: 0;
- transform: translateY(0);
- backface-visibility: hidden;
- transition: 0.2s ease-in;
- width: 100%;
- height: 75%;
- z-index: 105;
- border-radius: 8px 8px 0 0;
- &_show {
- transform: translateY(-100%);
- }
- &_hide {
- transform: translateY(0%);
- }
- &_header {
- position: relative;
- overflow: hidden;
- @extend .my-border_bottom;
- h4 {
- font-size: 18px;
- margin: 12px 0 5px;
- color: #272829;
- text-align: center;
- }
- h6 {
- color: #595959;
- font-size: 13px;
- margin: 5px 0 15px;
- text-align: center;
- }
- & .close-btn {
- position: absolute;
- padding: 5px;
- right: 3%;
- top: 10px;
- }
- }
- &_body {
- overflow-y: auto;
- height: calc(100% - 70px);
- padding: 12px 12px;
- box-sizing: border-box;
- }
- &_ul {
- @extend .fix;
- li {
- background: #f4f8ff;
- float: left;
- margin: 4px;
- width: calc(33.333% - 8px);
- border-radius: 4px;
- padding: 8px;
- box-sizing: border-box;
- h4,
- h6 {
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- h4 {
- font-size: 16px;
- margin: 6px 0;
- color: #272829;
- text-align: center;
- }
- h6 {
- color: #595959;
- font-size: 12px;
- height: 16px;
- margin: 6px 0;
- text-align: center;
- }
- }
- }
-}
-
-.search-box {
- position: absolute;
- right: 10px;
- width: 20px;
- height: 20px;
- box-sizing: border-box;
- padding: 2px;
- top: 2px;
- background: #fff;
-}
-
-.bg-arrow_grey {
- background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAABE0lEQVRYR+3VMQ6CMBQG4PdImPUIHsEjeBRZCJ30KDqVsNSjeASPwBF0Y6KmiSQM0NfXdiDmsZDQ0n79Wx4IG7twYx4QELUjkpAkRCVAtcsZ+p+EjDH7YRj2SqmeWhWnveu6Y1mWfVVV76X3Vs9Q27Y3RLyM41gppR6cSdf6aq3PRVEYa+29aZorC+RWYq19AsAuB2rCAMAHEU91Xb9YINc5FyoU4+YkP/tUFAcTBEpJiosJBsWgYjAsEAcVi2GDQlApmCiQD5WKiQYtodwzV/SoOkMVWPKz9w0wLwm/ft6iR2GSEpoGn6HAV4FDMFlAbhCt9cHdc/yIk7YsdNWcfgKi0pKEJCEqAapdzpAkRCVAtX8BqXjGJWAVZBoAAAAASUVORK5CYII=");
- background-repeat: no-repeat;
- display: inline-block;
- width: 64px;
- height: 64px;
- zoom: 0.3;
- background-size: contain;
-}
-
-.conta-wrap {
- position: relative;
- .tree-item {
- padding: 12px;
- color: #333;
- position: relative;
- a {
- color: #333;
- display: inline-block;
- outline: none;
- text-decoration: none;
- }
- input {
- display: none;
- }
- label {
- position: relative;
- vertical-align: middle;
- margin-left: 2px;
- }
- &_group {
- background: $treeCheckGroupColor;
- @extend .my-border_bottom;
- }
-
- &_arrow {
- &::before {
- @extend .bg-arrow_grey;
- content: "";
- display: block;
- position: absolute;
- right: 2%;
- top: 0;
- bottom: 0;
- margin: auto 0;
- transition: 300ms cubic-bezier(0.47, 0, 0.745, 0.715);
- }
- }
- &_open,
- &_close {
- @extend .tree-item_arrow;
- }
- &_close::before {
- transform: rotate(180deg);
- }
- }
-}
-
-.my-checkbox-core {
- border-radius: 3px;
- width: 20px;
- height: 20px;
- display: inline-block;
- background-color: #fff;
- border: 1px solid $treeCheckBorderColor;
- position: relative;
- vertical-align: middle;
-}
-.my-checkbox-core.active {
- background-color: $treeCheckColor;
- border-color: $treeCheckColor;
- &::after {
- border: 2px solid transparent;
- border-left: 0;
- border-top: 0;
- content: " ";
- top: 3px;
- left: 7px;
- position: absolute;
- width: 4px;
- height: 8px;
- -webkit-transform: rotate(45deg) scale(0);
- transform: rotate(45deg) scale(0);
- transition: -webkit-transform 0.2s;
- -webkit-transition: -webkit-transform 0.2s;
- transition: transform 0.2s;
- transition: transform 0.2s, -webkit-transform 0.2s;
- border-color: #fff;
- -webkit-transform: rotate(45deg) scale(1);
- transform: rotate(45deg) scale(1);
- }
-}
-
-
-.my-border_bottom::after {
- content: " ";
- position: absolute;
- color: #d9d9d9;
- -webkit-transform-origin: 0 0;
- transform-origin: 0 0;
- border-bottom: 1px solid #d9d9d9;
- height: 1px;
- left: 0;
- bottom: 0;
- right: 0;
- -webkit-transform: scaleY(0.5);
- transform: scaleY(0.5);
- transition: 0;
-}
-
-.my-border_top::after {
- content: " ";
- position: absolute;
- color: #d9d9d9;
- -webkit-transform-origin: 0 0;
- transform-origin: 0 0;
- border-top: 1px solid #d9d9d9;
- width: 100%;
- height: 1px;
- left: 0;
- top: 0;
- right: 0;
- -webkit-transform: scaleY(0.5);
- transform: scaleY(0.5);
- transition: 0;
-}
-
-.fade-enter-active,
-.fade-leave-active {
- transition: opacity 300ms ease-in-out;
-}
-.fade-enter,
-.fade-leave-to {
- opacity: 0;
-}
\ No newline at end of file
diff --git a/src/components/UserCheck/index.vue b/src/components/UserCheck/index.vue
deleted file mode 100644
index a593dfa..0000000
--- a/src/components/UserCheck/index.vue
+++ /dev/null
@@ -1,505 +0,0 @@
-
-
-
-
-
diff --git a/src/components/UserCheck/tree.vue b/src/components/UserCheck/tree.vue
deleted file mode 100644
index 279d33c..0000000
--- a/src/components/UserCheck/tree.vue
+++ /dev/null
@@ -1,80 +0,0 @@
-
-
-
-
-
diff --git a/src/components/codeModal/code_modal.vue b/src/components/codeModal/code_modal.vue
deleted file mode 100644
index 08692e2..0000000
--- a/src/components/codeModal/code_modal.vue
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/components/codeModal/index.js b/src/components/codeModal/index.js
deleted file mode 100644
index 8b005ad..0000000
--- a/src/components/codeModal/index.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import Vue from "vue";
-import codemodal from "./code_modal.vue";
-import { Message } from "view-design";
-export default props => {
- // 创建实例
- const vm = new Vue({
- render(h) {
- // h为createElement,返回VNode虚拟Node
- return h(codemodal, { props });
- }
- }).$mount();
-
- // 手动挂载实例到body
- document.body.appendChild(vm.$el);
-
- const comp = vm.$children[0];
- // 销毁方法
- // comp.remove = function() {
- // document.body.removeChild(vm.$el);
- // vm.$destroy();
- // };
- // 返回组件
- return comp;
-};
diff --git a/src/components/editor.vue b/src/components/editor.vue
deleted file mode 100644
index 96c629a..0000000
--- a/src/components/editor.vue
+++ /dev/null
@@ -1,240 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 提交
- 取消
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/components/layout.vue b/src/components/layout.vue
new file mode 100644
index 0000000..c857cf3
--- /dev/null
+++ b/src/components/layout.vue
@@ -0,0 +1,291 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 首页
+
+
+
+ {{ appName }}
+
+
+ {{ item.name }}
+
+ {{ item.name }}
+
+
+
+
+
+
+
diff --git a/src/components/myConfirm/confirm.vue b/src/components/myConfirm/confirm.vue
deleted file mode 100644
index ff2a1e2..0000000
--- a/src/components/myConfirm/confirm.vue
+++ /dev/null
@@ -1,64 +0,0 @@
-
-
-
-
- {{ msg }}
- {{ info }}
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/components/myConfirm/index.js b/src/components/myConfirm/index.js
deleted file mode 100644
index 118d57f..0000000
--- a/src/components/myConfirm/index.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import Vue from "vue";
-import confirm from "./confirm.vue";
-export default props => {
- // 创建实例
- const vm = new Vue({
- render(h) {
- // h为createElement,返回VNode虚拟Node
- return h(confirm, { props });
- }
- }).$mount();
-
- // 手动挂载实例到body
- document.body.appendChild(vm.$el);
-
- const comp = vm.$children[0];
- // 销毁方法
- // comp.remove = function() {
- // document.body.removeChild(vm.$el);
- // vm.$destroy();
- // };
- // 返回组件
- return comp;
-};
diff --git a/src/components/my_tree copy.vue b/src/components/my_tree copy.vue
deleted file mode 100644
index f839dfe..0000000
--- a/src/components/my_tree copy.vue
+++ /dev/null
@@ -1,95 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/components/my_tree.vue b/src/components/my_tree.vue
index 49e546a..d7cb1af 100644
--- a/src/components/my_tree.vue
+++ b/src/components/my_tree.vue
@@ -3,8 +3,7 @@
-
-
\ No newline at end of file
diff --git a/src/components/type_set_box.vue b/src/components/type_set_box.vue
deleted file mode 100644
index e958426..0000000
--- a/src/components/type_set_box.vue
+++ /dev/null
@@ -1,169 +0,0 @@
-
-
-
-
-
- {{ type.name }}
-
-
-
- 停用
- 启用
-
-
- 编辑
-
-
- 删除
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/components/upload_img.vue b/src/components/upload_img.vue
deleted file mode 100644
index ccd7614..0000000
--- a/src/components/upload_img.vue
+++ /dev/null
@@ -1,100 +0,0 @@
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/components/user_check.vue b/src/components/user_check.vue
index bf30c12..9c4e73c 100644
--- a/src/components/user_check.vue
+++ b/src/components/user_check.vue
@@ -48,16 +48,15 @@
-
diff --git a/src/frame/layout.child.vue b/src/frame/layout.child.vue
deleted file mode 100644
index a48c567..0000000
--- a/src/frame/layout.child.vue
+++ /dev/null
@@ -1,305 +0,0 @@
-
-
-
-
-
-
-
-
-
- {{ item.name }}
-
-
-
-
- {{ navPath }}
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/frame/layout_old.vue b/src/frame/layout_old.vue
deleted file mode 100644
index 64b49e9..0000000
--- a/src/frame/layout_old.vue
+++ /dev/null
@@ -1,306 +0,0 @@
-
-
-
-
-
-
-
{{ pathName }}
-
-
-
-
-
-
-
diff --git a/src/main.js b/src/main.js
deleted file mode 100644
index 074feac..0000000
--- a/src/main.js
+++ /dev/null
@@ -1,62 +0,0 @@
-import Vue from "vue";
-import App from "./App.vue";
-import router from "./router";
-
-import api from "./api/index.js";
-// 将API方法绑定到全局
-Vue.prototype.$api = api;
-
-import "@babel/polyfill";
-// import "babel-polyfill";
-
-// 引用工具文件
-import utils from "./utils/index.js";
-// 将工具方法绑定到全局
-Vue.prototype.$utils = utils;
-
-import APIConfig from "./config/apiConf.js";
-window.APIConfig = APIConfig;
-
-import "view-design/dist/styles/iview.css";
-import ViewUI from "view-design";
-Vue.use(ViewUI);
-
-import conf from "./config/hostConf.js";
-Vue.prototype.$conf = conf;
-window.conf = conf;
-
-import "./assets/styles/main.scss";
-
-// 是否是IE内核
-//代码高亮文件引入(IE暂不支持)
-import hljs from "highlight.js";
-//样式文件,这里我选的是sublime样式,文件里面还有其他样式可供选择
-// import "highlight.js/styles/monokai-sublime.css";
-// import "highlight.js/styles/vs2015.css";
-import "highlight.js/styles/atelier-dune-light.css";
-
-Vue.directive("highlight", function(el) {
- let blocks = el.querySelectorAll("pre code");
- blocks.forEach(block => {
- hljs.highlightBlock(block);
- });
-});
-
-
-import codeModal from "./mixins/code_modal";
-Vue.mixin(codeModal);
-
-var EventBus = new Vue(); //事件总线
-Object.defineProperties(Vue.prototype, {
- $bus: {
- get: function() {
- return EventBus;
- }
- }
-});
-
-Vue.config.productionTip = false;
-new Vue({
- router,
- render: h => h(App)
-}).$mount("#app");
diff --git a/src/main.ts b/src/main.ts
new file mode 100644
index 0000000..6bdfcab
--- /dev/null
+++ b/src/main.ts
@@ -0,0 +1,39 @@
+import { createApp } from "vue";
+import { createPinia } from "pinia";
+
+import App from "./App.vue";
+import router from "@/router";
+
+import ViewUIPlus from "view-ui-plus";
+import "view-ui-plus/dist/styles/viewuiplus.css";
+
+// 布局/主题/图标(base.layout.css + icons.css)由中央静态通道下发:
+// index.html 的 yh-theme-init.js 在 DOMContentLoaded 后按 manifest 版本追加
,
+// 天然排在本文件组件库样式之后。
+import "@/assets/styles/main.scss";
+
+import api from "@/api";
+import utils from "@/utils";
+import conf from "@/assets/config/host.config";
+import bus from "@/utils/bus";
+import registerDirectives from "@/utils/directive";
+import APIConfig from "@/config/apiConf";
+
+const app = createApp(App);
+
+app.use(createPinia());
+app.use(router);
+app.use(ViewUIPlus);
+
+// 兼容存量代码:全局 APIConfig / conf,以及 Vue2 时代的四个原型方法
+(window as any).APIConfig = APIConfig;
+(window as any).conf = conf;
+
+app.config.globalProperties.$api = api;
+app.config.globalProperties.$utils = utils;
+app.config.globalProperties.$conf = conf;
+app.config.globalProperties.$bus = bus;
+
+registerDirectives(app);
+
+app.mount("#app");
diff --git a/src/mixins/code_modal.js b/src/mixins/code_modal.js
deleted file mode 100644
index 2c14a47..0000000
--- a/src/mixins/code_modal.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import codeModal from "../components/codeModal/index.js";
-export default {
- methods: {
- showCode({ name, url, type = "vue" }) {
- codeModal({ name, url, type });
- }
- }
-};
diff --git a/src/router/index.js b/src/router/index.js
deleted file mode 100644
index 101f27a..0000000
--- a/src/router/index.js
+++ /dev/null
@@ -1,141 +0,0 @@
-import Vue from "vue";
-import VueRouter from "vue-router";
-
-const studySystemChoice = () => import("../views/studySystemChoice.vue");
-const itemSet = () => import("../views/itemSet.vue");
-const areaOperateDaily = () => import("../views/areaOperateDaily.vue");
-const schoolSetting = () => import("../views/schoolSetting.vue");
-const subjectManForZy = () => import("../views/subjectManForZy.vue");
-const classManage = () => import("../views/classManage.vue");
-const electiveClassManage = () => import("../views/electiveClassManage.vue");
-const electiveClassManageDetail = () => import("../views/electiveClassManageDetail.vue");
-const ChristianityDetail = () => import("../views/classManage/ChristianityDetail.vue");
-const subjectSetzhi = () => import("../views/subjectSetzhi.vue");
-const teacherManage = () => import("../views/teacherManage.vue");
-const studentManage = () => import("../views/studentManage.vue");
-const historySearch = () => import("../views/historySearch.vue");
-const historySearchDetail = () => import("../views/historySearchDetail.vue");
-const studentYDManage = () => import("../views/studentYDManage.vue");
-const zhuanruinfo = () => import("../views/zhuanruinfo.vue");
-const zhuanruinfostu = () => import("../views/zhuanruinfostu.vue");
-const dailySearch = () => import("../views/dailySearch.vue");
-
-Vue.use(VueRouter);
-
-const routes = [
- {
- path: "/studySystemChoice",
- name: "studySystemChoice",
- component: studySystemChoice,
- meta: { title: "学制选择", modId: 1, icon: "icon-shezhi" }
- },
- {
- path: '/itemSet',
- name: "itemSet",
- component: itemSet,
- meta:{title:"时段设置",modId:2,icon: "icon-shezhi"}
- },
- {
- path: '/areaOperateDaily',
- name: "areaOperateDaily",
- component: areaOperateDaily,
- meta:{title:"区域操作日志",modId:3,icon: "icon-chaxun"}
- },
- {
- path: '/schoolSetting',
- name: "schoolSetting",
- component: schoolSetting,
- meta:{title:"学校设置",modId:4,icon: "icon-cshxd"}
- },
- {
- path: '/subjectManForZy',
- name: "subjectManForZy",
- component: subjectManForZy,
- meta:{title:"课程设置",modId:5,icon: "icon-xuekeshezhi"}
- },
- {
- path: '/subjectSetzhi',
- name: "subjectSetzhi",
- component: subjectSetzhi,
- meta:{title:"学科管理",modId:6,icon: "icon-xuekeshezhi"}
- },
- {
- path: '/classManage',
- name: "classManage",
- component: classManage,
- meta:{title:"班级管理",modId:7,icon: "icon-banji"}
- },
- {
- path: "/ChristianityDetail",
- name: "ChristianityDetail",
- component: ChristianityDetail,
- meta: { title: "班级管理", modId: 7,parentPath:"/classManage" }
- },
- {
- path: '/electiveClassManage',
- name: "electiveClassManage",
- component: electiveClassManage,
- meta:{title:"选修班管理",modId:8,icon: "icon-banji"}
- },
- {
- path: "/electiveClassManageDetail",
- name: "electiveClassManageDetail",
- component: electiveClassManageDetail,
- meta: { title: "选修班管理", modId: 8,parentPath:"/electiveClassManage" }
- },
- {
- path: '/teacherManage',
- name: "teacherManage",
- component: teacherManage,
- meta:{title:"教师管理",modId:9,icon: "icon-jiaoshi"}
- },
- {
- path: '/studentManage',
- name: "studentManage",
- component: studentManage,
- meta:{title:"学生管理",modId:10,icon: "icon-xuesheng"}
- },
- {
- path: '/historySearch',
- name: "historySearch",
- component: historySearch,
- meta:{title:"历史查询",modId:11,icon: "icon-chaxun"}
- },
- {
- path: "/historySearchDetail",
- name: "historySearchDetail",
- component: historySearchDetail,
- meta: { title: "历史查询", modId: 11,parentPath:"/historySearch" }
- },
- {
- path: '/studentYDManage',
- name: "studentYDManage",
- component: studentYDManage,
- meta:{title:"学生异动管理",modId:12,icon: "icon-xuesheng"}
- },
- {
- path: '/zhuanruinfo',
- name: "zhuanruinfo",
- component: zhuanruinfo,
- meta:{title:"教师转入管理",modId:13,icon: "icon-jiaoshi"}
- },
- {
- path: '/zhuanruinfostu',
- name: "zhuanruinfostu",
- component: zhuanruinfostu,
- meta:{title:"学生转入管理",modId:14,icon: "icon-xuesheng"}
- },
- {
- path: '/dailySearch',
- name: "dailySearch",
- component: dailySearch,
- meta:{title:"日志管理",modId:15,icon: "icon-chaxun"}
- },
-];
-
-const router = new VueRouter({
- base: process.env.BASE_URL,
- routes
-});
-
-export default router;
diff --git a/src/router/index.ts b/src/router/index.ts
new file mode 100644
index 0000000..20217c3
--- /dev/null
+++ b/src/router/index.ts
@@ -0,0 +1,9 @@
+import { createRouter, createWebHashHistory } from "vue-router";
+import routes from "./routes";
+
+const router = createRouter({
+ history: createWebHashHistory(),
+ routes,
+});
+
+export default router;
diff --git a/src/router/routes.ts b/src/router/routes.ts
new file mode 100644
index 0000000..e8f92bf
--- /dev/null
+++ b/src/router/routes.ts
@@ -0,0 +1,138 @@
+import type { RouteRecordRaw } from "vue-router";
+
+const studySystemChoice = () => import("@/views/studySystemChoice.vue");
+const itemSet = () => import("@/views/itemSet.vue");
+const areaOperateDaily = () => import("@/views/areaOperateDaily.vue");
+const schoolSetting = () => import("@/views/schoolSetting.vue");
+const subjectManForZy = () => import("@/views/subjectManForZy.vue");
+const classManage = () => import("@/views/classManage.vue");
+const electiveClassManage = () => import("@/views/electiveClassManage.vue");
+const electiveClassManageDetail = () => import("@/views/electiveClassManageDetail.vue");
+const ChristianityDetail = () => import("@/views/classManage/ChristianityDetail.vue");
+const subjectSetzhi = () => import("@/views/subjectSetzhi.vue");
+const teacherManage = () => import("@/views/teacherManage.vue");
+const studentManage = () => import("@/views/studentManage.vue");
+const historySearch = () => import("@/views/historySearch.vue");
+const historySearchDetail = () => import("@/views/historySearchDetail.vue");
+const studentYDManage = () => import("@/views/studentYDManage.vue");
+const zhuanruinfo = () => import("@/views/zhuanruinfo.vue");
+const zhuanruinfostu = () => import("@/views/zhuanruinfostu.vue");
+const dailySearch = () => import("@/views/dailySearch.vue");
+
+const routes: RouteRecordRaw[] = [
+ {
+ path: "/",
+ name: "root",
+ component: { render: () => null },
+ },
+ {
+ path: "/studySystemChoice",
+ name: "studySystemChoice",
+ component: studySystemChoice,
+ meta: { title: "学制选择", modId: 1, icon: "icon-shezhi" },
+ },
+ {
+ path: "/itemSet",
+ name: "itemSet",
+ component: itemSet,
+ meta: { title: "时段设置", modId: 2, icon: "icon-shezhi" },
+ },
+ {
+ path: "/areaOperateDaily",
+ name: "areaOperateDaily",
+ component: areaOperateDaily,
+ meta: { title: "区域操作日志", modId: 3, icon: "icon-chaxun" },
+ },
+ {
+ path: "/schoolSetting",
+ name: "schoolSetting",
+ component: schoolSetting,
+ meta: { title: "学校设置", modId: 4, icon: "icon-cshxd" },
+ },
+ {
+ path: "/subjectManForZy",
+ name: "subjectManForZy",
+ component: subjectManForZy,
+ meta: { title: "课程设置", modId: 5, icon: "icon-xuekeshezhi" },
+ },
+ {
+ path: "/subjectSetzhi",
+ name: "subjectSetzhi",
+ component: subjectSetzhi,
+ meta: { title: "学科管理", modId: 6, icon: "icon-xuekeshezhi" },
+ },
+ {
+ path: "/classManage",
+ name: "classManage",
+ component: classManage,
+ meta: { title: "班级管理", modId: 7, icon: "icon-banji" },
+ },
+ {
+ path: "/ChristianityDetail",
+ name: "ChristianityDetail",
+ component: ChristianityDetail,
+ meta: { title: "班级管理", modId: 7, parentPath: "/classManage" },
+ },
+ {
+ path: "/electiveClassManage",
+ name: "electiveClassManage",
+ component: electiveClassManage,
+ meta: { title: "选修班管理", modId: 8, icon: "icon-banji" },
+ },
+ {
+ path: "/electiveClassManageDetail",
+ name: "electiveClassManageDetail",
+ component: electiveClassManageDetail,
+ meta: { title: "选修班管理", modId: 8, parentPath: "/electiveClassManage" },
+ },
+ {
+ path: "/teacherManage",
+ name: "teacherManage",
+ component: teacherManage,
+ meta: { title: "教师管理", modId: 9, icon: "icon-jiaoshi" },
+ },
+ {
+ path: "/studentManage",
+ name: "studentManage",
+ component: studentManage,
+ meta: { title: "学生管理", modId: 10, icon: "icon-xuesheng" },
+ },
+ {
+ path: "/historySearch",
+ name: "historySearch",
+ component: historySearch,
+ meta: { title: "历史查询", modId: 11, icon: "icon-chaxun" },
+ },
+ {
+ path: "/historySearchDetail",
+ name: "historySearchDetail",
+ component: historySearchDetail,
+ meta: { title: "历史查询", modId: 11, parentPath: "/historySearch" },
+ },
+ {
+ path: "/studentYDManage",
+ name: "studentYDManage",
+ component: studentYDManage,
+ meta: { title: "学生异动管理", modId: 12, icon: "icon-xuesheng" },
+ },
+ {
+ path: "/zhuanruinfo",
+ name: "zhuanruinfo",
+ component: zhuanruinfo,
+ meta: { title: "教师转入管理", modId: 13, icon: "icon-jiaoshi" },
+ },
+ {
+ path: "/zhuanruinfostu",
+ name: "zhuanruinfostu",
+ component: zhuanruinfostu,
+ meta: { title: "学生转入管理", modId: 14, icon: "icon-xuesheng" },
+ },
+ {
+ path: "/dailySearch",
+ name: "dailySearch",
+ component: dailySearch,
+ meta: { title: "日志管理", modId: 15, icon: "icon-chaxun" },
+ },
+];
+
+export default routes;
diff --git a/src/types/global.d.ts b/src/types/global.d.ts
new file mode 100644
index 0000000..ade852e
--- /dev/null
+++ b/src/types/global.d.ts
@@ -0,0 +1,16 @@
+declare module "*.vue" {
+ import type { DefineComponent } from "vue";
+ const component: DefineComponent<{}, {}, any>;
+ export default component;
+}
+
+declare const APIConfig: any;
+declare const $: any;
+declare const jQuery: any;
+
+interface Window {
+ conf: any;
+ APIConfig: any;
+ __APP_CONFIG__: any;
+ __YH_THEME_STATIC_BASE__?: string;
+}
diff --git a/src/utils/bus.ts b/src/utils/bus.ts
new file mode 100644
index 0000000..4ca7a6c
--- /dev/null
+++ b/src/utils/bus.ts
@@ -0,0 +1,18 @@
+import mitt from "mitt";
+
+/**
+ * 事件总线:保留 Vue2 时代的 $on / $off / $emit 调用形态,
+ * 业务代码(layout 的 setNavPath / setMenuPath)无需改动。
+ */
+const emitter = mitt();
+
+const bus = {
+ $on: emitter.on,
+ $off: emitter.off,
+ $emit: emitter.emit,
+ on: emitter.on,
+ off: emitter.off,
+ emit: emitter.emit,
+};
+
+export default bus;
diff --git a/src/utils/directive/index.ts b/src/utils/directive/index.ts
new file mode 100644
index 0000000..3e1f8b0
--- /dev/null
+++ b/src/utils/directive/index.ts
@@ -0,0 +1,12 @@
+import hljs from "highlight.js";
+
+/** 代码高亮指令(Vue3:mounted 替代 Vue2 的 bind/inserted) */
+export default function registerDirectives(app: any) {
+ app.directive("highlight", {
+ mounted(el: HTMLElement) {
+ el.querySelectorAll("pre code").forEach(block => {
+ hljs.highlightElement(block as HTMLElement);
+ });
+ },
+ });
+}
diff --git a/src/utils/index.js b/src/utils/index.js
index ab477cf..29eb4f0 100644
--- a/src/utils/index.js
+++ b/src/utils/index.js
@@ -43,15 +43,15 @@ export default {
const loop = function (nodes, parentNode) {
for (let node of nodes) {
// 清空所有节点选中状态
- vueThis.$set(node, 'selected', false)
+ node.selected = false
if (node.id === targetId) {
// 目标节点设为选中
- vueThis.$set(node, 'selected', true)
+ node.selected = true
let p = parentNode
// 逐层向上展开父节点
while (p) {
- vueThis.$set(p, 'expand', true)
+ p.expand = true
p = p._parent
}
return true
diff --git a/src/utils/menuRoute.ts b/src/utils/menuRoute.ts
new file mode 100644
index 0000000..bd03b53
--- /dev/null
+++ b/src/utils/menuRoute.ts
@@ -0,0 +1,146 @@
+import routes from "@/router/routes";
+
+/**
+ * 平台模块配置 → 前端内部路由的统一解析器(对齐 NoticeFront @/utils/menuRoute)。
+ * 平台配置的 path 格式不可控(旧前缀 / index.html#/hash / 完整 URL / 配错),
+ * 侧边栏跳转与高亮、登录后默认跳转都必须先经过这里,禁止手拼路由。
+ */
+const ROUTE_PATHS: string[] = routes
+ .map((r: any) => (typeof r.redirect === "string" ? r.redirect : r.path))
+ .filter((p: any): p is string => !!p && !String(p).includes(":"));
+
+const ROUTE_BY_MODID = new Map
();
+for (const r of routes as any[]) {
+ const modId = r.meta?.modId as number | undefined;
+ if (!modId || !r.path || String(r.path).includes(":") || r.redirect) continue;
+ if (!ROUTE_BY_MODID.has(modId)) ROUTE_BY_MODID.set(modId, r.path);
+}
+
+const ROUTE_BY_TITLE = new Map();
+for (const r of routes as any[]) {
+ if (r.redirect || !r.path || String(r.path).includes(":")) continue;
+ const title = r.meta?.title as string | undefined;
+ if (title && !ROUTE_BY_TITLE.has(title)) ROUTE_BY_TITLE.set(title, r.path);
+}
+
+/** 平台历史模块名 → 路由(旧菜单叫法与现页面标题不一致时的对照) */
+const NAME_ALIASES: Record = {
+ 学制设置: "/studySystemChoice",
+ 时段管理: "/itemSet",
+ 学校管理: "/schoolSetting",
+ 课程管理: "/subjectManForZy",
+ 学科设置: "/subjectSetzhi",
+ 班级列表: "/classManage",
+ 选修班: "/electiveClassManage",
+ 教师列表: "/teacherManage",
+ 学生列表: "/studentManage",
+ 日志查询: "/dailySearch",
+};
+
+/** 本应用历史上下文前缀(/bschclass、/userclass、/BschClassSystem)→ 去掉后比对 */
+const LEGACY_PREFIXES = ["/bschclass", "/userclass", "/bschclasssystem"];
+
+const EXTERNAL_RE = /^(https?:)?\/\//i;
+
+function extractCandidate(raw: string): string {
+ let p = raw.trim();
+ try {
+ p = decodeURIComponent(p);
+ } catch {
+ /* 非法编码保持原样 */
+ }
+ const hashIdx = p.indexOf("#");
+ if (hashIdx >= 0) {
+ p = p.slice(hashIdx + 1);
+ } else if (EXTERNAL_RE.test(p)) {
+ try {
+ p = new URL(p, "http://placeholder.local").pathname;
+ } catch {
+ /* 保持原样 */
+ }
+ }
+ const qIdx = p.indexOf("?");
+ if (qIdx >= 0) p = p.slice(0, qIdx);
+ p = p.replace(/index\.html?$/i, "");
+ p = p.replace(/\/+$/, "");
+ if (p && !p.startsWith("/")) p = "/" + p;
+ return p;
+}
+
+function matchRoute(candidate: string): string | null {
+ if (!candidate) return null;
+ const lower = candidate.toLowerCase();
+ const exact = ROUTE_PATHS.find((p: string) => p.toLowerCase() === lower);
+ if (exact) return exact;
+ for (const prefix of LEGACY_PREFIXES) {
+ if (lower.startsWith(prefix + "/")) {
+ const stripped = lower.slice(prefix.length);
+ const hit = ROUTE_PATHS.find((p: string) => p.toLowerCase() === stripped);
+ if (hit) return hit;
+ }
+ }
+ return null;
+}
+
+function matchByName(name?: string | null): string | null {
+ const n = String(name ?? "").trim();
+ if (!n) return null;
+ const byTitle = ROUTE_BY_TITLE.get(n);
+ if (byTitle) return byTitle;
+ const alias = NAME_ALIASES[n];
+ if (alias) return alias;
+ const hits = [...ROUTE_BY_TITLE.entries()].filter(
+ ([title]) => title.length >= 2 && (n.includes(title) || title.includes(n))
+ );
+ return hits.length === 1 ? hits[0][1] : null;
+}
+
+function isAppEntryCandidate(candidate: string): boolean {
+ if (!candidate || candidate === "/") return true;
+ return LEGACY_PREFIXES.some(p => candidate === p);
+}
+
+export interface ResolvedMenuPage {
+ path: string;
+ external: boolean;
+}
+
+export const EMPTY_MENU_PAGE: ResolvedMenuPage = { path: "", external: false };
+
+export function resolveMenuPage(
+ page?: string | null,
+ modId?: number | null,
+ name?: string | null
+): ResolvedMenuPage {
+ const raw = String(page ?? "").trim();
+ const byName = (): string | null => matchByName(name);
+ const byModId = (): string | null => (modId != null ? ROUTE_BY_MODID.get(modId) ?? null : null);
+
+ if (raw) {
+ const candidate = extractCandidate(raw);
+ const byPath = matchRoute(candidate);
+ if (byPath) return { path: byPath, external: false };
+
+ if (EXTERNAL_RE.test(raw) && !raw.includes("#")) {
+ if (!isAppEntryCandidate(candidate)) {
+ return { path: raw, external: true };
+ }
+ }
+
+ const fallback = byName() ?? byModId();
+ if (fallback) return { path: fallback, external: false };
+
+ console.warn(
+ "[menuRoute] 模块路径/名称/modId 均无法匹配前端路由,请检查基础平台模块配置:",
+ raw,
+ "modId =", modId,
+ "name =", name
+ );
+ return EMPTY_MENU_PAGE;
+ }
+
+ const fallback = byName() ?? byModId();
+ if (fallback) return { path: fallback, external: false };
+ console.warn("[menuRoute] 模块未配置路径且名称/modId 无法识别:", name, "modId =", modId);
+ return EMPTY_MENU_PAGE;
+}
diff --git a/src/views/areaOperateDaily.vue b/src/views/areaOperateDaily.vue
index cdc6a11..54fb15e 100644
--- a/src/views/areaOperateDaily.vue
+++ b/src/views/areaOperateDaily.vue
@@ -28,7 +28,7 @@
@@ -42,10 +42,10 @@
-