mvframe 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,163 @@
1
+ # MVFrame
2
+
3
+ 面向 **Vue 3 + Vite** 的管理端场景封装:**布局(Frame)**、**常用业务组件**、**全局工具/指令**、**Pinia 工厂与 Tabs 路由联动**、**可组合的 composition 模块**以及 **SCSS 工具类与主题变量**。工具与部分构建配置针对 SaaS 后台类项目做了取舍,更适合与同类技术栈的项目对齐使用,而非追求完全零依赖的通用库。
4
+
5
+ ---
6
+
7
+ ## 技术栈与依赖
8
+
9
+ | 类型 | 说明 |
10
+ |------|------|
11
+ | 运行时 | `vue` ^3.3、`vue-router` ^4.6、`pinia` ^3 |
12
+ | 演示 / 开发 | `element-plus`(demo 中用于表单等)、`vite` ^6、`sass-embedded` |
13
+ | 构建 | Library 模式产物为 ES 模块;`vue` / `pinia` / `vue-router` 为 **external**,由上层应用提供 |
14
+
15
+ `package.json` 中声明的发布入口包括:
16
+
17
+ - `"."` → `dist/index.js`(主插件,默认导出 `install` 函数)
18
+ - `"./composition"` → `dist/composition.js`
19
+ - `"./store"`、`"./directive"` → 对应 `dist` 下的分包(与 Rollup `manualChunks` 一致时存在)
20
+ - `"./style"` → `dist/style.css`(**需在构建流程中产出 CSS 后**方可使用;本地开发通常直接引用源码样式,见下文)
21
+
22
+ ---
23
+
24
+ ## 仓库目录概览
25
+
26
+ ### `src/` — 库源码
27
+
28
+ | 路径 | 作用 |
29
+ |------|------|
30
+ | `src/index.js` | **统一安装入口**:依次注册 `config` → 全局组件 `cpt` → `util` → `directive` → `store` → `router` |
31
+ | `src/config/` | 合并默认配置与调用方传入项,挂载 `globalThis.$config`(`chip/base.js` 含 name、copyright、version 等) |
32
+ | `src/cpt/index.js` | 通过 `import.meta.glob("../component/*/index.vue")` **自动全局注册**所有「一层子目录 + `index.vue`」的组件,组件名与**文件夹名**一致(PascalCase,如 `BtnGroup`) |
33
+ | `src/component/` | 全局组件实现,根节点 class 约定为 `Mvc` + 组件名(详见 `.cursor/rules/component-hierarchy.mdc`) |
34
+ | `src/util/index.js` | 挂到 `app.config.globalProperties` 与 `globalThis` 的工具方法(如 `$getLang`、`$fa`、`$copy`、`$deepClone` 等) |
35
+ | `src/directive/index.js` | 全局指令:`v-copy`(支持 `.dblclick`)、`v-focus` |
36
+ | `src/store/` | `createPinia` + 内置 `init` / `tab` / `rmenu`;支持 `storeChips` 动态注册;`provide("store", store)` |
37
+ | `src/router/` | `createWebHistory` 创建路由;可选 `guard`;内置 `guardThis`(`meta.admin`、`afterEach` 中与 `tab` 联动、`document.title`) |
38
+ | `src/composition/` | **按需 import**,导出 `lang` / `dom` / `data` / `media` 等(别名 `@cps` 在 Vite 中指向此目录) |
39
+ | `src/style/` | 样式总入口 `index.scss`,按需 `@use` 各 `chip/*.scss`(变量、间距、字体、布局、组件覆盖等) |
40
+
41
+ **当前 `src/component/` 下的全局组件(文件夹名即注册名):**
42
+
43
+ `BtnGroup`、`Form`、`Frame`、`Icon`、`Input`、`Page`、`Select`、`SelectV2`、`Table`、`Tabs`、`Textarea`
44
+
45
+ 子目录 `chip/` 为各组件内部拆片(如 `Frame/chip/Menu.vue`、`Table/chip/ColumnConfig.vue`),不单独注册。
46
+
47
+ ### `demo/` — 本地预览工程
48
+
49
+ Vite 在 **`NODE_ENV=development`** 下将 **`root` 设为 `./demo`**(见根目录 `vite.config.js`),用于跑通 Frame + 路由 + 组件演示。
50
+
51
+ | 文件 | 作用 |
52
+ |------|------|
53
+ | `demo/index.html` | 入口 HTML |
54
+ | `demo/main.js` | 创建应用:`ElementPlus` + 引入 `../src/index.js` + `../src/style/index.scss` + `routes` |
55
+ | `demo/App.vue` | 使用 **`Frame`** 布局,传入 `menu: { iconClass: 'imicon', routes }`,插槽 `logo` / `logomini` |
56
+ | `demo/routes.js` | 演示路由表:`/` → `Overview/Home`(组件与 Table 演示),`/a` → `A/Home`;含多级 `children` 用于侧栏结构 |
57
+ | `demo/views/Overview/Home.vue` | 使用 **`Page`** + **`Tabs`**,`Tabs` 切换 **`FormPanel`** / **`IconPanel`** |
58
+ | `demo/views/Overview/Home/FormPanel.vue` | Form 等表单控件演示 |
59
+ | `demo/views/Overview/Home/IconPanel.vue`、`iconfontAntNames.js` | 图标展示与 Ant 图标名列表 |
60
+ | `demo/auto-imports.d.ts` | `unplugin-auto-import` 生成的类型声明(Vue / vue-router) |
61
+
62
+ 本地开发:
63
+
64
+ ```bash
65
+ yarn install
66
+ yarn dev
67
+ ```
68
+
69
+ 默认开发服务器端口为 **8088**(见 `vite.config.js`)。
70
+
71
+ ### 路径别名(开发与库内)
72
+
73
+ | 别名 | 指向 |
74
+ |------|------|
75
+ | `@` | `src/` |
76
+ | `@cps` | `src/composition/` |
77
+ | `@scss` | `assets/scss`(若存在) |
78
+
79
+ 演示里路由组件使用形如 `import("/views/Overview/Home.vue")` 的路径,解析相对于 **`demo`** 根目录。
80
+
81
+ ---
82
+
83
+ ## 在上层应用中安装
84
+
85
+ ### 1. 安装依赖
86
+
87
+ 业务项目需自行安装并对齐版本:**`vue`、`vue-router`、`pinia`**。若使用 `Form` / `Table` 等与 Element Plus 绑定的能力,还需安装 **`element-plus`** 并在应用中 `app.use(ElementPlus)`。
88
+
89
+ ### 2. 注册 MVFrame
90
+
91
+ ```js
92
+ import { createApp } from "vue";
93
+ import mvframe from "mvframe";
94
+ // 样式:源码依赖 / monorepo 可用包内路径;仅发布 dist 时见下文「样式」小节
95
+ import "mvframe/src/style/index.scss";
96
+
97
+ const app = createApp(App);
98
+
99
+ app.use(mvframe, {
100
+ vueRouter: {
101
+ routes: yourRoutes,
102
+ // 可选:自定义 beforeEach 等
103
+ // guard: (router) => { /* ... */ },
104
+ // useAdmin: true,
105
+ // adminPermission: () => true,
106
+ // noaccess: (next) => next(false),
107
+ },
108
+ pinia: {
109
+ useTab: true, // 为 true 时启用多 Tab 与 localStorage 恢复(tabs / ctab)
110
+ // storeChips: import.meta.glob("./pinia/chip/*.js", { eager: true }),
111
+ },
112
+ config: {
113
+ // 会与 src/config/chip/base.js 合并后赋给 globalThis.$config
114
+ iconfont: {
115
+ url: "//at.alicdn.com/t/c/your_font.js",
116
+ prefix: "ant",
117
+ },
118
+ },
119
+ });
120
+ ```
121
+
122
+ **Frame** 组件在挂载时根据 `globalThis.$config.iconfont.url` 动态插入 `script` 加载图标字体(加载后源码中会删除 `url` 字段以避免重复插入)。
123
+
124
+ ### 3. 全局能力摘要
125
+
126
+ - **`globalThis.$config`**:应用配置
127
+ - **`globalThis.$router`**:安装后由本库赋值的 router 实例
128
+ - **`inject("store")`**:得到 **store 工厂对象**,如 `store.tab()`、`store.rmenu()` 及自定义 chip
129
+ - **全局组件**:直接使用 `Frame`、`Page`、`Table` 等,无需再注册
130
+ - **指令**:`v-copy`、`v-focus`
131
+ - **composition**:`import { ... } from "mvframe/composition"` 或项目内 `@cps` 指向的等价路径
132
+
133
+ 工具方法完整列表与约定见仓库内 **`.cursor/rules/util.mdc`** 与 **`src/util/index.js`**。
134
+
135
+ ### 4. 样式
136
+
137
+ - 工具类与变量说明见 `.cursor/rules/style-system.mdc`(`--color-*`、间距、字体、布局类等)。
138
+ - SCSS 会通过 `vite.config.js` 的 **`additionalData`** 注入 **`src/style/chip/mixin.scss`**,与库同构构建的业务项目可保持一致配置。
139
+ - 若 NPM 包仅发布 `dist` 且未包含 `style.css`,需在业务工程中从 Git 路径或 monorepo 链入 **`src/style/index.scss`**,或自行扩展库的 Vite 构建以导出 CSS。
140
+
141
+ ---
142
+
143
+ ## 构建库
144
+
145
+ ```bash
146
+ yarn build
147
+ ```
148
+
149
+ 生产构建使用 **library 模式**,入口为 `src/index.js`,并对产物启用混淆等插件(见 `vite.config.js`)。**开发时** `NODE_ENV` 为 `development` 时走的是 **demo** 工程,若需本地验证构建结果,请在执行 `vite build` 时使用生产环境变量。
150
+
151
+ ---
152
+
153
+ ## 设计取向与注意
154
+
155
+ - 布局、路由守卫、Tab、菜单等 **强绑定一套交互模型**;深度定制时可局部 fork `src/router`、`src/store/tab.js` 或外层包一层封装。
156
+ - **组件 class 与单位**:根节点 `Mvc*` + 子命名 camelCase;组件内尺寸除 1px/2px 外建议 **rem**(根号 16px),与 `style-system.mdc` 一致。
157
+ - 工具函数、Store、路由在非 setup 场景(如守卫)中通过 **`globalThis`** 或 **`store` / `pinia` 导出**访问,与 `src/router/chip/guard.js` 用法一致。
158
+
159
+ ---
160
+
161
+ ## 协议
162
+
163
+ ISC(见 `package.json`)。
@@ -0,0 +1,190 @@
1
+ const C = (n = {}) => {
2
+ const e = (t, r) => {
3
+ if (t)
4
+ if (r && globalThis.$getType(r) === "Object") {
5
+ let o = n[t] || t;
6
+ return Object.keys(r).forEach((s) => {
7
+ o[`{${s}}`] = r[s];
8
+ }), o;
9
+ } else
10
+ return n[t] || t;
11
+ else
12
+ return t;
13
+ };
14
+ globalThis.$l = e, String.prototype.$l = e;
15
+ }, U = (n, e) => {
16
+ if (!n || !e) return !1;
17
+ const t = n.getBoundingClientRect(), r = e.getBoundingClientRect(), o = r.right > t.left && r.left < t.right, s = r.bottom > t.top && r.top < t.bottom;
18
+ return o && s;
19
+ }, _ = (n, e) => {
20
+ if (n === e) return !0;
21
+ if (n == null || e == null || typeof n != "object" || typeof e != "object")
22
+ return JSON.stringify(n) === JSON.stringify(e);
23
+ const t = Object.keys(n), r = Object.keys(e);
24
+ if (t.length !== r.length) return !1;
25
+ for (const o of t)
26
+ if (!r.includes(o) || !_(n[o], e[o])) return !1;
27
+ return !0;
28
+ }, g = "download";
29
+ const O = (n, e = g) => {
30
+ const t = e || g, r = String(n ?? "").trim();
31
+ if (!r) return t;
32
+ const s = r.replace(/[/\\?%*:|"<>]/g, "_").replace(/\.\./g, "_").split(/[/\\]/).pop() || t, i = 200;
33
+ return s.length > i ? s.slice(0, i) : s;
34
+ }, R = (n) => {
35
+ const e = ((n == null ? void 0 : n.type) || "").toLowerCase();
36
+ return e ? e.includes("spreadsheet") || e.includes("ms-excel") || e.includes("excel") && e.includes("application") : !1;
37
+ }, h = (n, e) => {
38
+ const t = URL.createObjectURL(n), r = O(e), o = document.createElement("a");
39
+ o.href = t, o.download = r, o.style.display = "none", document.body.appendChild(o);
40
+ try {
41
+ o.click();
42
+ } finally {
43
+ document.body.removeChild(o), setTimeout(() => URL.revokeObjectURL(t), 150);
44
+ }
45
+ }, k = (n) => {
46
+ if (!n || n.source !== void 0 || n.type === void 0)
47
+ return n;
48
+ const { type: e, data: t, url: r, headers: o, name: s, filename: i, init: c, ...f } = n, a = i ?? s;
49
+ return e === "csv" ? {
50
+ ...f,
51
+ source: "inline",
52
+ content: t,
53
+ filename: a,
54
+ bom: n.bom
55
+ } : e === "excel" ? {
56
+ ...f,
57
+ source: "fetch",
58
+ url: r,
59
+ init: { ...c || {}, headers: o ?? (c == null ? void 0 : c.headers) },
60
+ response: "blob",
61
+ expectExcel: !0,
62
+ filename: a
63
+ } : n;
64
+ }, N = async (n = {}) => {
65
+ const e = k(n), {
66
+ source: t = "inline",
67
+ content: r,
68
+ blob: o,
69
+ bom: s = !0,
70
+ mime: i,
71
+ url: c,
72
+ init: f,
73
+ response: a = "blob",
74
+ openIn: b = "self",
75
+ expectExcel: E,
76
+ filename: x,
77
+ name: m,
78
+ error: u = () => {
79
+ },
80
+ // 避免 legacy 字段渗入后续逻辑
81
+ type: L,
82
+ data: $,
83
+ headers: T,
84
+ ...j
85
+ } = e, d = x ?? m;
86
+ try {
87
+ if (t === "inline") {
88
+ if (o instanceof Blob) {
89
+ h(o, d);
90
+ return;
91
+ }
92
+ if (r == null) {
93
+ u(new Error("content or blob is required for inline"));
94
+ return;
95
+ }
96
+ const l = typeof r == "string" ? r : String(r), p = s ? "\uFEFF" + l : l, y = i || (s ? "text/csv;charset=utf-8" : "text/plain;charset=utf-8");
97
+ h(new Blob([p], { type: y }), d);
98
+ return;
99
+ }
100
+ if (t === "fetch") {
101
+ if (!c) {
102
+ u(new Error("url is required for fetch"));
103
+ return;
104
+ }
105
+ const l = await fetch(c, f);
106
+ if (!l.ok) {
107
+ u(new Error(`fetch failed: ${l.status}`));
108
+ return;
109
+ }
110
+ if (a === "text") {
111
+ const y = await l.text(), w = s ? "\uFEFF" + y : y, S = i || (s ? "text/csv;charset=utf-8" : "text/plain;charset=utf-8");
112
+ h(new Blob([w], { type: S }), d);
113
+ return;
114
+ }
115
+ const p = await l.blob();
116
+ if (E && !R(p)) {
117
+ u(new Error("excel does not exist"));
118
+ return;
119
+ }
120
+ h(p, d);
121
+ return;
122
+ }
123
+ if (t === "open") {
124
+ if (!c) {
125
+ u(new Error("url is required for open"));
126
+ return;
127
+ }
128
+ b === "blank" ? window.open(c, "_blank", "noopener,noreferrer") : window.location.href = c;
129
+ return;
130
+ }
131
+ u(new Error(`unknown source: ${t}`));
132
+ } catch (l) {
133
+ u(l instanceof Error ? l : new Error(String(l)));
134
+ }
135
+ };
136
+ function B(n, e, t) {
137
+ if (e === "" || e === void 0 || e === null)
138
+ return "";
139
+ const r = globalThis.$fa, o = globalThis.$fu, s = (t == null ? void 0 : t.precision) ?? 2, i = t == null ? void 0 : t.unit;
140
+ if ((i === "currency" || i === "%") && o) {
141
+ const c = {
142
+ [n]: {
143
+ unit: i === "currency" ? "currency" : "%",
144
+ precision: s
145
+ }
146
+ };
147
+ try {
148
+ return o({
149
+ prop: n,
150
+ currency: t == null ? void 0 : t.currency,
151
+ value: e,
152
+ obj: c
153
+ });
154
+ } catch {
155
+ }
156
+ }
157
+ if (r)
158
+ try {
159
+ return r(e, s);
160
+ } catch {
161
+ return String(e);
162
+ }
163
+ return String(e);
164
+ }
165
+ function V(n, e, t = {}) {
166
+ const { columns: r = [] } = n || {}, { resolveMetric: o } = t;
167
+ return !r.length || !e || typeof e != "object" ? [] : r.map((s) => {
168
+ const i = s.property ?? s.prop ?? "";
169
+ if (!i)
170
+ return "";
171
+ let c = e[i];
172
+ if (c === void 0 && (c = ""), c === "")
173
+ return "";
174
+ const f = typeof o == "function" ? o(i) : void 0;
175
+ try {
176
+ return B(i, c, f);
177
+ } catch {
178
+ return String(c);
179
+ }
180
+ });
181
+ }
182
+ export {
183
+ _ as deepEqual,
184
+ N as download,
185
+ B as formatSummaryCell,
186
+ U as isInView,
187
+ O as sanitizeDownloadFileName,
188
+ C as useLang,
189
+ V as useRemoteSummary
190
+ };
@@ -0,0 +1,65 @@
1
+ import { computed as o, openBlock as s, createElementBlock as i, normalizeClass as d, unref as c, Fragment as y, renderList as v, toDisplayString as S } from "vue";
2
+ /* empty css */
3
+ import { _ as z } from "../vendor.js";
4
+ const h = ["disabled", "onClick"], O = /* @__PURE__ */ Object.assign({
5
+ name: "MvcBtnGroup",
6
+ inheritAttrs: !1
7
+ }, {
8
+ __name: "index",
9
+ props: {
10
+ modelValue: {
11
+ type: [String, Number, Boolean],
12
+ default: void 0
13
+ },
14
+ options: {
15
+ type: Array,
16
+ default: () => []
17
+ },
18
+ valueKey: {
19
+ type: String,
20
+ default: "value"
21
+ },
22
+ labelKey: {
23
+ type: String,
24
+ default: "label"
25
+ },
26
+ disabled: {
27
+ type: Boolean,
28
+ default: !1
29
+ },
30
+ size: {
31
+ type: String,
32
+ default: "default",
33
+ validator: (a) => ["default", "small", "large"].includes(a)
34
+ }
35
+ },
36
+ emits: ["update:modelValue", "change"],
37
+ setup(a, { emit: g }) {
38
+ const t = a, u = g, r = (e) => e == null ? e : ["Object", "Array"].includes(globalThis.$getType(e)) ? e[t.valueKey] : e, m = (e) => e == null ? "" : ["Object", "Array"].includes(globalThis.$getType(e)) ? e[t.labelKey] : String(e), f = (e) => {
39
+ const l = r(e);
40
+ return l === t.modelValue && (l !== void 0 || t.modelValue !== void 0);
41
+ }, p = (e) => {
42
+ if (t.disabled) return;
43
+ const l = r(e);
44
+ u("update:modelValue", l), u("change", l);
45
+ }, _ = o(() => ({ small: "g4", default: "g6", large: "g8" })[t.size] ?? "g6"), b = o(() => t.size === "small" ? "sizeSmall" : t.size === "large" ? "sizeLarge" : "");
46
+ return (e, l) => (s(), i("div", {
47
+ class: d(["MvcBtnGroup flexMode", [c(_), c(b)]]),
48
+ role: "group"
49
+ }, [
50
+ (s(!0), i(y, null, v(t.options, (n) => (s(), i("button", {
51
+ key: r(n),
52
+ type: "button",
53
+ class: d(["btnItem", { isActive: f(n) }]),
54
+ disabled: t.disabled,
55
+ onClick: (A) => p(n)
56
+ }, S(m(n)), 11, h))), 128))
57
+ ], 2));
58
+ }
59
+ }), x = /* @__PURE__ */ z(O, [["__scopeId", "data-v-19946018"]]), k = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
60
+ __proto__: null,
61
+ default: x
62
+ }, Symbol.toStringTag, { value: "Module" }));
63
+ export {
64
+ k as _
65
+ };
@@ -0,0 +1,90 @@
1
+ import { reactive as v, getCurrentInstance as y, computed as j, watch as n, resolveComponent as O, openBlock as h, createElementBlock as w, createVNode as m, unref as a, withCtx as c, renderSlot as x } from "vue";
2
+ import { f as z } from "./chip.js";
3
+ import { deepEqual as u } from "../composition.js";
4
+ const V = { class: "MvcForm" }, S = /* @__PURE__ */ Object.assign({
5
+ name: "MvcForm"
6
+ }, {
7
+ __name: "index",
8
+ props: {
9
+ modelValue: {
10
+ type: Object,
11
+ default: /* @__PURE__ */ Object.create(null)
12
+ },
13
+ rules: {
14
+ type: Object,
15
+ default: /* @__PURE__ */ Object.create(null)
16
+ },
17
+ size: {
18
+ type: String,
19
+ default: "large"
20
+ }
21
+ },
22
+ setup(f, { expose: i, emit: d }) {
23
+ const t = f, r = v({
24
+ form: {}
25
+ }), { proxy: s } = y(), p = d, _ = async () => {
26
+ var e;
27
+ try {
28
+ return (e = s.$refs) != null && e.form ? (await s.$refs.form.validate(), g()) : !1;
29
+ } catch {
30
+ return !1;
31
+ }
32
+ }, g = () => r.form, b = j(() => {
33
+ const e = {};
34
+ for (let l in t.rules)
35
+ e[l] = t.rules[l].map((o) => ({
36
+ ...o,
37
+ ...o.message && { message: window.$l(o.message) }
38
+ }));
39
+ return e;
40
+ });
41
+ return n(
42
+ () => r.form,
43
+ (e) => {
44
+ e && !u(e, t.modelValue) && p("update:modelValue", e);
45
+ },
46
+ {
47
+ deep: !0
48
+ }
49
+ ), n(
50
+ () => t.modelValue,
51
+ (e) => {
52
+ e && !u(e, r.form) && (r.form = e);
53
+ },
54
+ {
55
+ immediate: !0,
56
+ deep: !0
57
+ }
58
+ ), i({
59
+ validate: _
60
+ }), (e, l) => {
61
+ const o = O("el-form");
62
+ return h(), w("div", V, [
63
+ m(o, {
64
+ ref: "form",
65
+ model: a(r).form,
66
+ rules: a(b),
67
+ size: t.size,
68
+ "validate-on-rule-change": !1,
69
+ "label-position": "top"
70
+ }, {
71
+ default: c(() => [
72
+ m(a(z), null, {
73
+ default: c(() => [
74
+ x(e.$slots, "default")
75
+ ]),
76
+ _: 3
77
+ })
78
+ ]),
79
+ _: 3
80
+ }, 8, ["model", "rules", "size"])
81
+ ]);
82
+ };
83
+ }
84
+ }), F = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
85
+ __proto__: null,
86
+ default: S
87
+ }, Symbol.toStringTag, { value: "Module" }));
88
+ export {
89
+ F as _
90
+ };
@@ -0,0 +1,78 @@
1
+ import { reactive as v, inject as h, onMounted as j, resolveComponent as y, openBlock as l, createElementBlock as O, createVNode as r, normalizeProps as d, guardReactiveProps as u, createSlots as T, withCtx as f, renderSlot as m, createElementVNode as $, unref as k, createBlock as M, createCommentVNode as C } from "vue";
2
+ import { M as I, T as B, F as E } from "./chip.js";
3
+ /* empty css */
4
+ import { _ as F } from "../vendor.js";
5
+ const P = { class: "MvcFrame" }, S = { class: "PageArea" }, w = /* @__PURE__ */ Object.assign({
6
+ name: "MvcFrame",
7
+ inheritAttrs: !1
8
+ }, {
9
+ __name: "index",
10
+ props: {
11
+ /* menu包含:
12
+ @params
13
+ options: vue-router的路由表
14
+ iconClass: 菜单图标样式名,iconfont创建时的样式名或其它自定义规则
15
+ logo: 菜单logo, vue dom
16
+ logomini: 菜单logo缩小时的样子, vue dom
17
+ */
18
+ menu: {
19
+ type: Object,
20
+ default: /* @__PURE__ */ Object.create(null)
21
+ },
22
+ page: {
23
+ type: Object,
24
+ default: /* @__PURE__ */ Object.create(null)
25
+ }
26
+ },
27
+ setup(p) {
28
+ const c = p;
29
+ v({});
30
+ const _ = h("store").tab();
31
+ j(() => {
32
+ g();
33
+ });
34
+ const g = () => {
35
+ b();
36
+ }, b = () => {
37
+ var e, n, o, i, s, a;
38
+ if ((n = (e = globalThis.$config) == null ? void 0 : e.iconfont) != null && n.url) {
39
+ const t = document.createElement("script");
40
+ if (t.id = "iconfont", t.type = "text/javascript", t.src = (i = (o = globalThis.$config) == null ? void 0 : o.iconfont) == null ? void 0 : i.url, document.getElementById("iconfont"))
41
+ return;
42
+ document.head.appendChild(t), (a = (s = globalThis.$config) == null ? void 0 : s.iconfont) == null || delete a.url;
43
+ }
44
+ };
45
+ return (e, n) => {
46
+ const o = y("router-view");
47
+ return l(), O("div", P, [
48
+ r(I, d(u(c.menu)), T({ _: 2 }, [
49
+ e.$slots.logo ? {
50
+ name: "logo",
51
+ fn: f(() => [
52
+ m(e.$slots, "logo", {}, void 0, !0)
53
+ ]),
54
+ key: "0"
55
+ } : void 0,
56
+ e.$slots.logomini ? {
57
+ name: "logomini",
58
+ fn: f(() => [
59
+ m(e.$slots, "logomini", {}, void 0, !0)
60
+ ]),
61
+ key: "1"
62
+ } : void 0
63
+ ]), 1040),
64
+ $("div", S, [
65
+ k(_).useTab ? (l(), M(B, { key: 0 })) : C("", !0),
66
+ r(o, d(u(c.page)), null, 16),
67
+ r(E)
68
+ ])
69
+ ]);
70
+ };
71
+ }
72
+ }), x = /* @__PURE__ */ F(w, [["__scopeId", "data-v-d0100e71"]]), D = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
73
+ __proto__: null,
74
+ default: x
75
+ }, Symbol.toStringTag, { value: "Module" }));
76
+ export {
77
+ D as _
78
+ };
@@ -0,0 +1,34 @@
1
+ import { reactive as c, onMounted as i, openBlock as r, createElementBlock as l, createElementVNode as a, unref as s } from "vue";
2
+ const _ = {
3
+ class: "MvcIcon",
4
+ "aria-hidden": "true"
5
+ }, f = ["xlink:href"], p = /* @__PURE__ */ Object.assign({
6
+ name: "MvcIcon"
7
+ }, {
8
+ __name: "index",
9
+ props: {
10
+ name: {
11
+ type: String,
12
+ default: "cloud"
13
+ }
14
+ },
15
+ setup(o) {
16
+ const t = c({
17
+ prefix: "imc"
18
+ });
19
+ return i(() => {
20
+ var e, n;
21
+ (n = (e = globalThis.$config) == null ? void 0 : e.iconfont) != null && n.prefix && (t.prefix = globalThis.$config.iconfont.prefix);
22
+ }), (e, n) => (r(), l("svg", _, [
23
+ a("use", {
24
+ "xlink:href": `#${s(t).prefix}-${o.name}`
25
+ }, null, 8, f)
26
+ ]));
27
+ }
28
+ }), d = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
29
+ __proto__: null,
30
+ default: p
31
+ }, Symbol.toStringTag, { value: "Module" }));
32
+ export {
33
+ d as _
34
+ };
@@ -0,0 +1,68 @@
1
+ import { ref as C, reactive as S, getCurrentInstance as b, onMounted as y, nextTick as V, computed as v, watch as w, onUnmounted as E, resolveComponent as I, openBlock as L, createBlock as k, mergeProps as M, unref as s } from "vue";
2
+ const $ = /* @__PURE__ */ Object.assign({
3
+ name: "MvcInput"
4
+ }, {
5
+ __name: "index",
6
+ props: {
7
+ modelValue: {
8
+ type: [String, Number],
9
+ default: ""
10
+ }
11
+ },
12
+ emits: [
13
+ "update:modelValue",
14
+ "input",
15
+ "change",
16
+ "blur",
17
+ "focus"
18
+ ],
19
+ setup(f, { emit: g }) {
20
+ const _ = f, a = C(null);
21
+ let e = null;
22
+ const n = S({
23
+ val: "",
24
+ isComposing: !1
25
+ }), l = g, { proxy: u } = b();
26
+ y(() => {
27
+ var o, i, r;
28
+ const t = (o = a.value) == null ? void 0 : o.$el;
29
+ e = ((i = t == null ? void 0 : t.querySelector) == null ? void 0 : i.call(t, "input")) || ((r = t == null ? void 0 : t.querySelector) == null ? void 0 : r.call(t, "textarea")), e && (e.addEventListener("compositionstart", m), e.addEventListener("compositionend", p));
30
+ });
31
+ const m = () => {
32
+ n.isComposing = !0;
33
+ }, p = () => {
34
+ n.isComposing = !1, V(() => c(n.val));
35
+ }, x = (t) => {
36
+ n.isComposing || c(t);
37
+ }, c = (t) => {
38
+ l("update:modelValue", t), l("input", t);
39
+ }, h = v(() => !!(u.$attrs.maxlength || d.value)), d = v(() => u.$attrs.max);
40
+ return w(
41
+ () => _.modelValue,
42
+ (t) => {
43
+ const o = String(t ?? "");
44
+ String(n.val) !== o && (n.val = o);
45
+ },
46
+ { immediate: !0 }
47
+ ), E(() => {
48
+ e && (e.removeEventListener("compositionstart", m), e.removeEventListener("compositionend", p), e = null);
49
+ }), (t, o) => {
50
+ const i = I("el-input");
51
+ return L(), k(i, M({
52
+ ref_key: "inputRef",
53
+ ref: a,
54
+ modelValue: s(n).val,
55
+ "onUpdate:modelValue": o[0] || (o[0] = (r) => s(n).val = r),
56
+ "show-word-limit": s(h),
57
+ maxlength: s(d),
58
+ class: "MvcInput"
59
+ }, t.$attrs, { onInput: x }), null, 16, ["modelValue", "show-word-limit", "maxlength"]);
60
+ };
61
+ }
62
+ }), B = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
63
+ __proto__: null,
64
+ default: $
65
+ }, Symbol.toStringTag, { value: "Module" }));
66
+ export {
67
+ B as _
68
+ };