mvframe 1.0.20 → 1.0.58
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/rules/component-hierarchy.mdc +63 -0
- package/.cursor/rules/data.mdc +70 -0
- package/.cursor/rules/global-components.mdc +49 -0
- package/.cursor/rules/router.mdc +17 -0
- package/.cursor/rules/script-setup.mdc +33 -0
- package/.cursor/rules/style-system.mdc +219 -0
- package/.cursor/rules/util.mdc +60 -0
- package/.cursor/rules/views.mdc +69 -0
- package/.cursor/skills/mvframe-app-init/SKILL.md +1 -1
- package/README.cn.md +1 -1
- package/README.md +1 -1
- package/dist/Config.js +77 -160
- package/dist/composition.js +414 -244
- package/dist/css/cpt.css +1 -1
- package/dist/css/style.css +1 -1
- package/dist/index.js +1 -1
- package/dist/lodash.js +1 -1
- package/dist/maps.js +6 -5
- package/dist/store-shared.js +72 -58
- package/dist/util.js +67 -65
- package/dist/vendor.js +6274 -2232
- package/package.json +6 -2
- package/scripts/install-cursor-skill.js +0 -0
- package/scripts/scaffold-app.js +29 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: mvframe 组件层级与 class 命名规范
|
|
3
|
+
globs: src/component/**/*.{vue,scss}
|
|
4
|
+
alwaysApply: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 组件层级命名规范
|
|
8
|
+
|
|
9
|
+
组件的 class 命名需体现层级关系,便于维护与样式隔离。
|
|
10
|
+
|
|
11
|
+
## 根容器 class
|
|
12
|
+
|
|
13
|
+
- **`Mvc`**:全局注册组件的**统一标识前缀**(与 mvframe 全局组件体系对应)。
|
|
14
|
+
- **`Mvc{ComponentName}`**:根容器完整 class 为 `Mvc` + 组件名(PascalCase)。
|
|
15
|
+
|
|
16
|
+
`{ComponentName}` 与**文件名或文件夹名**一致:
|
|
17
|
+
|
|
18
|
+
- 文件为 `Xxx.vue`(非 index)→ 取 `Xxx`,如 `MvcXxx`
|
|
19
|
+
- 文件为 `index.vue` → 取外层**文件夹名**,如 `BtnGroup/index.vue` → `MvcBtnGroup`
|
|
20
|
+
|
|
21
|
+
## 内部 class
|
|
22
|
+
|
|
23
|
+
内部所有 class 名使用**小驼峰(camelCase)**书写,如 `btnItem`、`listWrap`、`optionItem`。
|
|
24
|
+
|
|
25
|
+
## 写法约定
|
|
26
|
+
|
|
27
|
+
- 根容器:`Mvc{ComponentName}`(`Mvc` 为全局组件标识 + 与文件/文件夹一致的组件名)
|
|
28
|
+
- 子元素:**仅**使用小驼峰语义名,**不**重复父级前缀;层级由 DOM 嵌套与 SCSS 嵌套体现
|
|
29
|
+
|
|
30
|
+
## 示例(BtnGroup/index.vue)
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
MvcBtnGroup ← 根:Mvc(全局组件标识)+ BtnGroup(文件夹名)
|
|
34
|
+
└─ btnItem ← 子级,小驼峰,不带父级前缀
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
模板:
|
|
38
|
+
```html
|
|
39
|
+
<div class="MvcBtnGroup">
|
|
40
|
+
<button class="btnItem">...</button>
|
|
41
|
+
</div>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
样式:
|
|
45
|
+
```scss
|
|
46
|
+
.MvcBtnGroup {
|
|
47
|
+
.btnItem { ... } /* 嵌套在根下,避免全局污染 */
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## 样式单位
|
|
52
|
+
|
|
53
|
+
`src/component` 内组件样式遵循 **`style-system.mdc`**:**除 1px、2px 外**,尺寸与字号使用 **`rem`**(root 16px,换算 `Npx → N/16 rem`)。
|
|
54
|
+
|
|
55
|
+
## 常见子元素后缀(camelCase)
|
|
56
|
+
|
|
57
|
+
| 后缀 | 用途 |
|
|
58
|
+
|------|------|
|
|
59
|
+
| `Item` | 列表/选项中的单项 |
|
|
60
|
+
| `List` | 列表容器 |
|
|
61
|
+
| `Header` / `Footer` | 头尾区域 |
|
|
62
|
+
| `Wrap` | 包裹层 |
|
|
63
|
+
| `Label` / `Content` | 文本/内容区 |
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: mvframe 数据处理与字典类数据抽离规范
|
|
3
|
+
globs: "**/*.{vue,js,ts}"
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 数据处理公共抽离
|
|
8
|
+
|
|
9
|
+
## 位置
|
|
10
|
+
|
|
11
|
+
数据处理相关的公共方法统一抽离到 `src/composition/chip/data.js`。
|
|
12
|
+
|
|
13
|
+
## 使用方式
|
|
14
|
+
|
|
15
|
+
- 使用路径别名:`import { deepEqual } from '@cps/chip/data.js'`(`@cps` → `src/composition`)
|
|
16
|
+
- 或从 composition 入口:`import { deepEqual } from '@cps'`
|
|
17
|
+
|
|
18
|
+
## 已有方法
|
|
19
|
+
|
|
20
|
+
| 方法 | 用途 |
|
|
21
|
+
|------|------|
|
|
22
|
+
| `deepEqual(a, b)` | 深度比较两个值是否相等,递归按 key 比较,不依赖 JSON.stringify 键序 |
|
|
23
|
+
|
|
24
|
+
## 扩展规则
|
|
25
|
+
|
|
26
|
+
- 新增数据处理工具(如 clone、merge、diff 等)时,优先放入 `data.js`
|
|
27
|
+
- 保持单一职责,每个方法只做一件事
|
|
28
|
+
- 补充 JSDoc 注释说明参数与返回值
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
# 字典类数据抽离(模块私有)
|
|
33
|
+
|
|
34
|
+
**字典类数据**:选项列表、枚举映射、配置表、多语言 key 表等以「键值 / 多行结构」为主的静态数据。
|
|
35
|
+
|
|
36
|
+
本节针对 **当前业务模块内的私有数据**,**不**放入 `src/composition`(`@cps`)。跨模块共享的通用逻辑与工具仍按上文「数据处理公共抽离」走 `composition`。
|
|
37
|
+
|
|
38
|
+
## 何时抽离(量化)
|
|
39
|
+
|
|
40
|
+
同时满足以下条件时**必须**抽离到独立文件,不得在页面或组件内长期堆叠:
|
|
41
|
+
|
|
42
|
+
1. **行数**:该段数据在单文件内占用 **超过 50 行**(以编辑器行数为准,含数组/对象字面量的多行)。
|
|
43
|
+
2. **复用**:在 **本模块内多处**(多页面、或同一页面拆分出的多个子组件)会重复使用(或明确预期会复用)。
|
|
44
|
+
|
|
45
|
+
仅超过 50 行、但暂时只有一处引用时,仍应抽离到独立文件,**不得**在 `.vue` 内大块硬编码;文件位置仍按下方「放置规则」。
|
|
46
|
+
|
|
47
|
+
## 放置规则(与模块内页面拆分一致)
|
|
48
|
+
|
|
49
|
+
与 `views.mdc` 中**页面同名文件夹**规则一致,不单独使用模块级 `chip/` 等其它目录存放此类私有字典。
|
|
50
|
+
|
|
51
|
+
1. **从属于某一页面**:在与该 `Xxx.vue` **同级**建立同名文件夹 `Xxx/`,将字典文件放入 `Xxx/` 内(与子组件 `.vue` 同级归类)。
|
|
52
|
+
2. **仅模块级、不挂靠单页**:若数据只服务模块根目录下的 `Home.vue`(或其它单一入口页),则放入该入口页对应的同名文件夹 `Home/`(或该页已有的拆分目录)内。
|
|
53
|
+
3. **拆分层级**:与页面拆分相同,**不得超过 4 级**(自第一层同名文件夹起算),详见 `views.mdc`。
|
|
54
|
+
|
|
55
|
+
示例(与页面拆分同夹):
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
views/
|
|
59
|
+
AdsManager/
|
|
60
|
+
CreateCampaign.vue
|
|
61
|
+
CreateCampaign/
|
|
62
|
+
Step1.vue
|
|
63
|
+
createCampaign.options.js ← 模块私有字典,与拆分组件同目录
|
|
64
|
+
regionMap.js
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## 命名与导出
|
|
68
|
+
|
|
69
|
+
- 文件命名体现用途:`xxxOptions.js`、`xxxMap.js`、`xxxDict.js` 等(可与页面名前缀一致便于检索)。
|
|
70
|
+
- 使用具名导出(`export const xxx = [...]`),由页面或子组件相对路径 `import`。
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: mvframe 全局组件(cpt)注册方式与使用总则:已封装能力须用全局组件
|
|
3
|
+
globs: src/**/*.vue,demo/**/*.vue
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 全局组件使用约定
|
|
8
|
+
|
|
9
|
+
## 总则
|
|
10
|
+
|
|
11
|
+
- 库内 **已通过全局注册封装**的 UI / 交互(见 `src/component/<Name>/index.vue` → `src/cpt/index.js`),在 **库内其它组件**与 **接入方应用**中 **必须优先使用对应全局组件**,在模板里直接写 **PascalCase 标签**(如 `<BtnGroup>`、`<Login>`),**无需 import**。
|
|
12
|
+
- **禁止**在业务或本库其它组件里,用裸写 DOM、`el-*` 组合或第三方组件 **重复实现** 与现有全局组件 **同类** 的样式与行为(除非全局组件 API 实在无法满足,再评估扩展该组件本身)。
|
|
13
|
+
- **布局 / 间距 / 字号 / 弹性对齐**等:优先使用 **`src/style`** 生成的工具类(见 **`style-system.mdc`**);组件内 **`scoped` 仅保留**无工具类覆盖的个案(如品牌色、特定阴影、`:deep` 覆盖子组件)。
|
|
14
|
+
|
|
15
|
+
## 注册与命名
|
|
16
|
+
|
|
17
|
+
- 注册名与 **`src/component` 下文件夹名** 一致(PascalCase),例如 `BtnGroup/index.vue` → `<BtnGroup>`。
|
|
18
|
+
- 根节点展示类名遵循 **`component-hierarchy.mdc`**:`Mvc` + 文件夹名(如 `MvcBtnGroup`)。
|
|
19
|
+
|
|
20
|
+
## 当前全局组件一览(随 `src/component` 目录演进)
|
|
21
|
+
|
|
22
|
+
| 组件 | 典型用途 |
|
|
23
|
+
|------|----------|
|
|
24
|
+
| `BtnGroup` | 分段切换、互斥单选的一排按钮 |
|
|
25
|
+
| `Drawer` / `DrawerArea` | 抽屉容器与区域 |
|
|
26
|
+
| `Form` | 表单封装 |
|
|
27
|
+
| `Frame` | 框架布局(菜单、页头、Tab 等) |
|
|
28
|
+
| `Icon` | 图标字体 |
|
|
29
|
+
| `Lang` | 语言下拉(与 `app.use(mvframe, { lang: { use: [...] } })` 对齐,见 `locale/langUseDefaults.js`) |
|
|
30
|
+
| `Input` / `Textarea` | 输入封装 |
|
|
31
|
+
| `Loading` | 局部/容器内全屏遮罩加载(`position: absolute` 铺满**最近一层 `position: relative` 祖先**,见 `Table` / `Drawer`) |
|
|
32
|
+
| `Login` | 登录页(表单项用 **`Form`** + **`Input`**,勿裸用 `el-form` / `el-input` 拼账号密码区) |
|
|
33
|
+
| `Page` | 页面布局块 |
|
|
34
|
+
| `Select` / `SelectV2` | 选择器 |
|
|
35
|
+
| `Table` | 表格 |
|
|
36
|
+
| `Tabs` | 标签页 |
|
|
37
|
+
|
|
38
|
+
新增目录下的 `index.vue` 会由 glob 自动注册;实现新页面或拆组件前,**先查上表与 `src/component`**,能复用则不复造。
|
|
39
|
+
|
|
40
|
+
## BtnGroup(分段 / 互斥单选按钮组)
|
|
41
|
+
|
|
42
|
+
若需要 **多段切换、互斥单选一项目** 的一组按钮(如登录方式、Tab 式筛选、小型 segmented control),**必须**使用 **`BtnGroup`**:
|
|
43
|
+
|
|
44
|
+
- **`v-model`** 绑定当前值,**`options`** 为 `{ value, label }`(或通过 **`valueKey` / `labelKey`** 对齐字段)。
|
|
45
|
+
- **不要**手写循环 `<button>` / `el-button` 组模仿同一套交互与层次。
|
|
46
|
+
- 整组禁用:**`disabled`**;疏密:**`size`** → `small` | `default` | `large`。
|
|
47
|
+
- 选项多需换行:给 **`BtnGroup`** 增加工具类 **`flexWrap`**,或外层 `:deep(.MvcBtnGroup) { flex-wrap: wrap }`(见 `Login` 等用法)。
|
|
48
|
+
|
|
49
|
+
参考:`src/component/BtnGroup/index.vue`。
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: mvframe 路由与导航规范
|
|
3
|
+
globs: src/**/*.{vue,js}
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 路由与导航
|
|
8
|
+
|
|
9
|
+
## 跳转方式
|
|
10
|
+
|
|
11
|
+
- **优先使用 `name`**:`router.push({ name: routeName })`、`router.replace({ name: routeName })`
|
|
12
|
+
- **避免使用 `path`**:除非动态路由或 name 不可用,否则不使用 `path` 跳转
|
|
13
|
+
|
|
14
|
+
## 原因
|
|
15
|
+
|
|
16
|
+
- `name` 与路由配置解耦,路径变更不影响跳转
|
|
17
|
+
- `name` 便于维护与重构
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: mvframe Vue SFC 块顺序与 `<script setup>` 分区注释、固定书写顺序
|
|
3
|
+
globs: src/**/*.vue,demo/**/*.vue
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 单文件组件(SFC)块顺序
|
|
8
|
+
|
|
9
|
+
`.vue` 顶层块**固定顺序**为:
|
|
10
|
+
|
|
11
|
+
1. **`<template>`** — 优先阅读结构,再放逻辑
|
|
12
|
+
2. **`<script setup>`**(或 `<script>`)
|
|
13
|
+
3. **`<style>`** — 可选;有则置于最后
|
|
14
|
+
|
|
15
|
+
无模板、仅做 re-export 等**极少数**特例可只保留 `<script>`;**页面与常规组件**不得把 `<script>` 写在 `<template>` 之上。
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# 组件 script setup 结构(固定顺序)
|
|
20
|
+
|
|
21
|
+
`<script setup>` 内必须按以下注释分区书写,且顺序不可打乱:
|
|
22
|
+
|
|
23
|
+
1. **// 定义** — `defineOptions`
|
|
24
|
+
2. **// 传参** — `defineProps`
|
|
25
|
+
3. **// 数据** — `reactive`、`ref`、`getCurrentInstance` 等状态与实例;`const { proxy } = getCurrentInstance();` 等实例相关获取须写在此分区
|
|
26
|
+
4. **// 挂载** — `onBeforeMount`、`onMounted` 等生命周期
|
|
27
|
+
5. **// 事件** — **`defineEmits`(含 `const emit = defineEmits(...)`)须紧接本注释之后**;其下为事件处理与业务方法(如 initParams、toSubmit 等)
|
|
28
|
+
6. **// 计算** — `computed`
|
|
29
|
+
7. **// 监听** — `watch`、`watchEffect`
|
|
30
|
+
8. **// 卸载** — `onUnmounted`、`defineExpose` 等;**`defineExpose` 一律写在此分区下方,不可放在其他分区**
|
|
31
|
+
9. **// Map** — 常量、配置(如 typeOptions、matchTypeOptions)
|
|
32
|
+
|
|
33
|
+
新增或修改代码时,将对应逻辑放入对应分区;例如 `watch` 必须写在 `// 监听` 下方,不要放在挂载或事件区;`defineEmits` 不得放在 `// 传参`,须写在 `// 事件` 第一组语句。
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: mvframe 项目 src/style 样式系统规范
|
|
3
|
+
globs: src/**/*.{vue,scss,css}
|
|
4
|
+
alwaysApply: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# mvframe 样式系统
|
|
8
|
+
|
|
9
|
+
## 关于 frontmatter 里的 `alwaysApply`
|
|
10
|
+
|
|
11
|
+
- **`alwaysApply: true` 只作用于 Cursor**:把本文件当作对话上下文里的规范读给 AI,**不会**在构建时自动给任何 `.vue` 挂上样式,也**不等于**工具类已生效。
|
|
12
|
+
- **运行时要用工具类**,必须在应用入口(如 demo `main.js`、宿主项目)**已 `import` `mvframe` 的 `src/style/index.scss`(或包导出的 `style`)**;然后在组件 **template 里写上工具类名**(如 `flexMode`、`g16`、`fs14`),尽量少写与工具类等价的 scoped 声明。
|
|
13
|
+
|
|
14
|
+
样式入口为 `src/style/index.scss`,按模块拆分为 `chip/*.scss`。
|
|
15
|
+
|
|
16
|
+
## 1. 变量与颜色(var.scss)
|
|
17
|
+
|
|
18
|
+
### :root 变量
|
|
19
|
+
|
|
20
|
+
| 变量 | 用途 |
|
|
21
|
+
|------|------|
|
|
22
|
+
| `--color-txt-h1` ~ `--color-txt-tip` | 文本层级色(#111→#999) |
|
|
23
|
+
| `--color-primary` / `--color-green` 等 | 主题色、状态色 |
|
|
24
|
+
| `--color-bg-body` / `--color-bg-menu*` | 背景色 |
|
|
25
|
+
| `--border-d` | 默认边框 `1px solid` |
|
|
26
|
+
| `--trans` / `--trans-all` | 过渡:`--trans` 为 `100ms ease-in`;`--trans-all` 为 `all var(--trans)` |
|
|
27
|
+
|
|
28
|
+
### 文本与背景工具类
|
|
29
|
+
|
|
30
|
+
- `txt-h1` / `txt-h2` / `txt-p` / `txt-tip` / `txt-gray`:文本色
|
|
31
|
+
- `txt-{color}` / `bg-{color}`:`primary`, `green`, `orange`, `red`, `purple`, `pink`, `yellow`, `white`, `body`, `dark`(见 `var.scss` 中 `$colorNames`)
|
|
32
|
+
- `bg-page-header`:读 `--color-bg-page-header`,与页头/卡片面一致(无 glow)
|
|
33
|
+
- `trans-all`:应用 `--trans-all` 过渡
|
|
34
|
+
|
|
35
|
+
### 边框工具类(`var.scss` 工具类段)
|
|
36
|
+
|
|
37
|
+
- `border`:四边 `var(--border-d)`
|
|
38
|
+
- `border-l` / `border-r` / `border-t` / `border-b`:单边
|
|
39
|
+
- `border-none`:清除边框(`!important`)
|
|
40
|
+
|
|
41
|
+
### 过渡规则
|
|
42
|
+
|
|
43
|
+
- **单个 CSS 属性**:使用 `transition: <属性> var(--trans)`,如 `transition: opacity var(--trans)`
|
|
44
|
+
- **多个 CSS 属性**:使用 `transition: var(--trans-all)`
|
|
45
|
+
|
|
46
|
+
### 单位规范
|
|
47
|
+
|
|
48
|
+
- **1px、2px**:使用 `px`
|
|
49
|
+
- **其余尺寸**:使用 `rem`
|
|
50
|
+
- **root 字号**:16px(`1rem = 16px`)
|
|
51
|
+
- **换算**:`Npx → N/16rem`,如 `8px → 0.5rem`、`24px → 1.5rem`
|
|
52
|
+
|
|
53
|
+
## 2. 内外边距与尺寸(distance.scss)
|
|
54
|
+
|
|
55
|
+
### 间距 $pm: 0, 2, 4, 6, 8, 10, 12, 16, 20, 24, 30, 32, 36, 40, 48
|
|
56
|
+
|
|
57
|
+
| 类名 | 用途 |
|
|
58
|
+
|------|------|
|
|
59
|
+
| `pt{N}` / `pr{N}` / `pb{N}` / `pl{N}` | padding 单边(逻辑属性) |
|
|
60
|
+
| `mt{N}` / `mr{N}` / `mb{N}` / `ml{N}` | margin 单边 |
|
|
61
|
+
| `p{N}` / `m{N}` | 四边相同 |
|
|
62
|
+
| `p{N}-{M}` / `m{N}-{M}` | 上下=N,左右=M |
|
|
63
|
+
| `p0` / `pt0` 等 | 带 `!important` 的零值 |
|
|
64
|
+
|
|
65
|
+
### margin / padding 与奇数 px
|
|
66
|
+
|
|
67
|
+
- **禁止**在样式(含 scoped、`@apply`、内联 style)中为 **`margin` / `padding`** 使用 **奇数 px**(如 `3px`、`5px`、`7px`、`9px`、`11px`…),以免与栅格、子像素对齐和工具类刻度不一致。
|
|
68
|
+
- **例外**:`1px`、`2px` 仅用于边框、分割线、hairline 等,**不**作为常规留白;常规留白用本节 **`pt{N}` / `m{N}`** 等工具类或 **`rem`**,且数值应对齐 **`$pm`**(均为 **0 或偶数 px** 档位)。
|
|
69
|
+
- 新增或修改 `distance.scss` 中的间距档位时,**不得**加入奇数 px。
|
|
70
|
+
|
|
71
|
+
### 尺寸 $dis: 16~800
|
|
72
|
+
|
|
73
|
+
| 类名 | 用途 |
|
|
74
|
+
|------|------|
|
|
75
|
+
| `w{N}` / `h{N}` | 固定宽高 px |
|
|
76
|
+
| `minw{N}` / `maxw{N}` / `minh{N}` / `maxh{N}` | 最小/最大宽高 |
|
|
77
|
+
| `minw0` / `minh0` | `min-width` / `min-height: 0`,flex/grid 子项防溢出 |
|
|
78
|
+
| `w1` | 1×1px 占位,flex-shrink: 0 |
|
|
79
|
+
| `grid-minw{N}` | `grid-template-columns: repeat(auto-fill, minmax(Npx→rem, 1fr))` |
|
|
80
|
+
|
|
81
|
+
### 百分比与视口
|
|
82
|
+
|
|
83
|
+
| 类名 | 用途 |
|
|
84
|
+
|------|------|
|
|
85
|
+
| `wp{N}` / `hp{N}` | N=10~100 的百分比宽高 |
|
|
86
|
+
| `wp25` / `wp30` / `wp50` / `wp75` / `wp100` | 常用百分比 |
|
|
87
|
+
| `vh50`~`vh100` | 视口高度 |
|
|
88
|
+
| `vw90` | 视口宽度 |
|
|
89
|
+
| `hauto` | height: auto |
|
|
90
|
+
|
|
91
|
+
## 3. 字体与文本(font.scss)
|
|
92
|
+
|
|
93
|
+
### 字体大小 $font: 10~96
|
|
94
|
+
|
|
95
|
+
- `fs{N}`:font-size Npx
|
|
96
|
+
|
|
97
|
+
### 字间距与行高
|
|
98
|
+
|
|
99
|
+
- `space{N}`:letter-spacing,N=1~5
|
|
100
|
+
- `lh{N}`:line-height,N=14~48(步长 2)
|
|
101
|
+
|
|
102
|
+
### 文本截断与换行
|
|
103
|
+
|
|
104
|
+
| 类名 | 用途 |
|
|
105
|
+
|------|------|
|
|
106
|
+
| `txt-nowrap` | 单行省略 |
|
|
107
|
+
| `txt-nowrap{N}` | 多行截断,N=1~10 |
|
|
108
|
+
| `txt-line{N}` | 多行截断,N=2~9 |
|
|
109
|
+
| `txt-wrap` / `txt-prewrap` | 自动换行 |
|
|
110
|
+
|
|
111
|
+
### 字重与其它
|
|
112
|
+
|
|
113
|
+
- `fw300` / `fw500` / `fw700`:lighter / normal / bold
|
|
114
|
+
- `block` / `indent2`:display block / text-indent 2rem
|
|
115
|
+
- `cursor-disabled`:cursor not-allowed
|
|
116
|
+
- `opacity{N}`:N=2~9,opacity 0.2~0.9
|
|
117
|
+
|
|
118
|
+
### 渐变色字体 .colorfulFont
|
|
119
|
+
|
|
120
|
+
需配合 `background-clip: text`,支持 `.primary` / `.orange` / `.blue` / `.green` / `.red` / `.purple`(依赖 `--mg-*` 变量时需确保已引入)。
|
|
121
|
+
|
|
122
|
+
## 4. 布局(layout.scss)
|
|
123
|
+
|
|
124
|
+
### 定位
|
|
125
|
+
|
|
126
|
+
| 类名 | 用途 |
|
|
127
|
+
|------|------|
|
|
128
|
+
| `relative` / `fixed` / `abs` | position |
|
|
129
|
+
| `t` / `l` / `r` / `b` | top/left/right/bottom: 0 |
|
|
130
|
+
| `absCenter` | 绝对居中 |
|
|
131
|
+
| `absFull` | 铺满四边 |
|
|
132
|
+
| `sticky` | position sticky, top: 0 |
|
|
133
|
+
| `z0` / `z1` / `z2` / `z9` | z-index |
|
|
134
|
+
|
|
135
|
+
### Flex
|
|
136
|
+
|
|
137
|
+
| 类名 | 用途 |
|
|
138
|
+
|------|------|
|
|
139
|
+
| `flexMode` | display flex;`.inline` → inline-flex |
|
|
140
|
+
| `flex1` / `flexGrow` / `noShrink` | flex 相关 |
|
|
141
|
+
| `flexV` / `flexV-1` | column / column-reverse |
|
|
142
|
+
| `flexWrap` / `flexWrap-1` | wrap / wrap-reverse |
|
|
143
|
+
| `hl` / `hc` / `hr` / `hb` / `ha` | 主轴 `justify-content`(`hl` = flex-start) |
|
|
144
|
+
| `vl` / `vc` / `vr` / `vs` | 交叉轴 `align-items`(`vl` = flex-start;CSS 初始为 stretch,需顶对齐时用 `vl`) |
|
|
145
|
+
| `acl` / `acc` / `acr` / `acb` / `aca` / `acs` | 多行时 `align-content`(`acl` = flex-start;CSS 初始为 stretch,与 `flexWrap` 同用) |
|
|
146
|
+
|
|
147
|
+
### Grid(`layout.scss`)
|
|
148
|
+
|
|
149
|
+
| 类名 | 用途 |
|
|
150
|
+
|------|------|
|
|
151
|
+
| `grid` | `display: grid` |
|
|
152
|
+
| `grid col{N}` / `grid row{N}`(N=1~12) | 组合在**同一元素**上:`grid-template-columns` / `rows` 为 `repeat(N, 1fr)` |
|
|
153
|
+
| `col{N}` / `row{N}`(单独使用) | `grid-column` / `grid-row`:跨 N 列/行 |
|
|
154
|
+
|
|
155
|
+
**注意**:同一元素上同时有 `grid` 与 `col7` 时,除 `.grid.col7` 外还会命中单独的 `.col7 { grid-column: span 7 }`(`layout.scss` 第二段 `@for`)。需要「7 列等宽、自身作为 grid 容器」时,优先 `:style` 写 `gridTemplateColumns: repeat(7, minmax(0, 1fr))`,避免再叠 `col7` 类。
|
|
156
|
+
|
|
157
|
+
行高、首行 `auto` 等需写在 **scoped** 或 **`:style`**,与工具类叠加即可。
|
|
158
|
+
|
|
159
|
+
### 其它
|
|
160
|
+
|
|
161
|
+
- `clear` / `txt-c` / `txt-r`:clear、text-align
|
|
162
|
+
- `fadeout`:水平渐变遮罩;`.v` 为垂直
|
|
163
|
+
- `fadeout-h16`:配合 fadeout 的 margin/padding
|
|
164
|
+
- `g{N}`:gap,N=2~40(步长 2)
|
|
165
|
+
- `mauto`:margin-inline auto
|
|
166
|
+
|
|
167
|
+
## 5. 其它样式(other.scss / static.scss)
|
|
168
|
+
|
|
169
|
+
### 全局重置与基础
|
|
170
|
+
|
|
171
|
+
- `*`:box-sizing border-box
|
|
172
|
+
- `body`:margin 0,背景 `--color-bg-body`
|
|
173
|
+
- `button`:outline none
|
|
174
|
+
|
|
175
|
+
### 图标字体
|
|
176
|
+
|
|
177
|
+
- `imicon`:mvframe 图标字体,16px
|
|
178
|
+
|
|
179
|
+
### 交互与显示
|
|
180
|
+
|
|
181
|
+
| 类名 | 用途 |
|
|
182
|
+
|------|------|
|
|
183
|
+
| `point` | cursor pointer |
|
|
184
|
+
| `opacity0` | opacity 0 |
|
|
185
|
+
| `yscroll` / `xscroll` | 纵向/横向滚动 |
|
|
186
|
+
| `noscroll` / `nobar` | 滚动锚点 / 隐藏滚动条 |
|
|
187
|
+
| `noselect` / `noevent` | 不可选 / 不响应事件 |
|
|
188
|
+
| `notrans` | transition none |
|
|
189
|
+
| `bg-none` / `hide` | 透明背景 / display none |
|
|
190
|
+
|
|
191
|
+
### 静态效果(`static.scss`)
|
|
192
|
+
|
|
193
|
+
| 类名 | 用途 |
|
|
194
|
+
|------|------|
|
|
195
|
+
| `backdrop` | `backdrop-filter: blur(8px)`,常配合半透明底栏 |
|
|
196
|
+
|
|
197
|
+
### 圆角
|
|
198
|
+
|
|
199
|
+
- `radius{N}`:border-radius,N=0~16
|
|
200
|
+
- `radius`:overflow hidden
|
|
201
|
+
- `radiusP50`:50% 圆形
|
|
202
|
+
|
|
203
|
+
### 悬停
|
|
204
|
+
|
|
205
|
+
- `hover`:hover 时 opacity 0.6 + 过渡
|
|
206
|
+
|
|
207
|
+
## 6. 动画(ani.scss)
|
|
208
|
+
|
|
209
|
+
| 类名 | 用途 |
|
|
210
|
+
|------|------|
|
|
211
|
+
| `rotateZ90` / `rotateZ180` | transform rotate |
|
|
212
|
+
| `ani-rotate` | 无限旋转动画 |
|
|
213
|
+
| `trans-all` | 过渡(在 var.scss) |
|
|
214
|
+
|
|
215
|
+
## 使用建议
|
|
216
|
+
|
|
217
|
+
- 优先使用工具类组合,避免重复写内联样式
|
|
218
|
+
- 新增样式时优先扩展 chip 内对应模块,保持命名一致
|
|
219
|
+
- 颜色类与 `--color-*` 变量对应,主题切换时统一生效
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: mvframe 项目 src/util 全局工具方法
|
|
3
|
+
globs: src/**/*.{vue,js,ts}
|
|
4
|
+
alwaysApply: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Util 全局工具方法
|
|
8
|
+
|
|
9
|
+
`src/util/index.js` 内的方法会在应用初始化时挂载为**全局方法**,可在项目内任何处直接使用(模板、组件、composition、script 等),无需 import。
|
|
10
|
+
|
|
11
|
+
## 调用方式
|
|
12
|
+
|
|
13
|
+
- 组件内:`proxy.$xxx()` 或 `globalThis.$xxx()`
|
|
14
|
+
- 模板:`$xxx()`(需通过 Vue 的 globalProperties 挂载)
|
|
15
|
+
- 普通 js:`globalThis.$xxx()` 或 `window.$xxx()`
|
|
16
|
+
|
|
17
|
+
## 方法一览
|
|
18
|
+
|
|
19
|
+
| 方法 | 用途 |
|
|
20
|
+
|------|------|
|
|
21
|
+
| `$getImg(url)` | 获取图片 URL,支持相对路径和 `/` 开头绝对路径 |
|
|
22
|
+
| `$getLang()` | 获取当前语言 |
|
|
23
|
+
| `$d` | **dayjs**:`globalThis.$d` 与默认导出一致;`$d()`、`$d(ts)`、`$d().format(...)`、`$d().add(n, 'day')` 等,勿在业务中重复 `import dayjs`(插件仅在应用入口统一 `extend`) |
|
|
24
|
+
| `$md5(v)` | 提取数字并拼接(简易 md5) |
|
|
25
|
+
| `$rn(v, min)` | 随机整数,v 为最大值,min 为最小值 |
|
|
26
|
+
| `$fd(total, cb)` | 假数据数组,cb(i) 生成第 i 项 |
|
|
27
|
+
| `$toUpperCamel(v, behindLowerCase)` | 首字母大写 |
|
|
28
|
+
| `$fa(v, fixed)` | 金额格式化,fixed 小数位 |
|
|
29
|
+
| `$fu({ prop, currency, value, obj })` | 按 metric 单位格式化值;`obj[prop]` 缺省时与 Table 汇总相同,回退 `$config.table.summaryMetric` |
|
|
30
|
+
| `$pm(cb, time)` | 延迟执行 Promise:`time` 为 ×100ms(默认 `2`→200ms),`cb` 可同步或返回 Promise;返回值作为 resolve 结果,`undefined` 时为 `true` |
|
|
31
|
+
| `$db(cb, time)` | 防抖 |
|
|
32
|
+
| `$getType(v)` | 获取变量类型(Object/Array/String 等) |
|
|
33
|
+
| `$copy(v, showV)` | 复制到剪切板 |
|
|
34
|
+
| `$sc(v)` | 计数简写(k/m) |
|
|
35
|
+
| `$nr(row, objMap)` | need rebuild key |
|
|
36
|
+
| `$nro(obj, nameMap)` | nameRebuildObj |
|
|
37
|
+
| `$pc(v)` | 参数数量计算器 |
|
|
38
|
+
| `$c.info` / `$c.log` / `$c.warn` / `$c.error` / `$c.success` | 控制台样式输出 |
|
|
39
|
+
| `$deepClone(dt)` | 深拷贝(挂载于 window) |
|
|
40
|
+
|
|
41
|
+
## 原生扩展
|
|
42
|
+
|
|
43
|
+
- `Number.prototype.toFixedNumber(v)`:保留精度并转 Number
|
|
44
|
+
- `Array.prototype.filter1(cb)`:筛选 1 个元素,返回 `{ index, data }`
|
|
45
|
+
|
|
46
|
+
## 使用建议
|
|
47
|
+
|
|
48
|
+
- 直接调用全局方法即可,无需在业务代码中 import util
|
|
49
|
+
- 新增工具方法时,应挂载到 `globalThis` 并补充到本 rules
|
|
50
|
+
|
|
51
|
+
## 全局封装方法的注释规范
|
|
52
|
+
|
|
53
|
+
**仅针对**在 **`src/util/index.js`** 中注册到 **`globalThis` / `Vue.globalProperties`** 的方法:在**导出函数声明紧上方**必须写 JSDoc,且对**主要使用场景**各给一条 **`@example`**(示例需可运行、参数贴近真实调用)。
|
|
54
|
+
|
|
55
|
+
- 多分支 API:**每种典型分支至少一条** `@example`,可用 `@example <caption>说明</caption>`。
|
|
56
|
+
- 文件顶层模块说明可简短,避免与 `@example` 重复堆砌。
|
|
57
|
+
|
|
58
|
+
`src/composition`(`@cps`)**默认不挂全局**,按需 `import`;若某实现复用到 `util` 并注册为 `$xxx`,注释规范同上,且可在 util 内薄封装转调 cps。
|
|
59
|
+
|
|
60
|
+
参考注释粒度:`src/composition/chip/media.js` 的 `download`(cps 内示例写法;真正注册为 `$download` 时应在 util 对应导出上保留或对齐示例)。
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: mvframe 应用层 views 目录与页面组织规范
|
|
3
|
+
globs: "**/views/**/*.{vue,js,ts}"
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# views 应用层组件
|
|
8
|
+
|
|
9
|
+
`views` 下的 Vue 文件表示**应用层**页面与模块,与库内 `src/component` 全局组件区分。
|
|
10
|
+
|
|
11
|
+
**SFC 块顺序**(`<template>` → `<script>` → `<style>`)与 `<script setup>` 内分区顺序见 **`script-setup.mdc`**。
|
|
12
|
+
|
|
13
|
+
## 模块目录(大驼峰)
|
|
14
|
+
|
|
15
|
+
- `views` 下**一级文件夹**使用**大驼峰(PascalCase)**,名称为**模块名**。
|
|
16
|
+
- 每个模块目录内**必须包含 `Home.vue`**:当该模块**没有子级模块路由**时,作为该模块的**默认入口页**。
|
|
17
|
+
|
|
18
|
+
示例:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
views/
|
|
22
|
+
Overview/
|
|
23
|
+
Home.vue ← 模块默认页
|
|
24
|
+
AdsManager/
|
|
25
|
+
Home.vue
|
|
26
|
+
CampaignList.vue
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## 页面拆分与同名校验夹
|
|
30
|
+
|
|
31
|
+
- 若某个 `.vue` 页面需要拆出子组件,在与该文件**同级**新建**与文件名相同**的文件夹(不含 `.vue` 后缀),将拆分出的组件放入其中,便于按页面归类查找。
|
|
32
|
+
- 例:`CreateCampaign.vue` 与 `CreateCampaign/` 同级,`CreateCampaign/` 内存放 `Step1.vue`、`Invoice.vue` 等。
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
views/
|
|
36
|
+
AdsManager/
|
|
37
|
+
CreateCampaign.vue
|
|
38
|
+
CreateCampaign/
|
|
39
|
+
Step1.vue
|
|
40
|
+
Invoice.vue
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 拆离子组件命名(defineOptions `name`)
|
|
44
|
+
|
|
45
|
+
从某模块页面拆入**同名文件夹**内的子组件,**`defineOptions({ name: '...' })`** 使用**一段拼接的 PascalCase**,由三部分顺序组成:
|
|
46
|
+
|
|
47
|
+
1. **模块文件夹名**:该页在 `views` 下所属**一级目录**名(如 `Overview`、`AdsManager`)。
|
|
48
|
+
2. **模块文件名**:该页面对应的 `.vue` 文件名**去掉后缀**(如 `Home`、`CreateCampaign`)。
|
|
49
|
+
3. **抽离语义名**:本次拆出的职责/区块简称(如 `FormPanel`、`Step1`、`Invoice`)。
|
|
50
|
+
|
|
51
|
+
即:`{模块文件夹}{页面文件名}{抽离名}`。
|
|
52
|
+
|
|
53
|
+
示例:
|
|
54
|
+
|
|
55
|
+
| 页面路径 | 拆出文件(示意) | `name` |
|
|
56
|
+
|----|----|-----|
|
|
57
|
+
| `views/Overview/Home.vue` | `Home/FormPanel.vue` | `OverviewHomeFormPanel` |
|
|
58
|
+
| `views/AdsManager/CreateCampaign.vue` | `CreateCampaign/Step1.vue` | `AdsManagerCreateCampaignStep1` |
|
|
59
|
+
|
|
60
|
+
- 根节点展示用 `class` 建议与上述 `name` **一致**,便于 DevTools 与样式范围对齐(与库内 `Mvc*` 全局组件区分)。
|
|
61
|
+
|
|
62
|
+
## 拆分层级上限
|
|
63
|
+
|
|
64
|
+
- 按上述方式继续拆分时,**拆分形成的目录层级不得超过 4 级**(自该页面对应的**第一层同名文件夹**起算,向下每多一层子目录计一级;达到 4 级后不应再向下套同名拆分夹)。
|
|
65
|
+
- 避免过深的 `A/A/A/...` 结构,优先在同级文件夹内平铺多个拆分文件。
|
|
66
|
+
|
|
67
|
+
## 与路由
|
|
68
|
+
|
|
69
|
+
- 路由 `name`、`path` 与模块、页面文件的对应关系由项目路由配置约定;跳转优先使用路由 `name`(见 `router.mdc`)。
|
|
@@ -94,7 +94,7 @@ app.use(mvframe, {
|
|
|
94
94
|
|
|
95
95
|
## 安装到业务工程
|
|
96
96
|
|
|
97
|
-
- **目录雏形(推荐)**:`yarn exec mvframe-init-app` 或 `node <mvframe>/scripts/scaffold-app.js`,生成 `src/views`、`router`、`pinia/chip`、`config` 等并写好 `main.js` + `App.use(mvframe)
|
|
97
|
+
- **目录雏形(推荐)**:`yarn exec mvframe-init-app` 或 `node <mvframe>/scripts/scaffold-app.js`,生成 `src/views`、`router`、`pinia/chip`、`config` 等并写好 `main.js` + `App.use(mvframe)`,同时将包内 **`.cursor/rules/*.mdc`** 复制到目标项目(与仓库规范一致);说明见目标项目根 `MVFRAME-SCAFFOLD.md`。
|
|
98
98
|
- **仅 Cursor Skill**:`yarn exec mvframe-install-cursor-skill` 或 `node <mvframe>/scripts/install-cursor-skill.js`(`MVFRAME_CURSOR_SKILL_OUT` 可选)。
|
|
99
99
|
|
|
100
100
|
详见仓库 `README.md` / `README.cn.md`。
|
package/README.cn.md
CHANGED
|
@@ -163,7 +163,7 @@ yarn build
|
|
|
163
163
|
|
|
164
164
|
## 命令行:项目目录雏形(推荐)
|
|
165
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
|
|
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),并复制 **`/.cursor/rules/*.mdc`**(与 mvframe 仓库内 Cursor 规则一致)。若不存在则附带 `index.html` 与 `vite.config.js`。会**合并** `package.json` 的 `dependencies` / `devDependencies`(与 Vite 模板一致;**同名包保留你原有版本**),最后请执行 **`yarn install`**;加 `--no-package-json` 可不改动 `package.json`。
|
|
167
167
|
|
|
168
168
|
```bash
|
|
169
169
|
cd /path/to/your-app
|
package/README.md
CHANGED
|
@@ -163,7 +163,7 @@ Production uses **library mode** with entry `src/index.js` and obfuscation-relat
|
|
|
163
163
|
|
|
164
164
|
## CLI: project skeleton
|
|
165
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`**.
|
|
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), and copies **`/.cursor/rules/*.mdc`** from the package (same as this repo’s Cursor rules). 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
167
|
|
|
168
168
|
```bash
|
|
169
169
|
cd /path/to/your-app
|