mvframe
v1.0.11
Published
**English** | [简体中文](README.cn.md)
Readme
MVFrame
English | 简体中文
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.
Stack & dependencies
| Kind | Notes |
|------|------|
| Runtime | vue ^3.3, vue-router ^4.6, pinia ^3 |
| Demo / dev | element-plus (demo forms, etc.), vite ^6, sass-embedded |
| Build | Library output is ESM; vue / pinia / vue-router are externals and must be supplied by the host app |
package.json exports include:
"."→dist/index.js(main plugin; default export is theinstallfunction)"./composition"→dist/composition.js(e.g.import { useMap } from 'mvframe/composition')"./store","./directive","./util"→ matching chunks underdist"./style"→dist/css/style.css(full toolkit CSS fromsrc/style/index.scssentry)"./style/cpt"→dist/css/cpt.css(component-extracted CSS; usuallyimport 'mvframe/style'is enough)
Repository layout
src/ — library source
| Path | Role |
|------|------|
| src/index.js | Install entry: registers config → global components (cpt) → util → directive → store → router |
| src/config/ | Merges defaults with app options → globalThis.$config (chip/base.js: name, copyright, version, etc.) |
| src/cpt/index.js | Auto-registers every component/*/index.vue via import.meta.glob; component name equals the folder name (PascalCase, e.g. BtnGroup) |
| src/component/ | Implementations; root class Mvc + name (see .cursor/rules/component-hierarchy.mdc) |
| src/util/index.js | Global helpers on app.config.globalProperties & globalThis ($getLang, $fa, $copy, $deepClone, …) |
| src/directive/index.js | Directives: v-copy (optional .dblclick), v-focus |
| src/store/ | createPinia + built-in init / tab / rmenu; optional storeChips; provide("store", store) |
| src/router/ | createWebHistory router; optional guard; built-in guardThis (meta.admin, afterEach + tabs, document.title) |
| src/composition/ | Import on demand; exports lang, dom, data, media, … (Vite alias @cps → this folder) |
| src/style/ | index.scss aggregates chip/*.scss (tokens, spacing, typography, layout, overrides) |
Globally registered components (folder name = registration name):
BtnGroup, Form, Frame, Icon, Input, Page, Select, SelectV2, Table, Tabs, Textarea
chip/ subfolders hold internal pieces (e.g. Frame/chip/Menu.vue); they are not registered as root components.
demo/ — local preview app
With NODE_ENV=development, Vite root is ./demo (see vite.config.js) to exercise Frame, routing, and components.
| File | Role |
|------|------|
| demo/index.html | HTML shell |
| demo/main.js | Boot: ElementPlus + ../src/index.js + ../src/style/index.scss + routes |
| demo/App.vue | Frame layout, menu: { iconClass: 'imicon', routes }, slots logo / logomini |
| demo/routes.js | Sample routes: / → Overview/Home, /a → A/Home; nested children for the sidebar |
| demo/views/Overview/Home.vue | Page + Tabs switching FormPanel / IconPanel |
| demo/views/Overview/Home/FormPanel.vue | Form demo |
| demo/views/Overview/Home/IconPanel.vue, iconfontAntNames.js | Icon demo & Ant icon name list |
| demo/auto-imports.d.ts | Types from unplugin-auto-import (Vue / vue-router) |
Local dev:
yarn install
yarn devDev server port 8088 (see vite.config.js).
Path aliases
| Alias | Points to |
|------|-----------|
| @ | src/ |
| @cps | src/composition/ |
| @scss | assets/scss (if present) |
Demo routes use paths like import("/views/Overview/Home.vue") resolved from the demo root.
Using in a host application
1. Install peer-style deps
Align versions of vue, vue-router, pinia. For Form / Table tied to Element Plus, add element-plus and app.use(ElementPlus).
2. Register MVFrame
import { createApp } from "vue";
import mvframe from "mvframe";
// Styles: use package path when depending on source / monorepo; published `dist`-only—see “Styles”
import "mvframe/src/style/index.scss";
const app = createApp(App);
app.use(mvframe, {
vueRouter: {
routes: yourRoutes,
// optional: custom beforeEach, etc.
// guard: (router) => { /* ... */ },
// useAdmin: true,
// adminPermission: () => true,
// noaccess: (next) => next(false),
},
pinia: {
useTab: true, // multi-tab + localStorage restore for `tabs` / `ctab`
// storeChips: import.meta.glob("./pinia/chip/*.js", { eager: true }),
},
config: {
// merged with src/config/chip/base.js → globalThis.$config
iconfont: {
url: "//at.alicdn.com/t/c/your_font.js",
prefix: "ant",
},
},
});Frame injects a <script> for icon fonts from globalThis.$config.iconfont.url on mount (implementation removes url afterward to avoid duplicate injection).
3. Globals at a glance
globalThis.$config— merged app configglobalThis.$router— router instance assigned by this library after installinject("store")— store factory (store.tab(),store.rmenu(), custom chips)- Global components — use
Frame,Page,Table, … without local registration - Directives —
v-copy,v-focus - Composition —
import { ... } from "mvframe/composition"or your@cpsalias
Full helper list: .cursor/rules/util.mdc and src/util/index.js.
4. Styles
- Utility classes & tokens:
.cursor/rules/style-system.mdc(--color-*, spacing, typography, layout). vite.config.jsadditionalDatainjectssrc/style/chip/mixin.scss; mirror this in apps that compile the same SCSS tree.- Published packages can use
import 'mvframe/style'(dist/css/style.css). For SCSS overrides, still linksrc/style/index.scssfrom Git/monorepo when needed.
Building the library
yarn buildProduction 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).
Design notes
- Layout, guards, tabs, and menu behavior are opinionated; heavy customization may mean forking
src/router,src/store/tab.js, or wrapping from the app. - CSS naming & units: root
Mvc*, children camelCase; prefer rem for sizes other than 1px/2px (16px root)—seestyle-system.mdc. - Use
globalThisorstore/piniaexports outsidesetup(e.g. guards), as insrc/router/chip/guard.js.
CLI: project skeleton
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.
cd /path/to/your-app
node /path/to/mvframe/scripts/scaffold-app.js
node /path/to/mvframe/scripts/scaffold-app.js --force
# Skip package.json (only scaffold sources + Vite config):
node /path/to/mvframe/scripts/scaffold-app.js --no-package-json
yarn exec mvframe-init-app
# or: npx mvframe-init-appSee MVFRAME-SCAFFOLD.md in the target project. Set MVFRAME_SCAFFOLD_TARGET to point at the project root.
Cursor Skill (app scaffold)
This repo ships .cursor/skills/mvframe-app-init. Copy it into your app’s .cursor/skills so Cursor can pick up MVFrame integration conventions.
From your app root, run either:
# Full checkout / monorepo path to mvframe
node /path/to/mvframe/scripts/install-cursor-skill.js
node /path/to/mvframe/scripts/install-cursor-skill.js /path/to/your-app
# After installing the npm package (the tarball must include `scripts/` and `.cursor/skills`—see `package.json` `files`)
cd /path/to/your-app
yarn exec mvframe-install-cursor-skill
# or: npx mvframe-install-cursor-skillDefault target is ./.cursor/skills/mvframe-app-init under the current working directory. Override with MVFRAME_CURSOR_SKILL_OUT=/path/to/your-app.
License
ISC (see package.json).
