mvframe 1.0.4 → 1.0.6
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/.cursor/skills/mvframe-app-init/SKILL.md +100 -0
- package/README.cn.md +209 -0
- package/README.md +118 -74
- package/dist/composition.js +67 -54
- package/dist/css/style.css +1 -0
- package/dist/vendor.js +1 -1
- package/package.json +23 -5
- package/scripts/install-cursor-skill.js +51 -0
- package/scripts/scaffold-app.js +467 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mvframe-app-init
|
|
3
|
+
description: >-
|
|
4
|
+
Scaffolds or audits Vue 3 + Vite host apps that use MVFrame: install order
|
|
5
|
+
(Element Plus, mvframe plugin, styles), Frame/menu/routes, Pinia options,
|
|
6
|
+
global config (iconfont, table.summaryMetric), Vite aliases, and views/layout
|
|
7
|
+
conventions. Use when the user initializes a project with mvframe, wires a
|
|
8
|
+
new app to @vue/mvframe, asks for MVFrame bootstrap or “same architecture
|
|
9
|
+
as mvframe”, or reviews structure against this library’s demo and rules.
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# MVFrame 应用初始化与架构对齐
|
|
13
|
+
|
|
14
|
+
在**消费方项目**(或 monorepo 业务包)中接入 MVFrame 时,按下列顺序与约定执行,并与本仓库 `demo/`、`.cursor/rules/` 保持一致。显式触发:用户说「初始化 / 脚手架 / 接入 mvframe / 与 mvframe 架构统一」。
|
|
15
|
+
|
|
16
|
+
## 1. 依赖与入口顺序
|
|
17
|
+
|
|
18
|
+
1. `createApp(App)`
|
|
19
|
+
2. **`app.use(ElementPlus)`**(使用 Form / Table 等依赖 EP 的能力时)
|
|
20
|
+
3. **`import` 本库样式**:`mvframe` 源码路径或 monorepo 下的 `.../src/style/index.scss`
|
|
21
|
+
4. **`app.use(mvframe, options)`** — 见下节
|
|
22
|
+
5. **`app.mount('#app')`**
|
|
23
|
+
|
|
24
|
+
`mvframe` 默认导出为 **install 函数**;注册顺序在库内为:`config` → 全局组件 → `util` → `directive` → `store` → `router`(见 `src/index.js`),调用方勿拆分或颠倒。
|
|
25
|
+
|
|
26
|
+
## 2. `app.use(mvframe, options)` 必备形状
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
app.use(mvframe, {
|
|
30
|
+
vueRouter: {
|
|
31
|
+
routes, // required
|
|
32
|
+
// guard, useAdmin, adminPermission, noaccess — 按需
|
|
33
|
+
},
|
|
34
|
+
pinia: {
|
|
35
|
+
useTab: true, // 多 Tab + localStorage 恢复时启用
|
|
36
|
+
// storeChips: import.meta.glob('./pinia/chip/*.js', { eager: true }),
|
|
37
|
+
},
|
|
38
|
+
config: {
|
|
39
|
+
iconfont: { url: '//...', prefix: '...' }, // Frame 挂载时注入 script
|
|
40
|
+
table: {
|
|
41
|
+
summaryMetric: { /* 或 (prop) => metric */ }, // 多表共用汇总/$fu 格式,可选
|
|
42
|
+
},
|
|
43
|
+
// 会与 src/config/chip/base.js 合并 → globalThis.$config
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- **`globalThis.$router`** 由库在安装路由后赋值。
|
|
49
|
+
- **Store**:组件内 `inject('store')` 取工厂,如 `store.tab()`。
|
|
50
|
+
- **Table 汇总**:单列优先 `summary-metric` prop,否则 `$config.table.summaryMetric`;`$fu` 与 `formatSummaryCell` 共用同一套 metric 配置。
|
|
51
|
+
|
|
52
|
+
## 3. 根组件与路由表
|
|
53
|
+
|
|
54
|
+
- 根布局使用 **`Frame`**,传入 `menu: { iconClass, routes }`(与 `demo/App.vue` 一致);`logo` / `logomini` 用插槽。
|
|
55
|
+
- **路由 `meta`**:至少 `title`(守卫里写 `document.title`);侧栏图标可用 `meta.icon`。
|
|
56
|
+
- **跳转**:优先 **`name`** 跳转,避免裸 `path`(见 `.cursor/rules/router.mdc`)。
|
|
57
|
+
|
|
58
|
+
## 4. Vite 对齐(消费方)
|
|
59
|
+
|
|
60
|
+
与库内一致可减少样式与路径问题:
|
|
61
|
+
|
|
62
|
+
| 项 | 建议 |
|
|
63
|
+
|----|------|
|
|
64
|
+
| `resolve.alias` | `@` → 业务 `src`;若直接引用 composition:`@cps` → `mvframe/.../composition` 或封装路径 |
|
|
65
|
+
| `css.preprocessorOptions.scss.additionalData` | 注入 mvframe 的 `chip/mixin.scss`(或与业务统一的 mixin) |
|
|
66
|
+
| 类型 | 若用 auto-import,为 `vue` / `vue-router` 生成 d.ts |
|
|
67
|
+
|
|
68
|
+
## 5. views 与应用层结构(消费方)
|
|
69
|
+
|
|
70
|
+
遵循 `.cursor/rules/views.mdc`:
|
|
71
|
+
|
|
72
|
+
- **`views` 下一级目录**:**PascalCase 模块名**;模块默认入口 **`Home.vue`**。
|
|
73
|
+
- **页面子组件**:与 `Xxx.vue` **同级**建 **`Xxx/`** 文件夹;子组件 `defineOptions({ name })` 使用 `{模块}{页面}{语义}` 拼接 PascalCase。
|
|
74
|
+
|
|
75
|
+
库内全局组件根 class:**`Mvc` + 组件名**;内部子 class **camelCase**(`.cursor/rules/component-hierarchy.mdc`)。业务页优先用库已注册组件名(`Frame`、`Page`、`Table` 等),勿重复注册。
|
|
76
|
+
|
|
77
|
+
## 6. 自检清单(Agent 生成/审查时用)
|
|
78
|
+
|
|
79
|
+
- [ ] Element Plus 在 mvframe 之前 `use`
|
|
80
|
+
- [ ] 已引入 `index.scss`(或等价主题入口),且 SCSS 与 mixin 策略与库一致
|
|
81
|
+
- [ ] `routes` 已传入,`Frame` 的 `menu.routes` 同源
|
|
82
|
+
- [ ] 需要多 Tab 时 `pinia.useTab: true`
|
|
83
|
+
- [ ] 需汇总格式化时配置 `config.table.summaryMetric` 或 Table `summary-metric`
|
|
84
|
+
- [ ] 路由跳转以 `name` 为主
|
|
85
|
+
- [ ] 业务 `views` 符合模块 / 同名文件夹 / 子组件命名规则
|
|
86
|
+
|
|
87
|
+
## 7. 参考文件(本仓库)
|
|
88
|
+
|
|
89
|
+
- `demo/main.js`、`demo/App.vue`、`demo/routes.js` — 最小可运行骨架
|
|
90
|
+
- `README.md` / `README.cn.md` — 目录与安装总览
|
|
91
|
+
- `.cursor/rules/*.mdc` — 组件 class、样式单位、router、views、util
|
|
92
|
+
|
|
93
|
+
在 **mvframe 仓库内开发库本身**时,改动以 `src/`、`demo/` 为准;技能主要面向 **引用 mvframe 的业务工程** 的初始化与对齐。
|
|
94
|
+
|
|
95
|
+
## 安装到业务工程
|
|
96
|
+
|
|
97
|
+
- **目录雏形(推荐)**:`yarn exec mvframe-init-app` 或 `node <mvframe>/scripts/scaffold-app.js`,生成 `src/views`、`router`、`pinia/chip`、`config` 等并写好 `main.js` + `App.use(mvframe)`;说明见目标项目根 `MVFRAME-SCAFFOLD.md`。
|
|
98
|
+
- **仅 Cursor Skill**:`yarn exec mvframe-install-cursor-skill` 或 `node <mvframe>/scripts/install-cursor-skill.js`(`MVFRAME_CURSOR_SKILL_OUT` 可选)。
|
|
99
|
+
|
|
100
|
+
详见仓库 `README.md` / `README.cn.md`。
|
package/README.cn.md
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# MVFrame
|
|
2
|
+
|
|
3
|
+
[English](README.md) | **简体中文**
|
|
4
|
+
|
|
5
|
+
面向 **Vue 3 + Vite** 的管理端场景封装:**布局(Frame)**、**常用业务组件**、**全局工具/指令**、**Pinia 工厂与 Tabs 路由联动**、**可组合的 composition 模块**以及 **SCSS 工具类与主题变量**。工具与部分构建配置针对 SaaS 后台类项目做了取舍,更适合与同类技术栈的项目对齐使用,而非追求完全零依赖的通用库。
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 技术栈与依赖
|
|
10
|
+
|
|
11
|
+
| 类型 | 说明 |
|
|
12
|
+
|------|------|
|
|
13
|
+
| 运行时 | `vue` ^3.3、`vue-router` ^4.6、`pinia` ^3 |
|
|
14
|
+
| 演示 / 开发 | `element-plus`(demo 中用于表单等)、`vite` ^6、`sass-embedded` |
|
|
15
|
+
| 构建 | Library 模式产物为 ES 模块;`vue` / `pinia` / `vue-router` 为 **external**,由上层应用提供 |
|
|
16
|
+
|
|
17
|
+
`package.json` 中声明的发布入口包括:
|
|
18
|
+
|
|
19
|
+
- `"."` → `dist/index.js`(主插件,默认导出 `install` 函数)
|
|
20
|
+
- `"./composition"` → `dist/composition.js`(`import { useMap, … } from 'mvframe/composition'`)
|
|
21
|
+
- `"./store"`、`"./directive"`、`"./util"` → 对应 `dist` 下分包
|
|
22
|
+
- `"./style"` → `dist/css/style.css`(由 `src/style/index.scss` 单独入口打包的全量工具类/变量)
|
|
23
|
+
- `"./style/cpt"` → `dist/css/cpt.css`(随组件抽取的样式;一般用 `mvframe/style` 即可)
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 仓库目录概览
|
|
28
|
+
|
|
29
|
+
### `src/` — 库源码
|
|
30
|
+
|
|
31
|
+
| 路径 | 作用 |
|
|
32
|
+
|------|------|
|
|
33
|
+
| `src/index.js` | **统一安装入口**:依次注册 `config` → 全局组件 `cpt` → `util` → `directive` → `store` → `router` |
|
|
34
|
+
| `src/config/` | 合并默认配置与调用方传入项,挂载 `globalThis.$config`(`chip/base.js` 含 name、copyright、version 等) |
|
|
35
|
+
| `src/cpt/index.js` | 通过 `import.meta.glob("../component/*/index.vue")` **自动全局注册**所有「一层子目录 + `index.vue`」的组件,组件名与**文件夹名**一致(PascalCase,如 `BtnGroup`) |
|
|
36
|
+
| `src/component/` | 全局组件实现,根节点 class 约定为 `Mvc` + 组件名(详见 `.cursor/rules/component-hierarchy.mdc`) |
|
|
37
|
+
| `src/util/index.js` | 挂到 `app.config.globalProperties` 与 `globalThis` 的工具方法(如 `$getLang`、`$fa`、`$copy`、`$deepClone` 等) |
|
|
38
|
+
| `src/directive/index.js` | 全局指令:`v-copy`(支持 `.dblclick`)、`v-focus` |
|
|
39
|
+
| `src/store/` | `createPinia` + 内置 `init` / `tab` / `rmenu`;支持 `storeChips` 动态注册;`provide("store", store)` |
|
|
40
|
+
| `src/router/` | `createWebHistory` 创建路由;可选 `guard`;内置 `guardThis`(`meta.admin`、`afterEach` 中与 `tab` 联动、`document.title`) |
|
|
41
|
+
| `src/composition/` | **按需 import**,导出 `lang` / `dom` / `data` / `media` 等(别名 `@cps` 在 Vite 中指向此目录) |
|
|
42
|
+
| `src/style/` | 样式总入口 `index.scss`,按需 `@use` 各 `chip/*.scss`(变量、间距、字体、布局、组件覆盖等) |
|
|
43
|
+
|
|
44
|
+
**当前 `src/component/` 下的全局组件(文件夹名即注册名):**
|
|
45
|
+
|
|
46
|
+
`BtnGroup`、`Form`、`Frame`、`Icon`、`Input`、`Page`、`Select`、`SelectV2`、`Table`、`Tabs`、`Textarea`
|
|
47
|
+
|
|
48
|
+
子目录 `chip/` 为各组件内部拆片(如 `Frame/chip/Menu.vue`、`Table/chip/ColumnConfig.vue`),不单独注册。
|
|
49
|
+
|
|
50
|
+
### `demo/` — 本地预览工程
|
|
51
|
+
|
|
52
|
+
Vite 在 **`NODE_ENV=development`** 下将 **`root` 设为 `./demo`**(见根目录 `vite.config.js`),用于跑通 Frame + 路由 + 组件演示。
|
|
53
|
+
|
|
54
|
+
| 文件 | 作用 |
|
|
55
|
+
|------|------|
|
|
56
|
+
| `demo/index.html` | 入口 HTML |
|
|
57
|
+
| `demo/main.js` | 创建应用:`ElementPlus` + 引入 `../src/index.js` + `../src/style/index.scss` + `routes` |
|
|
58
|
+
| `demo/App.vue` | 使用 **`Frame`** 布局,传入 `menu: { iconClass: 'imicon', routes }`,插槽 `logo` / `logomini` |
|
|
59
|
+
| `demo/routes.js` | 演示路由表:`/` → `Overview/Home`(组件与 Table 演示),`/a` → `A/Home`;含多级 `children` 用于侧栏结构 |
|
|
60
|
+
| `demo/views/Overview/Home.vue` | 使用 **`Page`** + **`Tabs`**,`Tabs` 切换 **`FormPanel`** / **`IconPanel`** |
|
|
61
|
+
| `demo/views/Overview/Home/FormPanel.vue` | Form 等表单控件演示 |
|
|
62
|
+
| `demo/views/Overview/Home/IconPanel.vue`、`iconfontAntNames.js` | 图标展示与 Ant 图标名列表 |
|
|
63
|
+
| `demo/auto-imports.d.ts` | `unplugin-auto-import` 生成的类型声明(Vue / vue-router) |
|
|
64
|
+
|
|
65
|
+
本地开发:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
yarn install
|
|
69
|
+
yarn dev
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
默认开发服务器端口为 **8088**(见 `vite.config.js`)。
|
|
73
|
+
|
|
74
|
+
### 路径别名(开发与库内)
|
|
75
|
+
|
|
76
|
+
| 别名 | 指向 |
|
|
77
|
+
|------|------|
|
|
78
|
+
| `@` | `src/` |
|
|
79
|
+
| `@cps` | `src/composition/` |
|
|
80
|
+
| `@scss` | `assets/scss`(若存在) |
|
|
81
|
+
|
|
82
|
+
演示里路由组件使用形如 `import("/views/Overview/Home.vue")` 的路径,解析相对于 **`demo`** 根目录。
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## 在上层应用中安装
|
|
87
|
+
|
|
88
|
+
### 1. 安装依赖
|
|
89
|
+
|
|
90
|
+
业务项目需自行安装并对齐版本:**`vue`、`vue-router`、`pinia`**。若使用 `Form` / `Table` 等与 Element Plus 绑定的能力,还需安装 **`element-plus`** 并在应用中 `app.use(ElementPlus)`。
|
|
91
|
+
|
|
92
|
+
### 2. 注册 MVFrame
|
|
93
|
+
|
|
94
|
+
```js
|
|
95
|
+
import { createApp } from "vue";
|
|
96
|
+
import mvframe from "mvframe";
|
|
97
|
+
// 样式:源码依赖 / monorepo 可用包内路径;仅发布 dist 时见下文「样式」小节
|
|
98
|
+
import "mvframe/src/style/index.scss";
|
|
99
|
+
|
|
100
|
+
const app = createApp(App);
|
|
101
|
+
|
|
102
|
+
app.use(mvframe, {
|
|
103
|
+
vueRouter: {
|
|
104
|
+
routes: yourRoutes,
|
|
105
|
+
// 可选:自定义 beforeEach 等
|
|
106
|
+
// guard: (router) => { /* ... */ },
|
|
107
|
+
// useAdmin: true,
|
|
108
|
+
// adminPermission: () => true,
|
|
109
|
+
// noaccess: (next) => next(false),
|
|
110
|
+
},
|
|
111
|
+
pinia: {
|
|
112
|
+
useTab: true, // 为 true 时启用多 Tab 与 localStorage 恢复(tabs / ctab)
|
|
113
|
+
// storeChips: import.meta.glob("./pinia/chip/*.js", { eager: true }),
|
|
114
|
+
},
|
|
115
|
+
config: {
|
|
116
|
+
// 会与 src/config/chip/base.js 合并后赋给 globalThis.$config
|
|
117
|
+
iconfont: {
|
|
118
|
+
url: "//at.alicdn.com/t/c/your_font.js",
|
|
119
|
+
prefix: "ant",
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**Frame** 组件在挂载时根据 `globalThis.$config.iconfont.url` 动态插入 `script` 加载图标字体(加载后源码中会删除 `url` 字段以避免重复插入)。
|
|
126
|
+
|
|
127
|
+
### 3. 全局能力摘要
|
|
128
|
+
|
|
129
|
+
- **`globalThis.$config`**:应用配置
|
|
130
|
+
- **`globalThis.$router`**:安装后由本库赋值的 router 实例
|
|
131
|
+
- **`inject("store")`**:得到 **store 工厂对象**,如 `store.tab()`、`store.rmenu()` 及自定义 chip
|
|
132
|
+
- **全局组件**:直接使用 `Frame`、`Page`、`Table` 等,无需再注册
|
|
133
|
+
- **指令**:`v-copy`、`v-focus`
|
|
134
|
+
- **composition**:`import { ... } from "mvframe/composition"` 或项目内 `@cps` 指向的等价路径
|
|
135
|
+
|
|
136
|
+
工具方法完整列表与约定见仓库内 **`.cursor/rules/util.mdc`** 与 **`src/util/index.js`**。
|
|
137
|
+
|
|
138
|
+
### 4. 样式
|
|
139
|
+
|
|
140
|
+
- 工具类与变量说明见 `.cursor/rules/style-system.mdc`(`--color-*`、间距、字体、布局类等)。
|
|
141
|
+
- SCSS 会通过 `vite.config.js` 的 **`additionalData`** 注入 **`src/style/chip/mixin.scss`**,与库同构构建的业务项目可保持一致配置。
|
|
142
|
+
- 发布包可 **`import 'mvframe/style'`**(即 `dist/css/style.css`);需与 Element Plus 等并存时仍可在业务工程中链入源码 **`src/style/index.scss`** 以便覆写变量。
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## 构建库
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
yarn build
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
生产构建使用 **library 模式**,入口为 `src/index.js`,并对产物启用混淆等插件(见 `vite.config.js`)。**开发时** `NODE_ENV` 为 `development` 时走的是 **demo** 工程,若需本地验证构建结果,请在执行 `vite build` 时使用生产环境变量。
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## 设计取向与注意
|
|
157
|
+
|
|
158
|
+
- 布局、路由守卫、Tab、菜单等 **强绑定一套交互模型**;深度定制时可局部 fork `src/router`、`src/store/tab.js` 或外层包一层封装。
|
|
159
|
+
- **组件 class 与单位**:根节点 `Mvc*` + 子命名 camelCase;组件内尺寸除 1px/2px 外建议 **rem**(根号 16px),与 `style-system.mdc` 一致。
|
|
160
|
+
- 工具函数、Store、路由在非 setup 场景(如守卫)中通过 **`globalThis`** 或 **`store` / `pinia` 导出**访问,与 `src/router/chip/guard.js` 用法一致。
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## 命令行:项目目录雏形(推荐)
|
|
165
|
+
|
|
166
|
+
在**空目录或已有 Vite 工程根目录**执行,生成 `src/views`、`src/component`、`src/api`、`src/assets/img`、`src/assets/style`、`src/router`、`src/pinia/chip`、`src/config` 及示例 `main.js` / `App.vue`(已 `app.use(mvframe, …)` 挂好路由、Pinia `storeChips`、config)。若不存在则附带 `index.html` 与 `vite.config.js`。会**合并** `package.json` 的 `dependencies` / `devDependencies`(与 Vite 模板一致;**同名包保留你原有版本**),最后请执行 **`yarn install`**;加 `--no-package-json` 可不改动 `package.json`。
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
cd /path/to/your-app
|
|
170
|
+
node /path/to/mvframe/scripts/scaffold-app.js
|
|
171
|
+
# 覆盖已有同名文件:
|
|
172
|
+
node /path/to/mvframe/scripts/scaffold-app.js --force
|
|
173
|
+
|
|
174
|
+
# 不修改 package.json(仅生成源码与配置):
|
|
175
|
+
node /path/to/mvframe/scripts/scaffold-app.js --no-package-json
|
|
176
|
+
|
|
177
|
+
# 安装 mvframe 后:
|
|
178
|
+
yarn exec mvframe-init-app
|
|
179
|
+
# 或:npx mvframe-init-app
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
生成说明见项目根 **`MVFRAME-SCAFFOLD.md`**。环境变量 **`MVFRAME_SCAFFOLD_TARGET`** 可指定目标路径。
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Cursor Skill(应用初始化)
|
|
187
|
+
|
|
188
|
+
本仓库自带 **`.cursor/skills/mvframe-app-init`**,消费方项目可复制到自身 `.cursor/skills` 以便 Cursor 识别 MVFrame 接入规范。
|
|
189
|
+
|
|
190
|
+
在**你的业务项目根目录**执行任一种方式:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
# 克隆 / monorepo 中指向 mvframe 源码时
|
|
194
|
+
node /path/to/mvframe/scripts/install-cursor-skill.js
|
|
195
|
+
node /path/to/mvframe/scripts/install-cursor-skill.js /path/to/your-app
|
|
196
|
+
|
|
197
|
+
# 安装 npm 包后(发布包需包含 scripts 与 .cursor/skills,见 package.json files)
|
|
198
|
+
cd /path/to/your-app
|
|
199
|
+
yarn exec mvframe-install-cursor-skill
|
|
200
|
+
# 或:npx mvframe-install-cursor-skill
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
默认安装到**当前工作目录**下的 `.cursor/skills/mvframe-app-init`。也可设置环境变量 `MVFRAME_CURSOR_SKILL_OUT=/path/to/your-app`。
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## 协议
|
|
208
|
+
|
|
209
|
+
ISC(见 `package.json`)。
|
package/README.md
CHANGED
|
@@ -1,97 +1,100 @@
|
|
|
1
1
|
# MVFrame
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**English** | [简体中文](README.cn.md)
|
|
4
|
+
|
|
5
|
+
A Vue 3 + Vite oriented admin-shell toolkit: **Frame layout**, **common business components**, **global utilities & directives**, **Pinia wiring with tabs/router**, **composable modules**, and **SCSS utilities & tokens**. Priorities favor SaaS-style admin apps over a fully pluggable, zero-opinion utility library.
|
|
4
6
|
|
|
5
7
|
---
|
|
6
8
|
|
|
7
|
-
##
|
|
9
|
+
## Stack & dependencies
|
|
8
10
|
|
|
9
|
-
|
|
|
11
|
+
| Kind | Notes |
|
|
10
12
|
|------|------|
|
|
11
|
-
|
|
|
12
|
-
|
|
|
13
|
-
|
|
|
13
|
+
| Runtime | `vue` ^3.3, `vue-router` ^4.6, `pinia` ^3 |
|
|
14
|
+
| Demo / dev | `element-plus` (demo forms, etc.), `vite` ^6, `sass-embedded` |
|
|
15
|
+
| Build | Library output is **ESM**; **`vue` / `pinia` / `vue-router` are externals** and must be supplied by the host app |
|
|
14
16
|
|
|
15
|
-
`package.json`
|
|
17
|
+
`package.json` exports include:
|
|
16
18
|
|
|
17
|
-
- `"."` → `dist/index.js
|
|
18
|
-
- `"./composition"` → `dist/composition.js`
|
|
19
|
-
- `"./store"
|
|
20
|
-
- `"./style"` → `dist/style.css
|
|
19
|
+
- `"."` → `dist/index.js` (main plugin; default export is the `install` function)
|
|
20
|
+
- `"./composition"` → `dist/composition.js` (e.g. `import { useMap } from 'mvframe/composition'`)
|
|
21
|
+
- `"./store"`, `"./directive"`, `"./util"` → matching chunks under `dist`
|
|
22
|
+
- `"./style"` → `dist/css/style.css` (full toolkit CSS from `src/style/index.scss` entry)
|
|
23
|
+
- `"./style/cpt"` → `dist/css/cpt.css` (component-extracted CSS; usually `import 'mvframe/style'` is enough)
|
|
21
24
|
|
|
22
25
|
---
|
|
23
26
|
|
|
24
|
-
##
|
|
27
|
+
## Repository layout
|
|
25
28
|
|
|
26
|
-
### `src/` —
|
|
29
|
+
### `src/` — library source
|
|
27
30
|
|
|
28
|
-
|
|
|
31
|
+
| Path | Role |
|
|
29
32
|
|------|------|
|
|
30
|
-
| `src/index.js` |
|
|
31
|
-
| `src/config/` |
|
|
32
|
-
| `src/cpt/index.js` |
|
|
33
|
-
| `src/component/` |
|
|
34
|
-
| `src/util/index.js` |
|
|
35
|
-
| `src/directive/index.js` |
|
|
36
|
-
| `src/store/` | `createPinia` +
|
|
37
|
-
| `src/router/` | `createWebHistory`
|
|
38
|
-
| `src/composition/` |
|
|
39
|
-
| `src/style/` |
|
|
33
|
+
| `src/index.js` | **Install entry**: registers `config` → global components (`cpt`) → `util` → `directive` → `store` → `router` |
|
|
34
|
+
| `src/config/` | Merges defaults with app options → `globalThis.$config` (`chip/base.js`: name, copyright, version, etc.) |
|
|
35
|
+
| `src/cpt/index.js` | **Auto-registers** every `component/*/index.vue` via `import.meta.glob`; component name equals the **folder** name (PascalCase, e.g. `BtnGroup`) |
|
|
36
|
+
| `src/component/` | Implementations; root class `Mvc` + name (see `.cursor/rules/component-hierarchy.mdc`) |
|
|
37
|
+
| `src/util/index.js` | Global helpers on `app.config.globalProperties` & `globalThis` (`$getLang`, `$fa`, `$copy`, `$deepClone`, …) |
|
|
38
|
+
| `src/directive/index.js` | Directives: `v-copy` (optional `.dblclick`), `v-focus` |
|
|
39
|
+
| `src/store/` | `createPinia` + built-in `init` / `tab` / `rmenu`; optional `storeChips`; `provide("store", store)` |
|
|
40
|
+
| `src/router/` | `createWebHistory` router; optional `guard`; built-in `guardThis` (`meta.admin`, `afterEach` + tabs, `document.title`) |
|
|
41
|
+
| `src/composition/` | **Import on demand**; exports `lang`, `dom`, `data`, `media`, … (Vite alias `@cps` → this folder) |
|
|
42
|
+
| `src/style/` | `index.scss` aggregates `chip/*.scss` (tokens, spacing, typography, layout, overrides) |
|
|
40
43
|
|
|
41
|
-
|
|
44
|
+
**Globally registered components** (folder name = registration name):
|
|
42
45
|
|
|
43
|
-
`BtnGroup
|
|
46
|
+
`BtnGroup`, `Form`, `Frame`, `Icon`, `Input`, `Page`, `Select`, `SelectV2`, `Table`, `Tabs`, `Textarea`
|
|
44
47
|
|
|
45
|
-
|
|
48
|
+
`chip/` subfolders hold internal pieces (e.g. `Frame/chip/Menu.vue`); they are **not** registered as root components.
|
|
46
49
|
|
|
47
|
-
### `demo/` —
|
|
50
|
+
### `demo/` — local preview app
|
|
48
51
|
|
|
49
|
-
|
|
52
|
+
With **`NODE_ENV=development`**, Vite **`root`** is **`./demo`** (see `vite.config.js`) to exercise Frame, routing, and components.
|
|
50
53
|
|
|
51
|
-
|
|
|
54
|
+
| File | Role |
|
|
52
55
|
|------|------|
|
|
53
|
-
| `demo/index.html` |
|
|
54
|
-
| `demo/main.js` |
|
|
55
|
-
| `demo/App.vue` |
|
|
56
|
-
| `demo/routes.js` |
|
|
57
|
-
| `demo/views/Overview/Home.vue` |
|
|
58
|
-
| `demo/views/Overview/Home/FormPanel.vue` | Form
|
|
59
|
-
| `demo/views/Overview/Home/IconPanel.vue
|
|
60
|
-
| `demo/auto-imports.d.ts` | `unplugin-auto-import`
|
|
56
|
+
| `demo/index.html` | HTML shell |
|
|
57
|
+
| `demo/main.js` | Boot: `ElementPlus` + `../src/index.js` + `../src/style/index.scss` + `routes` |
|
|
58
|
+
| `demo/App.vue` | **`Frame`** layout, `menu: { iconClass: 'imicon', routes }`, slots `logo` / `logomini` |
|
|
59
|
+
| `demo/routes.js` | Sample routes: `/` → `Overview/Home`, `/a` → `A/Home`; nested `children` for the sidebar |
|
|
60
|
+
| `demo/views/Overview/Home.vue` | **`Page`** + **`Tabs`** switching **`FormPanel`** / **`IconPanel`** |
|
|
61
|
+
| `demo/views/Overview/Home/FormPanel.vue` | Form demo |
|
|
62
|
+
| `demo/views/Overview/Home/IconPanel.vue`, `iconfontAntNames.js` | Icon demo & Ant icon name list |
|
|
63
|
+
| `demo/auto-imports.d.ts` | Types from `unplugin-auto-import` (Vue / vue-router) |
|
|
61
64
|
|
|
62
|
-
|
|
65
|
+
Local dev:
|
|
63
66
|
|
|
64
67
|
```bash
|
|
65
68
|
yarn install
|
|
66
69
|
yarn dev
|
|
67
70
|
```
|
|
68
71
|
|
|
69
|
-
|
|
72
|
+
Dev server port **8088** (see `vite.config.js`).
|
|
70
73
|
|
|
71
|
-
###
|
|
74
|
+
### Path aliases
|
|
72
75
|
|
|
73
|
-
|
|
|
74
|
-
|
|
76
|
+
| Alias | Points to |
|
|
77
|
+
|------|-----------|
|
|
75
78
|
| `@` | `src/` |
|
|
76
79
|
| `@cps` | `src/composition/` |
|
|
77
|
-
| `@scss` | `assets/scss
|
|
80
|
+
| `@scss` | `assets/scss` (if present) |
|
|
78
81
|
|
|
79
|
-
|
|
82
|
+
Demo routes use paths like `import("/views/Overview/Home.vue")` resolved from the **`demo`** root.
|
|
80
83
|
|
|
81
84
|
---
|
|
82
85
|
|
|
83
|
-
##
|
|
86
|
+
## Using in a host application
|
|
84
87
|
|
|
85
|
-
### 1.
|
|
88
|
+
### 1. Install peer-style deps
|
|
86
89
|
|
|
87
|
-
|
|
90
|
+
Align versions of **`vue`**, **`vue-router`**, **`pinia`**. For `Form` / `Table` tied to Element Plus, add **`element-plus`** and `app.use(ElementPlus)`.
|
|
88
91
|
|
|
89
|
-
### 2.
|
|
92
|
+
### 2. Register MVFrame
|
|
90
93
|
|
|
91
94
|
```js
|
|
92
95
|
import { createApp } from "vue";
|
|
93
96
|
import mvframe from "mvframe";
|
|
94
|
-
//
|
|
97
|
+
// Styles: use package path when depending on source / monorepo; published `dist`-only—see “Styles”
|
|
95
98
|
import "mvframe/src/style/index.scss";
|
|
96
99
|
|
|
97
100
|
const app = createApp(App);
|
|
@@ -99,18 +102,18 @@ const app = createApp(App);
|
|
|
99
102
|
app.use(mvframe, {
|
|
100
103
|
vueRouter: {
|
|
101
104
|
routes: yourRoutes,
|
|
102
|
-
//
|
|
105
|
+
// optional: custom beforeEach, etc.
|
|
103
106
|
// guard: (router) => { /* ... */ },
|
|
104
107
|
// useAdmin: true,
|
|
105
108
|
// adminPermission: () => true,
|
|
106
109
|
// noaccess: (next) => next(false),
|
|
107
110
|
},
|
|
108
111
|
pinia: {
|
|
109
|
-
useTab: true, //
|
|
112
|
+
useTab: true, // multi-tab + localStorage restore for `tabs` / `ctab`
|
|
110
113
|
// storeChips: import.meta.glob("./pinia/chip/*.js", { eager: true }),
|
|
111
114
|
},
|
|
112
115
|
config: {
|
|
113
|
-
//
|
|
116
|
+
// merged with src/config/chip/base.js → globalThis.$config
|
|
114
117
|
iconfont: {
|
|
115
118
|
url: "//at.alicdn.com/t/c/your_font.js",
|
|
116
119
|
prefix: "ant",
|
|
@@ -119,45 +122,86 @@ app.use(mvframe, {
|
|
|
119
122
|
});
|
|
120
123
|
```
|
|
121
124
|
|
|
122
|
-
**Frame**
|
|
125
|
+
**Frame** injects a `<script>` for icon fonts from `globalThis.$config.iconfont.url` on mount (implementation removes `url` afterward to avoid duplicate injection).
|
|
123
126
|
|
|
124
|
-
### 3.
|
|
127
|
+
### 3. Globals at a glance
|
|
125
128
|
|
|
126
|
-
- **`globalThis.$config
|
|
127
|
-
- **`globalThis.$router
|
|
128
|
-
- **`inject("store")
|
|
129
|
-
-
|
|
130
|
-
-
|
|
131
|
-
- **
|
|
129
|
+
- **`globalThis.$config`** — merged app config
|
|
130
|
+
- **`globalThis.$router`** — router instance assigned by this library after install
|
|
131
|
+
- **`inject("store")`** — store **factory** (`store.tab()`, `store.rmenu()`, custom chips)
|
|
132
|
+
- **Global components** — use `Frame`, `Page`, `Table`, … without local registration
|
|
133
|
+
- **Directives** — `v-copy`, `v-focus`
|
|
134
|
+
- **Composition** — `import { ... } from "mvframe/composition"` or your `@cps` alias
|
|
132
135
|
|
|
133
|
-
|
|
136
|
+
Full helper list: `.cursor/rules/util.mdc` and `src/util/index.js`.
|
|
134
137
|
|
|
135
|
-
### 4.
|
|
138
|
+
### 4. Styles
|
|
136
139
|
|
|
137
|
-
-
|
|
138
|
-
-
|
|
139
|
-
-
|
|
140
|
+
- Utility classes & tokens: `.cursor/rules/style-system.mdc` (`--color-*`, spacing, typography, layout).
|
|
141
|
+
- `vite.config.js` **`additionalData`** injects **`src/style/chip/mixin.scss`**; mirror this in apps that compile the same SCSS tree.
|
|
142
|
+
- Published packages can use **`import 'mvframe/style'`** (`dist/css/style.css`). For SCSS overrides, still link **`src/style/index.scss`** from Git/monorepo when needed.
|
|
140
143
|
|
|
141
144
|
---
|
|
142
145
|
|
|
143
|
-
##
|
|
146
|
+
## Building the library
|
|
144
147
|
|
|
145
148
|
```bash
|
|
146
149
|
yarn build
|
|
147
150
|
```
|
|
148
151
|
|
|
149
|
-
|
|
152
|
+
Production uses **library mode** with entry `src/index.js` and obfuscation-related plugins (see `vite.config.js`). **`NODE_ENV=development`** points Vite at the **demo** app; to verify a real build locally, run production **`vite build`** (or your script that sets production env).
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Design notes
|
|
157
|
+
|
|
158
|
+
- Layout, guards, tabs, and menu behavior are **opinionated**; heavy customization may mean forking `src/router`, `src/store/tab.js`, or wrapping from the app.
|
|
159
|
+
- **CSS naming & units**: root `Mvc*`, children camelCase; prefer **rem** for sizes other than 1px/2px (16px root)—see `style-system.mdc`.
|
|
160
|
+
- Use **`globalThis`** or **`store` / `pinia` exports** outside `setup` (e.g. guards), as in `src/router/chip/guard.js`.
|
|
150
161
|
|
|
151
162
|
---
|
|
152
163
|
|
|
153
|
-
##
|
|
164
|
+
## CLI: project skeleton
|
|
165
|
+
|
|
166
|
+
From an **empty folder or existing Vite root**, generates `src/views`, `src/component`, `src/api`, `src/assets/img`, `src/assets/style`, `src/router`, `src/pinia/chip`, `src/config`, plus starter `main.js` / `App.vue` with `app.use(mvframe, …)` (routes, Pinia `storeChips`, config). Adds `index.html` and `vite.config.js` only if missing (use `--force` to overwrite). **Merges** `dependencies` / `devDependencies` into `package.json` (existing versions win for shared keys); use `--no-package-json` to skip. Then run **`yarn install`**.
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
cd /path/to/your-app
|
|
170
|
+
node /path/to/mvframe/scripts/scaffold-app.js
|
|
171
|
+
node /path/to/mvframe/scripts/scaffold-app.js --force
|
|
172
|
+
|
|
173
|
+
# Skip package.json (only scaffold sources + Vite config):
|
|
174
|
+
node /path/to/mvframe/scripts/scaffold-app.js --no-package-json
|
|
175
|
+
|
|
176
|
+
yarn exec mvframe-init-app
|
|
177
|
+
# or: npx mvframe-init-app
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
See **`MVFRAME-SCAFFOLD.md`** in the target project. Set **`MVFRAME_SCAFFOLD_TARGET`** to point at the project root.
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## Cursor Skill (app scaffold)
|
|
185
|
+
|
|
186
|
+
This repo ships **`.cursor/skills/mvframe-app-init`**. Copy it into your app’s **`.cursor/skills`** so Cursor can pick up MVFrame integration conventions.
|
|
187
|
+
|
|
188
|
+
From **your app root**, run either:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
# Full checkout / monorepo path to mvframe
|
|
192
|
+
node /path/to/mvframe/scripts/install-cursor-skill.js
|
|
193
|
+
node /path/to/mvframe/scripts/install-cursor-skill.js /path/to/your-app
|
|
194
|
+
|
|
195
|
+
# After installing the npm package (the tarball must include `scripts/` and `.cursor/skills`—see `package.json` `files`)
|
|
196
|
+
cd /path/to/your-app
|
|
197
|
+
yarn exec mvframe-install-cursor-skill
|
|
198
|
+
# or: npx mvframe-install-cursor-skill
|
|
199
|
+
```
|
|
154
200
|
|
|
155
|
-
-
|
|
156
|
-
- **组件 class 与单位**:根节点 `Mvc*` + 子命名 camelCase;组件内尺寸除 1px/2px 外建议 **rem**(根号 16px),与 `style-system.mdc` 一致。
|
|
157
|
-
- 工具函数、Store、路由在非 setup 场景(如守卫)中通过 **`globalThis`** 或 **`store` / `pinia` 导出**访问,与 `src/router/chip/guard.js` 用法一致。
|
|
201
|
+
Default target is **`./.cursor/skills/mvframe-app-init`** under the current working directory. Override with **`MVFRAME_CURSOR_SKILL_OUT=/path/to/your-app`**.
|
|
158
202
|
|
|
159
203
|
---
|
|
160
204
|
|
|
161
|
-
##
|
|
205
|
+
## License
|
|
162
206
|
|
|
163
|
-
ISC
|
|
207
|
+
ISC (see `package.json`).
|