一键导入
cube-init
初始化一个新的前端项目,使用 cube-front 框架。 当用户说"初始化项目"、"创建新项目"、"搭建前端项目"、"使用 cube-front 初始化"时使用此技能。 自动配置布局、状态管理(Pinia)、路由、API请求库、多语言支持、容器化部署等核心功能,开箱即用。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
初始化一个新的前端项目,使用 cube-front 框架。 当用户说"初始化项目"、"创建新项目"、"搭建前端项目"、"使用 cube-front 初始化"时使用此技能。 自动配置布局、状态管理(Pinia)、路由、API请求库、多语言支持、容器化部署等核心功能,开箱即用。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
根据后端 NewLife.Cube 控制器定义,在前端项目创建页面组件。当用户说"新增页面"、"创建页面"、"添加功能页面"、"给 XX 模块加页面"时使用。
在 cube-front 框架中新增、注册或切换页面布局。 当用户说"新增布局"、"自定义布局"、"修改布局"、"切换布局"、"使用 XXX 布局"时使用。 包含布局组件创建、框架注册、应用使用的完整流程。
LOV(List of Values)值集系统使用指南。涵盖后端配置、前端组件、API 封装、枚举自动注册全链路。当用户说"配置值集"、"使用LovSelect"、"添加LOV"、"值集选择"、"枚举下拉"、"使用LOV"时使用。
命令式弹窗的代码组织规范与最佳实践。 当用户问"弹窗怎么组织"、"弹窗放哪"、"弹窗目录结构"、"弹窗代码规范"、"新增弹窗怎么写"、"重构弹窗结构"时使用。 核心原则:Vue 组件 + openXxx.ts 打开函数作为"一对"放在一起,按业务归属就近放置。
(已迁移) 此技能已更名为 cube-add-page,请使用 cube-add-page 技能根据控制器创建前端页面。当你需要创建或修改 Cube 前端 API 文件时也请使用 cube-add-page。
在 cube-front 微前端架构中新增一个子应用/模块。 当用户说"新增应用"、"创建子应用"、"添加新模块"、"新建页面"、"创建新页面"时使用。 注意:新增的应用放在调用技能的目录(项目根目录 apps/),而不是 cube-front 目录。
| name | cube-init |
| description | 初始化一个新的前端项目,使用 cube-front 框架。 当用户说"初始化项目"、"创建新项目"、"搭建前端项目"、"使用 cube-front 初始化"时使用此技能。 自动配置布局、状态管理(Pinia)、路由、API请求库、多语言支持、容器化部署等核心功能,开箱即用。 |
当用户需要创建一个新的前端项目,或在现有项目中引入 cube-front 框架时使用。
cube-front 包发布名为 @newlife/cube-vue,代码中 import 使用 cube-front/... 路径(通过 pnpm 别名机制)。
支持两种项目结构:
| 场景 | 说明 | 参考 |
|---|---|---|
| Monorepo 工作空间 | 项目放在 cube-front 所在仓库内,通过 workspace 协议引用 | |
| 独立应用 | cube-front 作为 npm 包安装 | 后续 npm 发布后 |
本技能以 monorepo 场景为主,独立应用场景仅调整依赖声明方式(npm install @newlife/cube-vue + 别名)。
pnpm-workspace.yaml(monorepo 场景)在根目录 pnpm-workspace.yaml 中添加新项目:
packages:
- '新项目目录'
- 'Cube/NewLife.Cube.Vue/web' # 如已有则跳过
在项目 src/ 目录下创建 main.ts:
// src/main.ts
import { initApp } from 'cube-front/core/initApp';
import 'cube-front/core/global.css';
initApp();
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>应用名称</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
在项目根目录创建 configs/ 目录:
configs/config.ts - 通用配置:
import type { EnvConfig } from 'cube-front/core/configure/types';
export const config: EnvConfig = {
base: {
title: '应用名称',
footer: '版权所有 © 2026',
},
ui: {
theme: {
primaryColor: '#1890ff',
},
},
auth: {
oauthUrl: '/login',
getUserInfoAxiosConfig: {
url: '/Admin/User/Info',
method: 'GET',
},
},
};
configs/config.development.ts - 开发环境配置:
import type { EnvConfig } from 'cube-front/core/configure/types';
export const config: EnvConfig = {
request: {
baseUrl: import.meta.env.VITE_APP_BASE_API || 'http://localhost:5000',
timeout: 30000,
},
};
configs/config.test.ts - 测试环境配置:
import type { EnvConfig } from 'cube-front/core/configure/types';
export const config: EnvConfig = {
request: {
baseUrl: import.meta.env.VITE_APP_BASE_API || '/api',
timeout: 30000,
},
};
configs/config.production.ts - 生产环境配置(支持容器部署替换):
import type { EnvConfig } from 'cube-front/core/configure/types';
export const config: EnvConfig = {
request: {
baseUrl: '${BUILD_REQUEST_BASE_URL}',
timeout: 30000,
},
};
configs/microAppConfig.json - 微应用配置(空数组即可):
[]
.env - 通用环境变量:
VITE_APP_TITLE=应用名称
.env.development - 开发环境变量:
VITE_APP_ENV=development
VITE_APP_TITLE=应用名称 - 开发环境
VITE_APP_BASE_API=http://localhost:5000
.env.test - 测试环境变量(需 vite --mode test):
VITE_APP_ENV=test
VITE_APP_TITLE=应用名称 - 测试环境
VITE_APP_BASE_API=http://test-api.example.com
.env.production - 生产环境变量:
VITE_APP_ENV=production
VITE_APP_TITLE=应用名称
# 生产环境 API URL 由容器部署时通过 BUILD_REQUEST_BASE_URL 注入
VITE_APP_BASE_API=/api
vite.config.ts(monorepo 场景——不需要 alias):
import { fileURLToPath, URL } from 'node:url';
import { defineConfig, loadEnv } from 'vite';
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
import cubeFront from 'cube-front/core/plugin';
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), '');
return {
plugins: [
vue(),
vueJsx(),
cubeFront(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
// ❌ 不需要 'cube-front' 别名——pnpm workspace 协议自动处理
},
},
server: {
port: 5188,
host: '0.0.0.0',
proxy: {
'/api': {
target: env.VITE_APP_BASE_API || 'http://localhost:5000',
changeOrigin: true,
},
},
},
build: {
outDir: 'dist',
sourcemap: true,
target: 'es2022',
},
};
});
为什么不需要
cube-front别名? 因为 pnpm workspace 协议(workspace:*)+ 别名("cube-front": "workspace:@newlife/cube-vue@*")会自动创建node_modules/cube-front的 symlink,Node.js 模块解析就能直接找到。
tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }]
}
tsconfig.node.json:
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true,
"strict": true
},
"include": ["vite.config.ts"]
}
Monorepo 场景 — 依赖声明:
使用 两条 workspace 依赖,利用 pnpm 别名保留 cube-front import 路径:
{
"dependencies": {
"cube-front": "workspace:@newlife/cube-vue@*",
"@newlife/cube-vue": "workspace:*",
"dayjs": "^1.11.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.2.0",
"@vitejs/plugin-vue-jsx": "^4.1.0",
"cross-env": "^7.0.3",
"typescript": "~5.8.0",
"vite": "^6.2.0",
"vue-tsc": "^2.2.0"
}
}
条目解释:
| 依赖 | 作用 |
|---|---|
"cube-front": "workspace:@newlife/cube-vue@*" | 别名,让 node_modules/cube-front → symlink 到本地库 |
"@newlife/cube-vue": "workspace:*" | 正式包名,将来发 npm 版时用于安装 |
| vue/pinia/element-plus/vue-router | 不必须声明(pnpm auto-install-peers 自动装),但建议显式锁定版本 |
为什么不需要
cube-front: "link:../../cube-front"?因为 monorepo workspace 模式下,workspace:*等价且语义更清晰,link:路径已被淘汰。
{
"name": "your-app",
"version": "0.1.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"dev:test": "vite --mode test",
"build": "vite build",
"build:test": "vite build --mode test",
"preview": "vite preview",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix"
},
"dependencies": {
"cube-front": "workspace:@newlife/cube-vue@*",
"@newlife/cube-vue": "workspace:*",
"element-plus": "^2.9.0",
"pinia": "^3.0.0",
"vue": "^3.5.0",
"vue-router": "^4.5.0",
"dayjs": "^1.11.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.2.0",
"@vitejs/plugin-vue-jsx": "^4.1.0",
"cross-env": "^7.0.3",
"typescript": "~5.8.0",
"vite": "^6.2.0",
"vue-tsc": "^2.2.0"
}
}
在项目根目录创建 docker/ 目录:
docker/Dockerfile:
# 构建阶段
FROM node:20-alpine AS builder
WORKDIR /app
# 安装 pnpm
RUN npm install -g pnpm
# 安装依赖(monorepo 场景需复制根目录 lock)
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
# 复制源代码
COPY . .
# 构建
RUN pnpm run build
# 生产阶段
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY docker/enterpoint.sh /docker-entrypoint.d/enterpoint.sh
RUN chmod +x /docker-entrypoint.d/enterpoint.sh
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
docker/enterpoint.sh:
#!/bin/bash
set +e
set -x
echo "🚀 Frontend Container Starting..."
# 替换 BUILD_ 开头的占位符
sed -i "s|BUILD_REQUEST_BASE_URL|${BUILD_REQUEST_BASE_URL:-/}|g" /usr/share/nginx/html/index.html
echo "✅ 配置完成"
echo "🎉 启动 Nginx..."
exec "$@"
defaultConfig → configs/config.ts → configs/config.{env}.ts → window._CUBE_CONFIG_ → BUILD_ 占位符
用于生产环境容器部署时动态注入配置:
configs/config.production.ts 中使用 baseUrl: '${BUILD_REQUEST_BASE_URL}'BUILD_XXX 占位符注入到 dist/index.htmldocker/enterpoint.sh 通过 sed 替换占位符生成的 html 内联脚本格式:
<script>
let cubeConfig = window._CUBE_CONFIG_ || (window._CUBE_CONFIG_={});
let request = cubeConfig["request"] || (cubeConfig["request"]={});
request["baseUrl"] = "BUILD_REQUEST_BASE_URL";
</script>
| 功能 | 说明 | 如何使用 |
|---|---|---|
| 布局系统 | MainLayout 主布局,侧边栏+内容区 | 通过 LayoutKey 依赖注入自定义 |
| 状态管理 | UserStore 用户状态,MenuStore 菜单状态 | useUserStore(), useMenuStore() |
| 路由系统 | 动态路由,微前端支持 | 通过后端菜单动态生成 |
| API请求 | 带 Token、401处理、错误提示的 Axios 封装 | import request from 'cube-front/core/utils/request' |
| 国际化 | Vue I18n,支持动态切换 | intl.get('key').d('默认值') |
| 页面覆盖 | Section 机制,可覆盖框架组件 | 在 views/ 下创建大写开头的 Vue 文件 |
| BUILD_ 配置注入 | 生产构建时自动注入到 html | 在 config.production.ts 使用 ${BUILD_XXX} |
开发环境验证:
pnpm dev 启动http://localhost:3000生产构建验证:
pnpm build 成功dist/index.html 是否包含 BUILD_ 占位符脚本默认中文,如需多语言在 src/i18n/ 下配置:
src/i18n/index.ts - I18n 实例src/i18n/locales/ - 语言文件目录