Compare commits
4 Commits
tauri-v0.1
...
fast-crud
Author | SHA1 | Date | |
---|---|---|---|
|
032dbc6815 | ||
|
3c33f89ec1 | ||
|
f7090d3dbc | ||
|
59af204a4c |
@@ -1,2 +1 @@
|
|||||||
VITE_HTTP_PROXY=Y
|
VITE_HTTP_PROXY=Y
|
||||||
VITE_SOYBEAN_ROUTE_PLUGIN=Y
|
|
||||||
|
@@ -2,4 +2,3 @@
|
|||||||
components.d.ts
|
components.d.ts
|
||||||
router-page.d.ts
|
router-page.d.ts
|
||||||
*.svg
|
*.svg
|
||||||
src-tauri/target
|
|
||||||
|
16
.github/workflows/release.yml
vendored
@@ -1,25 +1,27 @@
|
|||||||
name: Release
|
name: Release
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "v*.**"
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- "v*"
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
|
name: Build
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- uses: actions/setup-node@v3
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 16.x
|
node-version: 16.x
|
||||||
|
|
||||||
- run: npx githublogen
|
- name: Create github releases
|
||||||
|
run: npx changelogithub
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||||
|
2
.npmrc
@@ -1,2 +1,4 @@
|
|||||||
registry=https://registry.npmmirror.com/
|
registry=https://registry.npmmirror.com/
|
||||||
shamefully-hoist=true
|
shamefully-hoist=true
|
||||||
|
strict-peer-dependencies=false
|
||||||
|
auto-install-peers=true
|
||||||
|
8
.vscode/launch.json
vendored
@@ -7,14 +7,6 @@
|
|||||||
"name": "Vue debugger",
|
"name": "Vue debugger",
|
||||||
"url": "http://localhost:3200",
|
"url": "http://localhost:3200",
|
||||||
"webRoot": "${workspaceFolder}"
|
"webRoot": "${workspaceFolder}"
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "node",
|
|
||||||
"request": "launch",
|
|
||||||
"name": "TS debugger",
|
|
||||||
"skipFiles": ["<node_internals>/**"],
|
|
||||||
"runtimeArgs": ["--loader", "tsx"],
|
|
||||||
"program": "${relativeFile}"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
1313
CHANGELOG.md
51
README.md
@@ -19,19 +19,6 @@
|
|||||||
- **权限路由**:提供前端静态和后端动态两种路由模式,基于 mock 的动态路由能快速实现后端动态路由
|
- **权限路由**:提供前端静态和后端动态两种路由模式,基于 mock 的动态路由能快速实现后端动态路由
|
||||||
- **请求函数**:基于 axios 的完善的请求函数封装,提供 Promise 和 hooks 两种请求函数,加入请求结果数据转换的适配器
|
- **请求函数**:基于 axios 的完善的请求函数封装,提供 Promise 和 hooks 两种请求函数,加入请求结果数据转换的适配器
|
||||||
|
|
||||||
## SoybeanJS 工具库
|
|
||||||
|
|
||||||
- [@soybeanjs/cli](https://github.com/soybeanjs/cli): SoybeanJS 命令行工具,包含发布、git 和依赖等相关的实用命令
|
|
||||||
- [@soybeanjs/changelog](https://github.com/soybeanjs/changelog): 根据 git tags 和 commits 生成 changelog [示例](./CHANGELOG.md)
|
|
||||||
- [eslint-config-soybeanjs](https://github.com/soybeanjs/eslint-config): SoybeanJS 的 eslint 预设配置
|
|
||||||
- [@soybeanjs/materials](https://github.com/soybeanjs/materials): SoybeanJS 的物料仓库
|
|
||||||
- [@soybeanjs/vite-plugin-vue-page-route](https://github.com/soybeanjs/vite-plugin-vue-page-route): SoybeanAdmin 的路由插件
|
|
||||||
|
|
||||||
## 基于 SoybeanAdmin 二次开发的项目
|
|
||||||
|
|
||||||
- [electron-mock-admin](https://github.com/lixin59/electron-mock-api): 一个 Mock Api 管理系统,帮助前端开发伙伴快速实现接口的 mock。
|
|
||||||
- [T-Shell](https://github.com/TheBlindM/T-Shell): 是一个可配置命令提示的终端模拟器和 SSH 客户端。
|
|
||||||
|
|
||||||
## 在线预览
|
## 在线预览
|
||||||
|
|
||||||
- [Soybean Admin 预览地址](https://soybean.pro/)
|
- [Soybean Admin 预览地址](https://soybean.pro/)
|
||||||
@@ -42,12 +29,12 @@
|
|||||||
|
|
||||||
## 代码仓库
|
## 代码仓库
|
||||||
|
|
||||||
| 仓库 | github 地址 | gitee 镜像 | 预览 |
|
- [github](https://github.com/honghuangdc/soybean-admin)
|
||||||
| -------------- | ----------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | --------------------------------------------------------- |
|
- [tauri 版](https://github.com/honghuangdc/soybean-admin/tree/tauri)
|
||||||
| soybean-admin | [github](https://github.com/honghuangdc/soybean-admin) | [gitee](https://gitee.com/honghuangdc/soybean-admin) | [预览](https://soybean.pro/) |
|
- [精简版](https://github.com/honghuangdc/soybean-admin/tree/thin)
|
||||||
| tauri 版 | [tauri 版](https://github.com/honghuangdc/soybean-admin/tree/tauri) | [tauri 版](https://gitee.com/honghuangdc/soybean-admin/tree/tauri) | |
|
- [gitee](https://gitee.com/honghuangdc/soybean-admin)
|
||||||
| 精简版 | [精简版](https://github.com/honghuangdc/soybean-admin/tree/thin) | [精简版](https://gitee.com/honghuangdc/soybean-admin/tree/thin) | |
|
- [tauri 版](https://gitee.com/honghuangdc/soybean-admin/tree/tauri)
|
||||||
| 集成 fast-crud | [集成 fast-crud](https://github.com/honghuangdc/soybean-admin/tree/fast-crud) | [集成 fast-crud](https://gitee.com/honghuangdc/soybean-admin/tree/fast-crud) | [预览](http://fast-crud.docmirror.cn/soybean/#/crud/demo) |
|
- [精简版](https://gitee.com/honghuangdc/soybean-admin/tree/thin)
|
||||||
|
|
||||||
## 更新日志
|
## 更新日志
|
||||||
|
|
||||||
@@ -67,15 +54,13 @@
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -83,12 +68,6 @@
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
<div align="center">
|
|
||||||
<img style="width:380px;margin-right:18px;border:1px solid #dedede;" src="https://s2.loli.net/2023/06/07/A5Nonc9vI6pB1lr.png" />
|
|
||||||
|
|
||||||
<img style="width:380px;border:1px solid #dedede;" src="https://s2.loli.net/2023/06/07/VwBjqEhTke3OxXF.png" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## 安装使用
|
## 安装使用
|
||||||
|
|
||||||
- 环境配置
|
- 环境配置
|
||||||
@@ -140,6 +119,10 @@ docker run --name soybean -p 80:80 -d soybeanjs/soybean-admin:v0.9.6
|
|||||||
|
|
||||||
项目已用 simple-git-hooks 代替了 husky, 旧版本用了 husky,执行 pnpm soy init-git-hooks 进行初始化配置
|
项目已用 simple-git-hooks 代替了 husky, 旧版本用了 husky,执行 pnpm soy init-git-hooks 进行初始化配置
|
||||||
|
|
||||||
|
## 基于 SoybeanAdmin 二次开发的项目
|
||||||
|
[electron-mock-admin](https://github.com/lixin59/electron-mock-api): 一个 Mock Api 管理系统,帮助前端开发伙伴快速实现接口的mock。
|
||||||
|
[T-Shell](https://github.com/TheBlindM/T-Shell): 是一个可配置命令提示的终端模拟器和 SSH客户端。
|
||||||
|
|
||||||
## 浏览器支持
|
## 浏览器支持
|
||||||
|
|
||||||
本地开发推荐使用`Chrome 90+` 浏览器
|
本地开发推荐使用`Chrome 90+` 浏览器
|
||||||
@@ -159,13 +142,17 @@ docker run --name soybean -p 80:80 -d soybeanjs/soybean-admin:v0.9.6
|
|||||||
`Soybean Admin` 是完全开源免费的项目,在帮助开发者更方便地进行中大型管理系统开发,同时也提供微信和 QQ 交流群,使用问题欢迎在群内提问。
|
`Soybean Admin` 是完全开源免费的项目,在帮助开发者更方便地进行中大型管理系统开发,同时也提供微信和 QQ 交流群,使用问题欢迎在群内提问。
|
||||||
|
|
||||||
<div style="display:flex;">
|
<div style="display:flex;">
|
||||||
|
<!-- <div style="padding-right:24px;">
|
||||||
|
<p>微信交流群</p>
|
||||||
|
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybeanjs-wechat0503.jpeg" style="width:200px" />
|
||||||
|
</div> -->
|
||||||
<div style="padding-right:24px;">
|
<div style="padding-right:24px;">
|
||||||
<p>QQ交流群</p>
|
<p>QQ交流群</p>
|
||||||
<img src="https://i.loli.net/2021/11/24/1J6REWXiHomU2kM.jpg" style="width:200px" />
|
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/qq-soybean-admin.jpg" style="width:200px" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p>添加本人微信,欢迎来技术交流,业务咨询</p>
|
<p>添加本人微信,欢迎来技术交流,业务咨询</p>
|
||||||
<img src="https://s2.loli.net/2023/06/07/sVyCUFBvzQ9f5b7.jpg" style="width:200px" />
|
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybeanjs.jpeg" style="width:180px" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -177,4 +164,4 @@ docker run --name soybean -p 80:80 -d soybeanjs/soybean-admin:v0.9.6
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
本项目基于[MIT © Soybean-2021](./LICENSE) 协议,仅供参考学习,商用时请保留作者的版权信息,作者不对软件做担保和负责。
|
[MIT © Soybean-2021](./LICENSE)
|
||||||
|
@@ -3,7 +3,6 @@ import vue from '@vitejs/plugin-vue';
|
|||||||
import vueJsx from '@vitejs/plugin-vue-jsx';
|
import vueJsx from '@vitejs/plugin-vue-jsx';
|
||||||
import unocss from '@unocss/vite';
|
import unocss from '@unocss/vite';
|
||||||
import progress from 'vite-plugin-progress';
|
import progress from 'vite-plugin-progress';
|
||||||
import VueDevtools from 'vite-plugin-vue-devtools';
|
|
||||||
import pageRoute from '@soybeanjs/vite-plugin-vue-page-route';
|
import pageRoute from '@soybeanjs/vite-plugin-vue-page-route';
|
||||||
import unplugin from './unplugin';
|
import unplugin from './unplugin';
|
||||||
import mock from './mock';
|
import mock from './mock';
|
||||||
@@ -23,11 +22,11 @@ export function setupVitePlugins(viteEnv: ImportMetaEnv): (PluginOption | Plugin
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
vueJsx(),
|
vueJsx(),
|
||||||
VueDevtools(),
|
|
||||||
...unplugin(viteEnv),
|
...unplugin(viteEnv),
|
||||||
unocss(),
|
unocss(),
|
||||||
mock(viteEnv),
|
mock(viteEnv),
|
||||||
progress()
|
progress(),
|
||||||
|
pageRoute()
|
||||||
];
|
];
|
||||||
|
|
||||||
if (viteEnv.VITE_VISUALIZER === 'Y') {
|
if (viteEnv.VITE_VISUALIZER === 'Y') {
|
||||||
@@ -39,9 +38,6 @@ export function setupVitePlugins(viteEnv: ImportMetaEnv): (PluginOption | Plugin
|
|||||||
if (viteEnv.VITE_PWA === 'Y' || viteEnv.VITE_VERCEL === 'Y') {
|
if (viteEnv.VITE_PWA === 'Y' || viteEnv.VITE_VERCEL === 'Y') {
|
||||||
plugins.push(pwa());
|
plugins.push(pwa());
|
||||||
}
|
}
|
||||||
if (viteEnv.VITE_SOYBEAN_ROUTE_PLUGIN === 'Y') {
|
|
||||||
plugins.push(pageRoute());
|
|
||||||
}
|
|
||||||
|
|
||||||
return plugins;
|
return plugins;
|
||||||
}
|
}
|
||||||
|
21
changelogithub.config.json
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"types": {
|
||||||
|
"feat": { "title": "🚀 Features" },
|
||||||
|
"perf": { "title": "🔥 Performance" },
|
||||||
|
"fix": { "title": "🩹 Fixes" },
|
||||||
|
"refactor": { "title": "💅 Refactors" },
|
||||||
|
"docs": { "title": "📖 Documentation" },
|
||||||
|
"types": { "title": "🌊 Types" },
|
||||||
|
"chore": { "title": "🏡 Chore" },
|
||||||
|
"test": { "title": "🧪 Tests" },
|
||||||
|
"style": { "title": "🎨 Styles" },
|
||||||
|
"ci": { "title": "🤖 CI" }
|
||||||
|
},
|
||||||
|
"scopeMap": {},
|
||||||
|
"titles": {
|
||||||
|
"breakingChanges": "🚨 Breaking Changes"
|
||||||
|
},
|
||||||
|
"contributors": true,
|
||||||
|
"capitalize": true,
|
||||||
|
"group": true
|
||||||
|
}
|
295
mock/api/crud/base.ts
Normal file
@@ -0,0 +1,295 @@
|
|||||||
|
export type ListItem = {
|
||||||
|
id?: number;
|
||||||
|
children?: ListItem[];
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
|
export type BaseMockOptions = { name: string; copyTimes?: number; list: ListItem[]; idGenerator: number };
|
||||||
|
type CopyListParams = { originList: ListItem[]; newList: ListItem[]; options: BaseMockOptions; parentId?: number };
|
||||||
|
|
||||||
|
function copyList(props: CopyListParams) {
|
||||||
|
const { originList, newList, options, parentId } = props;
|
||||||
|
for (const item of originList) {
|
||||||
|
const newItem: ListItem = { ...item, parentId };
|
||||||
|
newItem.id = options.idGenerator;
|
||||||
|
options.idGenerator += 1;
|
||||||
|
newList.push(newItem);
|
||||||
|
if (item.children) {
|
||||||
|
newItem.children = [];
|
||||||
|
copyList({
|
||||||
|
originList: item.children,
|
||||||
|
newList: newItem.children,
|
||||||
|
options,
|
||||||
|
parentId: newItem.id
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function delById(req: Service.MockOption, list: any[]) {
|
||||||
|
for (let i = 0; i < list.length; i += 1) {
|
||||||
|
const item = list[i];
|
||||||
|
if (item.id === parseInt(req.query.id, 10)) {
|
||||||
|
list.splice(i, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (item.children && item.children.length > 0) {
|
||||||
|
delById(req, item.children);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findById(id: number, list: ListItem[]): any {
|
||||||
|
for (const item of list) {
|
||||||
|
if (item.id === id) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
if (item.children && item.children.length > 0) {
|
||||||
|
const sub = findById(id, item.children);
|
||||||
|
if (sub !== null && sub !== undefined) {
|
||||||
|
return sub;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function matchWithArrayCondition(value: any[], item: ListItem, key: string) {
|
||||||
|
if (value.length === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
let matched = false;
|
||||||
|
for (const i of value) {
|
||||||
|
if (item[key] instanceof Array) {
|
||||||
|
for (const j of item[key]) {
|
||||||
|
if (i === j) {
|
||||||
|
matched = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (matched) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (item[key] === i || (typeof item[key] === 'string' && item[key].indexOf(`${i}`) >= 0)) {
|
||||||
|
matched = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (matched) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matched;
|
||||||
|
}
|
||||||
|
|
||||||
|
function matchWithObjectCondition(value: any, item: ListItem, key: string) {
|
||||||
|
let matched = true;
|
||||||
|
for (const key2 of Object.keys(value)) {
|
||||||
|
const v = value[key2];
|
||||||
|
if (v && item[key] && v !== item[key][key2]) {
|
||||||
|
matched = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matched;
|
||||||
|
}
|
||||||
|
|
||||||
|
function searchFromList(list: ListItem[], query: any) {
|
||||||
|
const filter = (item: ListItem) => {
|
||||||
|
let allFound = true; // 是否所有条件都符合
|
||||||
|
for (const key of Object.keys(query)) {
|
||||||
|
const value = query[key];
|
||||||
|
if (value === undefined || value === null || value === '') {
|
||||||
|
// no nothing
|
||||||
|
} else if (value instanceof Array) {
|
||||||
|
// 如果条件中的value是数组的话,只要查到一个就行
|
||||||
|
const matched = matchWithArrayCondition(value, item, key);
|
||||||
|
if (!matched) {
|
||||||
|
allFound = false;
|
||||||
|
}
|
||||||
|
} else if (value instanceof Object) {
|
||||||
|
// 如果条件中的value是对象的话,需要每个key都匹配
|
||||||
|
const matched = matchWithObjectCondition(value, item, key);
|
||||||
|
if (!matched) {
|
||||||
|
allFound = false;
|
||||||
|
}
|
||||||
|
} else if (item[key] !== value) {
|
||||||
|
allFound = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allFound;
|
||||||
|
};
|
||||||
|
return list.filter(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
buildMock(options: BaseMockOptions) {
|
||||||
|
const name = options.name;
|
||||||
|
if (!options.copyTimes) {
|
||||||
|
options.copyTimes = 29;
|
||||||
|
}
|
||||||
|
const list: any[] = [];
|
||||||
|
for (let i = 0; i < options.copyTimes; i += 1) {
|
||||||
|
copyList({
|
||||||
|
originList: options.list,
|
||||||
|
newList: list,
|
||||||
|
options
|
||||||
|
});
|
||||||
|
}
|
||||||
|
options.list = list;
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
path: `/mock/${name}/page`,
|
||||||
|
method: 'post',
|
||||||
|
handle(req: Service.MockOption) {
|
||||||
|
let data = [...list];
|
||||||
|
let limit = 20;
|
||||||
|
let offset = 0;
|
||||||
|
for (const item of list) {
|
||||||
|
if (item.children && item.children.length === 0) {
|
||||||
|
item.hasChildren = false;
|
||||||
|
item.lazy = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let orderAsc: any;
|
||||||
|
let orderProp: any;
|
||||||
|
if (req && req.body) {
|
||||||
|
const { page, query } = req.body;
|
||||||
|
if (page.limit) {
|
||||||
|
limit = parseInt(page.limit, 10);
|
||||||
|
}
|
||||||
|
if (page.offset) {
|
||||||
|
offset = parseInt(page.offset, 10);
|
||||||
|
}
|
||||||
|
if (Object.keys(query).length > 0) {
|
||||||
|
data = searchFromList(list, query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const start = offset;
|
||||||
|
let end = offset + limit;
|
||||||
|
if (data.length < end) {
|
||||||
|
end = data.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (orderProp) {
|
||||||
|
// 排序
|
||||||
|
data.sort((a, b) => {
|
||||||
|
let ret = 0;
|
||||||
|
if (a[orderProp] > b[orderProp]) {
|
||||||
|
ret = 1;
|
||||||
|
} else if (a[orderProp] < b[orderProp]) {
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
return orderAsc ? ret : -ret;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const records = data.slice(start, end);
|
||||||
|
const lastOffset = data.length - (data.length % limit);
|
||||||
|
if (offset > lastOffset) {
|
||||||
|
offset = lastOffset;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
code: 200,
|
||||||
|
message: 'success',
|
||||||
|
data: {
|
||||||
|
records,
|
||||||
|
total: data.length,
|
||||||
|
limit,
|
||||||
|
offset
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: `/mock/${name}/get`,
|
||||||
|
method: 'get',
|
||||||
|
handle(req: Service.MockOption) {
|
||||||
|
let id = req.query.id;
|
||||||
|
id = parseInt(id, 10);
|
||||||
|
let current = null;
|
||||||
|
for (const item of list) {
|
||||||
|
if (item.id === id) {
|
||||||
|
current = item;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
code: 200,
|
||||||
|
message: 'success',
|
||||||
|
data: current
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: `/mock/${name}/add`,
|
||||||
|
method: 'post',
|
||||||
|
handle(req: Service.MockOption) {
|
||||||
|
req.body.id = options.idGenerator;
|
||||||
|
options.idGenerator += 1;
|
||||||
|
list.unshift(req.body);
|
||||||
|
return {
|
||||||
|
code: 200,
|
||||||
|
message: 'success',
|
||||||
|
data: req.body.id
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: `/mock/${name}/update`,
|
||||||
|
method: 'post',
|
||||||
|
handle(req: Service.MockOption) {
|
||||||
|
const item = findById(req.body.id, list);
|
||||||
|
if (item) {
|
||||||
|
Object.assign(item, req.body);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
code: 200,
|
||||||
|
message: 'success',
|
||||||
|
data: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: `/mock/${name}/delete`,
|
||||||
|
method: 'post',
|
||||||
|
handle(req: Service.MockOption) {
|
||||||
|
delById(req, list);
|
||||||
|
return {
|
||||||
|
code: 200,
|
||||||
|
message: 'success',
|
||||||
|
data: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: `/mock/${name}/batchDelete`,
|
||||||
|
method: 'post',
|
||||||
|
handle(req: Service.MockOption) {
|
||||||
|
const ids = req.body.ids;
|
||||||
|
for (let i = list.length - 1; i >= 0; i -= 1) {
|
||||||
|
const item = list[i];
|
||||||
|
if (ids.indexOf(item.id) >= 0) {
|
||||||
|
list.splice(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
code: 200,
|
||||||
|
message: 'success',
|
||||||
|
data: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: `/mock/${name}/all`,
|
||||||
|
method: 'post',
|
||||||
|
handle() {
|
||||||
|
return {
|
||||||
|
code: 200,
|
||||||
|
message: 'success',
|
||||||
|
data: list
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
};
|
5
mock/api/crud/index.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import demo from './modules/demo';
|
||||||
|
import headerGroup from './modules/header-group';
|
||||||
|
|
||||||
|
const crudApis = [...demo, ...headerGroup];
|
||||||
|
export default crudApis;
|
56
mock/api/crud/modules/demo.ts
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import type { MethodType, MockMethod } from 'vite-plugin-mock';
|
||||||
|
import type { BaseMockOptions } from '../base';
|
||||||
|
import mockBase from '../base';
|
||||||
|
import MockOption = Service.MockOption;
|
||||||
|
|
||||||
|
const options: BaseMockOptions = {
|
||||||
|
name: 'crud/demo',
|
||||||
|
idGenerator: 0,
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
select: '1',
|
||||||
|
text: '文本测试',
|
||||||
|
copyable: '文本可复制',
|
||||||
|
avatar: 'http://greper.handsfree.work/extends/avatar.jpg',
|
||||||
|
richtext: '富文本',
|
||||||
|
datetime: '2023-01-30 11:11:11'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
select: '2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
select: '0'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
const mockedApis = mockBase.buildMock(options);
|
||||||
|
|
||||||
|
const apis: MockMethod[] = [
|
||||||
|
{
|
||||||
|
url: `/mock/${options.name}/dict`,
|
||||||
|
method: 'get',
|
||||||
|
response: () => {
|
||||||
|
return {
|
||||||
|
code: 200,
|
||||||
|
message: '',
|
||||||
|
data: [
|
||||||
|
{ value: '0', label: '关', color: 'warning' },
|
||||||
|
{ value: '1', label: '开', color: 'success' },
|
||||||
|
{ value: '2', label: '停' }
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const mockedApi of mockedApis) {
|
||||||
|
apis.push({
|
||||||
|
url: mockedApi.path,
|
||||||
|
method: mockedApi.method as MethodType,
|
||||||
|
response: (request: MockOption) => {
|
||||||
|
return mockedApi.handle(request);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default apis;
|
46
mock/api/crud/modules/header-group.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import type { MethodType, MockMethod } from 'vite-plugin-mock';
|
||||||
|
import type { BaseMockOptions } from '../base';
|
||||||
|
import mockBase from '../base';
|
||||||
|
import MockOption = Service.MockOption;
|
||||||
|
|
||||||
|
const options: BaseMockOptions = {
|
||||||
|
name: 'crud/header-group',
|
||||||
|
idGenerator: 0,
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
name: '张三',
|
||||||
|
age: 18,
|
||||||
|
province: '广东省',
|
||||||
|
city: '深圳市',
|
||||||
|
county: '南山区',
|
||||||
|
street: '粤海街道'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '李四',
|
||||||
|
age: 26,
|
||||||
|
province: '浙江省',
|
||||||
|
city: '杭州市',
|
||||||
|
county: '西湖区',
|
||||||
|
street: '西湖街道'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '王五',
|
||||||
|
age: 24
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
const mockedApis = mockBase.buildMock(options);
|
||||||
|
|
||||||
|
const apis: MockMethod[] = [];
|
||||||
|
|
||||||
|
for (const mockedApi of mockedApis) {
|
||||||
|
apis.push({
|
||||||
|
url: mockedApi.path,
|
||||||
|
method: mockedApi.method as MethodType,
|
||||||
|
response: (request: MockOption) => {
|
||||||
|
return mockedApi.handle(request);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default apis;
|
@@ -1,5 +1,6 @@
|
|||||||
import auth from './auth';
|
import auth from './auth';
|
||||||
import route from './route';
|
import route from './route';
|
||||||
import management from './management';
|
import management from './management';
|
||||||
|
import crud from './crud';
|
||||||
|
|
||||||
export default [...auth, ...route, ...management];
|
export default [...auth, ...route, ...management, ...crud];
|
||||||
|
@@ -12,8 +12,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
meta: {
|
meta: {
|
||||||
title: '分析页',
|
title: '分析页',
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'icon-park-outline:analysis',
|
icon: 'icon-park-outline:analysis'
|
||||||
i18nTitle: 'message.routes.dashboard.analysis'
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -23,16 +22,14 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
meta: {
|
meta: {
|
||||||
title: '工作台',
|
title: '工作台',
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'icon-park-outline:workbench',
|
icon: 'icon-park-outline:workbench'
|
||||||
i18nTitle: 'message.routes.dashboard.workbench'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '仪表盘',
|
title: '仪表盘',
|
||||||
icon: 'mdi:monitor-dashboard',
|
icon: 'mdi:monitor-dashboard',
|
||||||
order: 1,
|
order: 1
|
||||||
i18nTitle: 'message.routes.dashboard._value'
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -46,7 +43,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'vue文档',
|
title: 'vue文档',
|
||||||
i18nTitle: 'message.routes.document.vue',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'logos:vue'
|
icon: 'logos:vue'
|
||||||
}
|
}
|
||||||
@@ -57,7 +53,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'vite文档',
|
title: 'vite文档',
|
||||||
i18nTitle: 'message.routes.document.vite',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'logos:vitejs'
|
icon: 'logos:vitejs'
|
||||||
}
|
}
|
||||||
@@ -68,7 +63,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'naive文档',
|
title: 'naive文档',
|
||||||
i18nTitle: 'message.routes.document.naive',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'logos:naiveui'
|
icon: 'logos:naiveui'
|
||||||
}
|
}
|
||||||
@@ -79,7 +73,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '项目文档',
|
title: '项目文档',
|
||||||
i18nTitle: 'message.routes.document.project',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
localIcon: 'logo'
|
localIcon: 'logo'
|
||||||
}
|
}
|
||||||
@@ -89,7 +82,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
path: '/document/project-link',
|
path: '/document/project-link',
|
||||||
meta: {
|
meta: {
|
||||||
title: '项目文档(外链)',
|
title: '项目文档(外链)',
|
||||||
i18nTitle: 'message.routes.document.project-link',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
localIcon: 'logo',
|
localIcon: 'logo',
|
||||||
href: 'https://docs.soybean.pro/'
|
href: 'https://docs.soybean.pro/'
|
||||||
@@ -98,7 +90,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '文档',
|
title: '文档',
|
||||||
i18nTitle: 'message.routes.document._value',
|
|
||||||
icon: 'mdi:file-document-multiple-outline',
|
icon: 'mdi:file-document-multiple-outline',
|
||||||
order: 2
|
order: 2
|
||||||
}
|
}
|
||||||
@@ -114,7 +105,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '按钮',
|
title: '按钮',
|
||||||
i18nTitle: 'message.routes.component.button',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'mdi:button-cursor'
|
icon: 'mdi:button-cursor'
|
||||||
}
|
}
|
||||||
@@ -125,7 +115,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '卡片',
|
title: '卡片',
|
||||||
i18nTitle: 'message.routes.component.card',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'mdi:card-outline'
|
icon: 'mdi:card-outline'
|
||||||
}
|
}
|
||||||
@@ -136,7 +125,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '表格',
|
title: '表格',
|
||||||
i18nTitle: 'message.routes.component.table',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'mdi:table-large'
|
icon: 'mdi:table-large'
|
||||||
}
|
}
|
||||||
@@ -144,7 +132,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '组件示例',
|
title: '组件示例',
|
||||||
i18nTitle: 'message.routes.component._value',
|
|
||||||
icon: 'cib:app-store',
|
icon: 'cib:app-store',
|
||||||
order: 3
|
order: 3
|
||||||
}
|
}
|
||||||
@@ -165,7 +152,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'ECharts',
|
title: 'ECharts',
|
||||||
i18nTitle: 'message.routes.plugin.charts.echarts',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'simple-icons:apacheecharts'
|
icon: 'simple-icons:apacheecharts'
|
||||||
}
|
}
|
||||||
@@ -176,7 +162,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'AntV',
|
title: 'AntV',
|
||||||
i18nTitle: 'message.routes.plugin.charts.antv',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'simple-icons:antdesign'
|
icon: 'simple-icons:antdesign'
|
||||||
}
|
}
|
||||||
@@ -184,7 +169,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '图表',
|
title: '图表',
|
||||||
i18nTitle: 'message.routes.plugin.charts._value',
|
|
||||||
icon: 'mdi:chart-areaspline'
|
icon: 'mdi:chart-areaspline'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -194,7 +178,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '地图',
|
title: '地图',
|
||||||
i18nTitle: 'message.routes.plugin.map',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'mdi:map'
|
icon: 'mdi:map'
|
||||||
}
|
}
|
||||||
@@ -205,7 +188,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '视频',
|
title: '视频',
|
||||||
i18nTitle: 'message.routes.plugin.video',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'mdi:video'
|
icon: 'mdi:video'
|
||||||
}
|
}
|
||||||
@@ -221,7 +203,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '富文本编辑器',
|
title: '富文本编辑器',
|
||||||
i18nTitle: 'message.routes.plugin.editor.quill',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'mdi:file-document-edit-outline'
|
icon: 'mdi:file-document-edit-outline'
|
||||||
}
|
}
|
||||||
@@ -232,7 +213,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'markdown编辑器',
|
title: 'markdown编辑器',
|
||||||
i18nTitle: 'message.routes.plugin.editor.markdown',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'ri:markdown-line'
|
icon: 'ri:markdown-line'
|
||||||
}
|
}
|
||||||
@@ -240,7 +220,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '编辑器',
|
title: '编辑器',
|
||||||
i18nTitle: 'message.routes.plugin.editor._value',
|
|
||||||
icon: 'icon-park-outline:editor'
|
icon: 'icon-park-outline:editor'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -250,7 +229,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Swiper插件',
|
title: 'Swiper插件',
|
||||||
i18nTitle: 'message.routes.plugin.swiper',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'simple-icons:swiper'
|
icon: 'simple-icons:swiper'
|
||||||
}
|
}
|
||||||
@@ -261,7 +239,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '剪贴板',
|
title: '剪贴板',
|
||||||
i18nTitle: 'message.routes.plugin.copy',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'mdi:clipboard-outline'
|
icon: 'mdi:clipboard-outline'
|
||||||
}
|
}
|
||||||
@@ -272,7 +249,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '图标',
|
title: '图标',
|
||||||
i18nTitle: 'message.routes.plugin.icon',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
localIcon: 'custom-icon'
|
localIcon: 'custom-icon'
|
||||||
}
|
}
|
||||||
@@ -283,7 +259,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '打印',
|
title: '打印',
|
||||||
i18nTitle: 'message.routes.plugin.print',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'mdi:printer'
|
icon: 'mdi:printer'
|
||||||
}
|
}
|
||||||
@@ -291,7 +266,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '插件示例',
|
title: '插件示例',
|
||||||
i18nTitle: 'message.routes.plugin._value',
|
|
||||||
icon: 'clarity:plugin-line',
|
icon: 'clarity:plugin-line',
|
||||||
order: 4
|
order: 4
|
||||||
}
|
}
|
||||||
@@ -307,7 +281,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '权限切换',
|
title: '权限切换',
|
||||||
i18nTitle: 'message.routes.auth-demo.permission',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'ic:round-construction'
|
icon: 'ic:round-construction'
|
||||||
}
|
}
|
||||||
@@ -318,7 +291,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '超级管理员可见',
|
title: '超级管理员可见',
|
||||||
i18nTitle: 'message.routes.auth-demo.super',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'ic:round-supervisor-account'
|
icon: 'ic:round-supervisor-account'
|
||||||
}
|
}
|
||||||
@@ -326,7 +298,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '权限示例',
|
title: '权限示例',
|
||||||
i18nTitle: 'message.routes.auth-demo._value',
|
|
||||||
icon: 'ic:baseline-security',
|
icon: 'ic:baseline-security',
|
||||||
order: 5
|
order: 5
|
||||||
}
|
}
|
||||||
@@ -342,7 +313,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Tab',
|
title: 'Tab',
|
||||||
i18nTitle: 'message.routes.function.tab',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'ic:round-tab'
|
icon: 'ic:round-tab'
|
||||||
}
|
}
|
||||||
@@ -375,7 +345,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '功能',
|
title: '功能',
|
||||||
i18nTitle: 'message.routes.function._value',
|
|
||||||
icon: 'icon-park-outline:all-application',
|
icon: 'icon-park-outline:all-application',
|
||||||
order: 6
|
order: 6
|
||||||
}
|
}
|
||||||
@@ -391,7 +360,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '异常页403',
|
title: '异常页403',
|
||||||
i18nTitle: 'message.routes.exception.403',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'ic:baseline-block'
|
icon: 'ic:baseline-block'
|
||||||
}
|
}
|
||||||
@@ -402,7 +370,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '异常页404',
|
title: '异常页404',
|
||||||
i18nTitle: 'message.routes.exception.404',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'ic:baseline-web-asset-off'
|
icon: 'ic:baseline-web-asset-off'
|
||||||
}
|
}
|
||||||
@@ -413,14 +380,12 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '异常页500',
|
title: '异常页500',
|
||||||
i18nTitle: 'message.routes.exception.500',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'ic:baseline-wifi-off'
|
icon: 'ic:baseline-wifi-off'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
i18nTitle: 'message.routes.exception._value',
|
|
||||||
title: '异常页',
|
title: '异常页',
|
||||||
icon: 'ant-design:exception-outlined',
|
icon: 'ant-design:exception-outlined',
|
||||||
order: 7
|
order: 7
|
||||||
@@ -442,7 +407,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '二级菜单',
|
title: '二级菜单',
|
||||||
i18nTitle: 'message.routes.multi-menu.first.second',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'mdi:menu'
|
icon: 'mdi:menu'
|
||||||
}
|
}
|
||||||
@@ -458,7 +422,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '三级菜单',
|
title: '三级菜单',
|
||||||
i18nTitle: 'message.routes.multi-menu.first.second-new.third',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'mdi:menu'
|
icon: 'mdi:menu'
|
||||||
}
|
}
|
||||||
@@ -466,21 +429,18 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '二级菜单(有子菜单)',
|
title: '二级菜单(有子菜单)',
|
||||||
i18nTitle: 'message.routes.multi-menu.first.second-new._value',
|
|
||||||
icon: 'mdi:menu'
|
icon: 'mdi:menu'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '一级菜单',
|
title: '一级菜单',
|
||||||
i18nTitle: 'message.routes.multi-menu.first._value',
|
|
||||||
icon: 'mdi:menu'
|
icon: 'mdi:menu'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '多级菜单',
|
title: '多级菜单',
|
||||||
i18nTitle: 'message.routes.multi-menu._value',
|
|
||||||
icon: 'carbon:menu',
|
icon: 'carbon:menu',
|
||||||
order: 8
|
order: 8
|
||||||
}
|
}
|
||||||
@@ -496,7 +456,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '权限管理',
|
title: '权限管理',
|
||||||
i18nTitle: 'message.routes.management.auth',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'ic:baseline-security'
|
icon: 'ic:baseline-security'
|
||||||
}
|
}
|
||||||
@@ -507,7 +466,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '角色管理',
|
title: '角色管理',
|
||||||
i18nTitle: 'message.routes.management.role',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'carbon:user-role'
|
icon: 'carbon:user-role'
|
||||||
}
|
}
|
||||||
@@ -518,7 +476,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '用户管理',
|
title: '用户管理',
|
||||||
i18nTitle: 'message.routes.management.user',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'ic:round-manage-accounts'
|
icon: 'ic:round-manage-accounts'
|
||||||
}
|
}
|
||||||
@@ -529,7 +486,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '路由管理',
|
title: '路由管理',
|
||||||
i18nTitle: 'message.routes.management.route',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'material-symbols:route'
|
icon: 'material-symbols:route'
|
||||||
}
|
}
|
||||||
@@ -537,7 +493,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '系统管理',
|
title: '系统管理',
|
||||||
i18nTitle: 'message.routes.management._value',
|
|
||||||
icon: 'carbon:cloud-service-management',
|
icon: 'carbon:cloud-service-management',
|
||||||
order: 9
|
order: 9
|
||||||
}
|
}
|
||||||
@@ -548,9 +503,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '关于',
|
title: '关于',
|
||||||
i18nTitle: 'message.routes.about',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
keepAlive: true,
|
|
||||||
singleLayout: 'basic',
|
singleLayout: 'basic',
|
||||||
icon: 'fluent:book-information-24-regular',
|
icon: 'fluent:book-information-24-regular',
|
||||||
order: 10
|
order: 10
|
||||||
@@ -570,8 +523,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
meta: {
|
meta: {
|
||||||
title: '分析页',
|
title: '分析页',
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'icon-park-outline:analysis',
|
icon: 'icon-park-outline:analysis'
|
||||||
i18nTitle: 'message.routes.dashboard.analysis'
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -581,16 +533,14 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
meta: {
|
meta: {
|
||||||
title: '工作台',
|
title: '工作台',
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'icon-park-outline:workbench',
|
icon: 'icon-park-outline:workbench'
|
||||||
i18nTitle: 'message.routes.dashboard.workbench'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '仪表盘',
|
title: '仪表盘',
|
||||||
icon: 'mdi:monitor-dashboard',
|
icon: 'mdi:monitor-dashboard',
|
||||||
order: 1,
|
order: 1
|
||||||
i18nTitle: 'message.routes.dashboard._value'
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -604,7 +554,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'vue文档',
|
title: 'vue文档',
|
||||||
i18nTitle: 'message.routes.document.vue',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'logos:vue'
|
icon: 'logos:vue'
|
||||||
}
|
}
|
||||||
@@ -615,7 +564,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'vite文档',
|
title: 'vite文档',
|
||||||
i18nTitle: 'message.routes.document.vite',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'logos:vitejs'
|
icon: 'logos:vitejs'
|
||||||
}
|
}
|
||||||
@@ -626,7 +574,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'naive文档',
|
title: 'naive文档',
|
||||||
i18nTitle: 'message.routes.document.naive',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'logos:naiveui'
|
icon: 'logos:naiveui'
|
||||||
}
|
}
|
||||||
@@ -637,7 +584,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '项目文档',
|
title: '项目文档',
|
||||||
i18nTitle: 'message.routes.document.project',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
localIcon: 'logo'
|
localIcon: 'logo'
|
||||||
}
|
}
|
||||||
@@ -647,7 +593,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
path: '/document/project-link',
|
path: '/document/project-link',
|
||||||
meta: {
|
meta: {
|
||||||
title: '项目文档(外链)',
|
title: '项目文档(外链)',
|
||||||
i18nTitle: 'message.routes.document.project-link',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
localIcon: 'logo',
|
localIcon: 'logo',
|
||||||
href: 'https://docs.soybean.pro/'
|
href: 'https://docs.soybean.pro/'
|
||||||
@@ -656,7 +601,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '文档',
|
title: '文档',
|
||||||
i18nTitle: 'message.routes.document._value',
|
|
||||||
icon: 'mdi:file-document-multiple-outline',
|
icon: 'mdi:file-document-multiple-outline',
|
||||||
order: 2
|
order: 2
|
||||||
}
|
}
|
||||||
@@ -672,7 +616,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '按钮',
|
title: '按钮',
|
||||||
i18nTitle: 'message.routes.component.button',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'mdi:button-cursor'
|
icon: 'mdi:button-cursor'
|
||||||
}
|
}
|
||||||
@@ -683,7 +626,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '卡片',
|
title: '卡片',
|
||||||
i18nTitle: 'message.routes.component.card',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'mdi:card-outline'
|
icon: 'mdi:card-outline'
|
||||||
}
|
}
|
||||||
@@ -694,7 +636,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '表格',
|
title: '表格',
|
||||||
i18nTitle: 'message.routes.component.table',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'mdi:table-large'
|
icon: 'mdi:table-large'
|
||||||
}
|
}
|
||||||
@@ -702,7 +643,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '组件示例',
|
title: '组件示例',
|
||||||
i18nTitle: 'message.routes.component._value',
|
|
||||||
icon: 'cib:app-store',
|
icon: 'cib:app-store',
|
||||||
order: 3
|
order: 3
|
||||||
}
|
}
|
||||||
@@ -723,7 +663,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'ECharts',
|
title: 'ECharts',
|
||||||
i18nTitle: 'message.routes.plugin.charts.echarts',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'simple-icons:apacheecharts'
|
icon: 'simple-icons:apacheecharts'
|
||||||
}
|
}
|
||||||
@@ -734,7 +673,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'AntV',
|
title: 'AntV',
|
||||||
i18nTitle: 'message.routes.plugin.charts.antv',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'simple-icons:antdesign'
|
icon: 'simple-icons:antdesign'
|
||||||
}
|
}
|
||||||
@@ -742,7 +680,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '图表',
|
title: '图表',
|
||||||
i18nTitle: 'message.routes.plugin.charts._value',
|
|
||||||
icon: 'mdi:chart-areaspline'
|
icon: 'mdi:chart-areaspline'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -752,7 +689,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '地图',
|
title: '地图',
|
||||||
i18nTitle: 'message.routes.plugin.map',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'mdi:map'
|
icon: 'mdi:map'
|
||||||
}
|
}
|
||||||
@@ -763,7 +699,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '视频',
|
title: '视频',
|
||||||
i18nTitle: 'message.routes.plugin.video',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'mdi:video'
|
icon: 'mdi:video'
|
||||||
}
|
}
|
||||||
@@ -779,7 +714,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '富文本编辑器',
|
title: '富文本编辑器',
|
||||||
i18nTitle: 'message.routes.plugin.editor.quill',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'mdi:file-document-edit-outline'
|
icon: 'mdi:file-document-edit-outline'
|
||||||
}
|
}
|
||||||
@@ -790,7 +724,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'markdown编辑器',
|
title: 'markdown编辑器',
|
||||||
i18nTitle: 'message.routes.plugin.editor.markdown',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'ri:markdown-line'
|
icon: 'ri:markdown-line'
|
||||||
}
|
}
|
||||||
@@ -798,7 +731,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '编辑器',
|
title: '编辑器',
|
||||||
i18nTitle: 'message.routes.plugin.editor._value',
|
|
||||||
icon: 'icon-park-outline:editor'
|
icon: 'icon-park-outline:editor'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -808,7 +740,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Swiper插件',
|
title: 'Swiper插件',
|
||||||
i18nTitle: 'message.routes.plugin.swiper',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'simple-icons:swiper'
|
icon: 'simple-icons:swiper'
|
||||||
}
|
}
|
||||||
@@ -819,7 +750,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '剪贴板',
|
title: '剪贴板',
|
||||||
i18nTitle: 'message.routes.plugin.copy',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'mdi:clipboard-outline'
|
icon: 'mdi:clipboard-outline'
|
||||||
}
|
}
|
||||||
@@ -830,7 +760,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '图标',
|
title: '图标',
|
||||||
i18nTitle: 'message.routes.plugin.icon',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
localIcon: 'custom-icon'
|
localIcon: 'custom-icon'
|
||||||
}
|
}
|
||||||
@@ -841,7 +770,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '打印',
|
title: '打印',
|
||||||
i18nTitle: 'message.routes.plugin.print',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'mdi:printer'
|
icon: 'mdi:printer'
|
||||||
}
|
}
|
||||||
@@ -849,7 +777,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '插件示例',
|
title: '插件示例',
|
||||||
i18nTitle: 'message.routes.plugin._value',
|
|
||||||
icon: 'clarity:plugin-line',
|
icon: 'clarity:plugin-line',
|
||||||
order: 4
|
order: 4
|
||||||
}
|
}
|
||||||
@@ -865,26 +792,13 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '权限切换',
|
title: '权限切换',
|
||||||
i18nTitle: 'message.routes.auth-demo.permission',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'ic:round-construction'
|
icon: 'ic:round-construction'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'auth-demo_super',
|
|
||||||
path: '/auth-demo/super',
|
|
||||||
component: 'self',
|
|
||||||
meta: {
|
|
||||||
title: '超级管理员可见',
|
|
||||||
i18nTitle: 'message.routes.auth-demo.super',
|
|
||||||
requiresAuth: true,
|
|
||||||
icon: 'ic:round-supervisor-account'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '权限示例',
|
title: '权限示例',
|
||||||
i18nTitle: 'message.routes.auth-demo._value',
|
|
||||||
icon: 'ic:baseline-security',
|
icon: 'ic:baseline-security',
|
||||||
order: 5
|
order: 5
|
||||||
}
|
}
|
||||||
@@ -900,7 +814,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Tab',
|
title: 'Tab',
|
||||||
i18nTitle: 'message.routes.function.tab',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'ic:round-tab'
|
icon: 'ic:round-tab'
|
||||||
}
|
}
|
||||||
@@ -933,7 +846,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '功能',
|
title: '功能',
|
||||||
i18nTitle: 'message.routes.function._value',
|
|
||||||
icon: 'icon-park-outline:all-application',
|
icon: 'icon-park-outline:all-application',
|
||||||
order: 6
|
order: 6
|
||||||
}
|
}
|
||||||
@@ -949,7 +861,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '异常页403',
|
title: '异常页403',
|
||||||
i18nTitle: 'message.routes.exception.403',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'ic:baseline-block'
|
icon: 'ic:baseline-block'
|
||||||
}
|
}
|
||||||
@@ -960,7 +871,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '异常页404',
|
title: '异常页404',
|
||||||
i18nTitle: 'message.routes.exception.404',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'ic:baseline-web-asset-off'
|
icon: 'ic:baseline-web-asset-off'
|
||||||
}
|
}
|
||||||
@@ -971,14 +881,12 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '异常页500',
|
title: '异常页500',
|
||||||
i18nTitle: 'message.routes.exception.500',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'ic:baseline-wifi-off'
|
icon: 'ic:baseline-wifi-off'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
i18nTitle: 'message.routes.exception._value',
|
|
||||||
title: '异常页',
|
title: '异常页',
|
||||||
icon: 'ant-design:exception-outlined',
|
icon: 'ant-design:exception-outlined',
|
||||||
order: 7
|
order: 7
|
||||||
@@ -1000,7 +908,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '二级菜单',
|
title: '二级菜单',
|
||||||
i18nTitle: 'message.routes.multi-menu.first.second',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'mdi:menu'
|
icon: 'mdi:menu'
|
||||||
}
|
}
|
||||||
@@ -1016,7 +923,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '三级菜单',
|
title: '三级菜单',
|
||||||
i18nTitle: 'message.routes.multi-menu.first.second-new.third',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'mdi:menu'
|
icon: 'mdi:menu'
|
||||||
}
|
}
|
||||||
@@ -1024,21 +930,18 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '二级菜单(有子菜单)',
|
title: '二级菜单(有子菜单)',
|
||||||
i18nTitle: 'message.routes.multi-menu.first.second-new._value',
|
|
||||||
icon: 'mdi:menu'
|
icon: 'mdi:menu'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '一级菜单',
|
title: '一级菜单',
|
||||||
i18nTitle: 'message.routes.multi-menu.first._value',
|
|
||||||
icon: 'mdi:menu'
|
icon: 'mdi:menu'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '多级菜单',
|
title: '多级菜单',
|
||||||
i18nTitle: 'message.routes.multi-menu._value',
|
|
||||||
icon: 'carbon:menu',
|
icon: 'carbon:menu',
|
||||||
order: 8
|
order: 8
|
||||||
}
|
}
|
||||||
@@ -1054,7 +957,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '权限管理',
|
title: '权限管理',
|
||||||
i18nTitle: 'message.routes.management.auth',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'ic:baseline-security'
|
icon: 'ic:baseline-security'
|
||||||
}
|
}
|
||||||
@@ -1065,7 +967,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '角色管理',
|
title: '角色管理',
|
||||||
i18nTitle: 'message.routes.management.role',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'carbon:user-role'
|
icon: 'carbon:user-role'
|
||||||
}
|
}
|
||||||
@@ -1076,7 +977,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '用户管理',
|
title: '用户管理',
|
||||||
i18nTitle: 'message.routes.management.user',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'ic:round-manage-accounts'
|
icon: 'ic:round-manage-accounts'
|
||||||
}
|
}
|
||||||
@@ -1087,7 +987,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '路由管理',
|
title: '路由管理',
|
||||||
i18nTitle: 'message.routes.management.route',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'material-symbols:route'
|
icon: 'material-symbols:route'
|
||||||
}
|
}
|
||||||
@@ -1095,7 +994,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '系统管理',
|
title: '系统管理',
|
||||||
i18nTitle: 'message.routes.management._value',
|
|
||||||
icon: 'carbon:cloud-service-management',
|
icon: 'carbon:cloud-service-management',
|
||||||
order: 9
|
order: 9
|
||||||
}
|
}
|
||||||
@@ -1106,9 +1004,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '关于',
|
title: '关于',
|
||||||
i18nTitle: 'message.routes.about',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
keepAlive: true,
|
|
||||||
singleLayout: 'basic',
|
singleLayout: 'basic',
|
||||||
icon: 'fluent:book-information-24-regular',
|
icon: 'fluent:book-information-24-regular',
|
||||||
order: 10
|
order: 10
|
||||||
@@ -1128,27 +1024,14 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
meta: {
|
meta: {
|
||||||
title: '分析页',
|
title: '分析页',
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'icon-park-outline:analysis',
|
icon: 'icon-park-outline:analysis'
|
||||||
i18nTitle: 'message.routes.dashboard.analysis'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'dashboard_workbench',
|
|
||||||
path: '/dashboard/workbench',
|
|
||||||
component: 'self',
|
|
||||||
meta: {
|
|
||||||
title: '工作台',
|
|
||||||
requiresAuth: true,
|
|
||||||
icon: 'icon-park-outline:workbench',
|
|
||||||
i18nTitle: 'message.routes.dashboard.workbench'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '仪表盘',
|
title: '仪表盘',
|
||||||
icon: 'mdi:monitor-dashboard',
|
icon: 'mdi:monitor-dashboard',
|
||||||
order: 1,
|
order: 1
|
||||||
i18nTitle: 'message.routes.dashboard._value'
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1162,26 +1045,13 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '权限切换',
|
title: '权限切换',
|
||||||
i18nTitle: 'message.routes.auth-demo.permission',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'ic:round-construction'
|
icon: 'ic:round-construction'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'auth-demo_super',
|
|
||||||
path: '/auth-demo/super',
|
|
||||||
component: 'self',
|
|
||||||
meta: {
|
|
||||||
title: '超级管理员可见',
|
|
||||||
i18nTitle: 'message.routes.auth-demo.super',
|
|
||||||
requiresAuth: true,
|
|
||||||
icon: 'ic:round-supervisor-account'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '权限示例',
|
title: '权限示例',
|
||||||
i18nTitle: 'message.routes.auth-demo._value',
|
|
||||||
icon: 'ic:baseline-security',
|
icon: 'ic:baseline-security',
|
||||||
order: 5
|
order: 5
|
||||||
}
|
}
|
||||||
@@ -1202,7 +1072,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '二级菜单',
|
title: '二级菜单',
|
||||||
i18nTitle: 'message.routes.multi-menu.first.second',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'mdi:menu'
|
icon: 'mdi:menu'
|
||||||
}
|
}
|
||||||
@@ -1218,7 +1087,6 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '三级菜单',
|
title: '三级菜单',
|
||||||
i18nTitle: 'message.routes.multi-menu.first.second-new.third',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
icon: 'mdi:menu'
|
icon: 'mdi:menu'
|
||||||
}
|
}
|
||||||
@@ -1226,23 +1094,20 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '二级菜单(有子菜单)',
|
title: '二级菜单(有子菜单)',
|
||||||
i18nTitle: 'message.routes.multi-menu.first.second-new._value',
|
|
||||||
icon: 'mdi:menu'
|
icon: 'mdi:menu'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '一级菜单',
|
title: '一级菜单',
|
||||||
i18nTitle: 'message.routes.multi-menu.first._value',
|
|
||||||
icon: 'mdi:menu'
|
icon: 'mdi:menu'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
meta: {
|
meta: {
|
||||||
title: '多级菜单',
|
title: '多级菜单',
|
||||||
i18nTitle: 'message.routes.multi-menu._value',
|
|
||||||
icon: 'carbon:menu',
|
icon: 'carbon:menu',
|
||||||
order: 8
|
order: 7
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1251,12 +1116,10 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
|
|||||||
component: 'self',
|
component: 'self',
|
||||||
meta: {
|
meta: {
|
||||||
title: '关于',
|
title: '关于',
|
||||||
i18nTitle: 'message.routes.about',
|
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
keepAlive: true,
|
|
||||||
singleLayout: 'basic',
|
singleLayout: 'basic',
|
||||||
icon: 'fluent:book-information-24-regular',
|
icon: 'fluent:book-information-24-regular',
|
||||||
order: 10
|
order: 8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
140
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "soybean-admin",
|
"name": "soybean-admin",
|
||||||
"version": "0.10.3",
|
"version": "0.9.9",
|
||||||
"description": "A fresh and elegant admin template, based on Vue3、Vite3、TypeScript、NaiveUI and UnoCSS. 一个基于Vue3、Vite3、TypeScript、NaiveUI and UnoCSS的清新优雅的中后台模版。",
|
"description": "A fresh and elegant admin template, based on Vue3、Vite3、TypeScript、NaiveUI and UnoCSS. 一个基于Vue3、Vite3、TypeScript、NaiveUI and UnoCSS的清新优雅的中后台模版。",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Soybean",
|
"name": "Soybean",
|
||||||
@@ -38,88 +38,92 @@
|
|||||||
"dev": "cross-env VITE_SERVICE_ENV=dev vite",
|
"dev": "cross-env VITE_SERVICE_ENV=dev vite",
|
||||||
"dev:test": "cross-env VITE_SERVICE_ENV=test vite",
|
"dev:test": "cross-env VITE_SERVICE_ENV=test vite",
|
||||||
"dev:prod": "cross-env VITE_SERVICE_ENV=prod vite",
|
"dev:prod": "cross-env VITE_SERVICE_ENV=prod vite",
|
||||||
"dev:tauri": "pnpm tauri dev",
|
|
||||||
"build": "npm run typecheck && cross-env VITE_SERVICE_ENV=prod vite build",
|
"build": "npm run typecheck && cross-env VITE_SERVICE_ENV=prod vite build",
|
||||||
"build:dev": "npm run typecheck && cross-env VITE_SERVICE_ENV=dev vite build",
|
"build:dev": "npm run typecheck && cross-env VITE_SERVICE_ENV=dev vite build",
|
||||||
"build:test": "npm run typecheck && cross-env VITE_SERVICE_ENV=test vite build",
|
"build:test": "npm run typecheck && cross-env VITE_SERVICE_ENV=test vite build",
|
||||||
"build:vercel": "cross-env VITE_HASH_ROUTE=Y VITE_VERCEL=Y vite build",
|
"build:vercel": "cross-env VITE_HASH_ROUTE=Y VITE_VERCEL=Y vite build",
|
||||||
"build:tauri": "pnpm tauri build",
|
|
||||||
"tauri-icon": "pnpm tauri icon ./public/logo.png",
|
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"typecheck": "vue-tsc --noEmit --skipLibCheck",
|
"typecheck": "vue-tsc --noEmit --skipLibCheck",
|
||||||
"lint": "eslint . --fix",
|
"lint": "eslint . --fix --ext .js,.jsx,.mjs,.json,.ts,.tsx,.vue",
|
||||||
"format": "soy prettier-write",
|
"format": "soy prettier-format",
|
||||||
"commit": "soy git-commit",
|
"commit": "soy git-commit",
|
||||||
"cleanup": "soy cleanup",
|
"cleanup": "soy cleanup",
|
||||||
"update-pkg": "soy ncu",
|
"update-pkg": "soy update-pkg",
|
||||||
"release": "soy release",
|
|
||||||
"tsx": "tsx",
|
"tsx": "tsx",
|
||||||
"logo": "tsx ./scripts/logo.ts",
|
"logo": "tsx ./scripts/logo.ts",
|
||||||
"prepare": "soy init-simple-git-hooks"
|
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
|
||||||
|
"release": "standard-version",
|
||||||
|
"prepare": "soy init-git-hooks"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@antv/data-set": "0.11.8",
|
"@ant-design/icons-vue": "^6.1.0",
|
||||||
"@antv/g2": "4.2.10",
|
"@fast-crud/fast-crud": "^1.13.6",
|
||||||
"@better-scroll/core": "2.5.1",
|
"@fast-crud/fast-extends": "^1.13.6",
|
||||||
"@soybeanjs/vue-materials": "0.2.0",
|
"@fast-crud/ui-naive": "^1.13.6",
|
||||||
"@vueuse/core": "10.1.2",
|
"@fast-crud/ui-interface": "^1.13.6",
|
||||||
|
"@antv/data-set": "^0.11.8",
|
||||||
|
"@antv/g2": "^4.2.10",
|
||||||
|
"@better-scroll/core": "^2.5.1",
|
||||||
|
"@soybeanjs/vue-materials": "^0.1.9",
|
||||||
|
"@vueuse/core": "^10.1.2",
|
||||||
"axios": "1.4.0",
|
"axios": "1.4.0",
|
||||||
"clipboard": "2.0.11",
|
"clipboard": "^2.0.11",
|
||||||
"colord": "2.9.3",
|
"colord": "^2.9.3",
|
||||||
"crypto-js": "4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
"dayjs": "1.11.8",
|
"dayjs": "^1.11.7",
|
||||||
"echarts": "5.4.2",
|
"echarts": "^5.4.2",
|
||||||
"form-data": "4.0.0",
|
"form-data": "^4.0.0",
|
||||||
"lodash-es": "4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"naive-ui": "2.34.4",
|
"naive-ui": "2.34.4",
|
||||||
"pinia": "2.1.4",
|
"pinia": "^2.1.3",
|
||||||
"print-js": "1.6.0",
|
"print-js": "^1.6.0",
|
||||||
"qs": "6.11.2",
|
"qs": "^6.11.2",
|
||||||
"swiper": "9.4.1",
|
"swiper": "^9.3.2",
|
||||||
"ua-parser-js": "1.0.35",
|
"ua-parser-js": "^1.0.35",
|
||||||
"vditor": "3.9.3",
|
"vditor": "^3.9.2",
|
||||||
"vue": "3.3.4",
|
"vue": "3.3.4",
|
||||||
"vue-i18n": "9.2.2",
|
"vue-i18n": "^9.2.2",
|
||||||
"vue-router": "4.2.2",
|
"vue-router": "^4.2.1",
|
||||||
"vuedraggable": "4.1.0",
|
"vuedraggable": "^4.1.0",
|
||||||
"wangeditor": "4.7.15",
|
"wangeditor": "^4.7.15",
|
||||||
"xgplayer": "3.0.4"
|
"xgplayer": "^3.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@amap/amap-jsapi-types": "0.0.13",
|
"@amap/amap-jsapi-types": "^0.0.13",
|
||||||
"@iconify/json": "2.2.78",
|
"@iconify/json": "^2.2.67",
|
||||||
"@iconify/vue": "4.1.1",
|
"@iconify/vue": "^4.1.1",
|
||||||
"@soybeanjs/cli": "0.6.2",
|
"@soybeanjs/cli": "^0.1.9",
|
||||||
"@soybeanjs/vite-plugin-vue-page-route": "0.0.5",
|
"@soybeanjs/vite-plugin-vue-page-route": "^0.0.5",
|
||||||
"@tauri-apps/cli": "^1.3.1",
|
"@types/bmapgl": "^0.0.7",
|
||||||
"@types/bmapgl": "0.0.7",
|
"@types/crypto-js": "^4.1.1",
|
||||||
"@types/crypto-js": "4.1.1",
|
"@types/node": "20.2.1",
|
||||||
"@types/node": "20.3.1",
|
"@types/qs": "^6.9.7",
|
||||||
"@types/qs": "6.9.7",
|
"@types/ua-parser-js": "^0.7.36",
|
||||||
"@types/ua-parser-js": "0.7.36",
|
"@unocss/preset-uno": "^0.52.0",
|
||||||
"@unocss/preset-uno": "0.53.1",
|
"@unocss/transformer-directives": "^0.52.0",
|
||||||
"@unocss/transformer-directives": "0.53.1",
|
"@unocss/vite": "^0.52.0",
|
||||||
"@unocss/vite": "0.53.1",
|
"@vitejs/plugin-vue": "^4.2.3",
|
||||||
"@vitejs/plugin-vue": "4.2.3",
|
"@vitejs/plugin-vue-jsx": "^3.0.1",
|
||||||
"@vitejs/plugin-vue-jsx": "3.0.1",
|
"conventional-changelog": "^3.1.25",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"eslint": "8.42.0",
|
"eslint": "^8.41.0",
|
||||||
"eslint-config-soybeanjs": "0.4.9",
|
"eslint-config-soybeanjs": "^0.3.7",
|
||||||
"mockjs": "1.1.0",
|
"lint-staged": "13.2.2",
|
||||||
"rollup-plugin-visualizer": "5.9.2",
|
"mockjs": "^1.1.0",
|
||||||
"sass": "1.63.4",
|
"rollup-plugin-visualizer": "^5.9.0",
|
||||||
"simple-git-hooks": "2.8.1",
|
"sass": "^1.62.1",
|
||||||
"tsx": "3.12.7",
|
"simple-git-hooks": "^2.8.1",
|
||||||
"typescript": "5.1.3",
|
"standard-version": "^9.5.0",
|
||||||
"unplugin-icons": "0.16.3",
|
"tsx": "^3.12.7",
|
||||||
"unplugin-vue-components": "0.25.1",
|
"typescript": "5.0.4",
|
||||||
"vite": "4.3.9",
|
"unplugin-icons": "^0.16.1",
|
||||||
"vite-plugin-compression": "0.5.1",
|
"unplugin-vue-components": "0.24.1",
|
||||||
|
"vite": "^4.3.8",
|
||||||
|
"vite-plugin-compression": "^0.5.1",
|
||||||
"vite-plugin-mock": "2.9.8",
|
"vite-plugin-mock": "2.9.8",
|
||||||
"vite-plugin-progress": "0.0.7",
|
"vite-plugin-progress": "^0.0.7",
|
||||||
"vite-plugin-pwa": "0.16.4",
|
"vite-plugin-pwa": "^0.15.0",
|
||||||
"vite-plugin-svg-icons": "2.0.1",
|
"vite-plugin-svg-icons": "^2.0.1",
|
||||||
"vite-plugin-vue-devtools": "0.2.0",
|
|
||||||
"vue-tsc": "1.6.5"
|
"vue-tsc": "1.6.5"
|
||||||
},
|
},
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
@@ -129,9 +133,9 @@
|
|||||||
},
|
},
|
||||||
"simple-git-hooks": {
|
"simple-git-hooks": {
|
||||||
"commit-msg": "pnpm soy git-commit-verify",
|
"commit-msg": "pnpm soy git-commit-verify",
|
||||||
"pre-commit": "pnpm typecheck && pnpm lint"
|
"pre-commit": "pnpm typecheck && pnpm lint-staged"
|
||||||
},
|
},
|
||||||
"soybean": {
|
"lint-staged": {
|
||||||
"useSoybeanToken": true
|
"*.{js,jsx,mjs,json,ts,tsx,vue}": "eslint . --fix"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
7970
pnpm-lock.yaml
generated
3
src-tauri/.gitignore
vendored
@@ -1,3 +0,0 @@
|
|||||||
# Generated by Cargo
|
|
||||||
# will have compiled files and executables
|
|
||||||
/target/
|
|
4302
src-tauri/Cargo.lock
generated
@@ -1,28 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "app"
|
|
||||||
version = "0.1.0"
|
|
||||||
description = "A Tauri App"
|
|
||||||
authors = ["you"]
|
|
||||||
license = ""
|
|
||||||
repository = ""
|
|
||||||
default-run = "app"
|
|
||||||
edition = "2021"
|
|
||||||
rust-version = "1.57"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
tauri-build = { version = "1.1.1", features = [] }
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
serde_json = "1.0"
|
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
|
||||||
tauri = { version = "1.1.1", features = ["api-all"] }
|
|
||||||
|
|
||||||
[features]
|
|
||||||
# by default Tauri runs in production mode
|
|
||||||
# when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL
|
|
||||||
default = [ "custom-protocol" ]
|
|
||||||
# this feature is used for production builds where `devPath` points to the filesystem
|
|
||||||
# DO NOT remove this
|
|
||||||
custom-protocol = [ "tauri/custom-protocol" ]
|
|
@@ -1,3 +0,0 @@
|
|||||||
fn main() {
|
|
||||||
tauri_build::build()
|
|
||||||
}
|
|
Before Width: | Height: | Size: 9.0 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 42 KiB |
@@ -1,10 +0,0 @@
|
|||||||
#![cfg_attr(
|
|
||||||
all(not(debug_assertions), target_os = "windows"),
|
|
||||||
windows_subsystem = "windows"
|
|
||||||
)]
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
tauri::Builder::default()
|
|
||||||
.run(tauri::generate_context!())
|
|
||||||
.expect("error while running tauri application");
|
|
||||||
}
|
|
@@ -1,60 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
|
||||||
"build": {
|
|
||||||
"beforeBuildCommand": "npm run build",
|
|
||||||
"beforeDevCommand": "npm run dev",
|
|
||||||
"devPath": "http://localhost:3200",
|
|
||||||
"distDir": "../dist"
|
|
||||||
},
|
|
||||||
"package": {
|
|
||||||
"productName": "soybean-admin",
|
|
||||||
"version": "0.1.0"
|
|
||||||
},
|
|
||||||
"tauri": {
|
|
||||||
"allowlist": {
|
|
||||||
"all": true
|
|
||||||
},
|
|
||||||
"bundle": {
|
|
||||||
"active": true,
|
|
||||||
"category": "DeveloperTool",
|
|
||||||
"copyright": "",
|
|
||||||
"deb": {
|
|
||||||
"depends": []
|
|
||||||
},
|
|
||||||
"externalBin": [],
|
|
||||||
"icon": ["icons/32x32.png", "icons/128x128.png", "icons/128x128@2x.png", "icons/icon.icns", "icons/icon.ico"],
|
|
||||||
"identifier": "cn.soybeanjs.tauri-admin",
|
|
||||||
"longDescription": "",
|
|
||||||
"macOS": {
|
|
||||||
"entitlements": null,
|
|
||||||
"exceptionDomain": "",
|
|
||||||
"frameworks": [],
|
|
||||||
"providerShortName": null,
|
|
||||||
"signingIdentity": null
|
|
||||||
},
|
|
||||||
"resources": [],
|
|
||||||
"shortDescription": "",
|
|
||||||
"targets": "all",
|
|
||||||
"windows": {
|
|
||||||
"certificateThumbprint": null,
|
|
||||||
"digestAlgorithm": "sha256",
|
|
||||||
"timestampUrl": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"security": {
|
|
||||||
"csp": null
|
|
||||||
},
|
|
||||||
"updater": {
|
|
||||||
"active": false
|
|
||||||
},
|
|
||||||
"windows": [
|
|
||||||
{
|
|
||||||
"fullscreen": false,
|
|
||||||
"height": 800,
|
|
||||||
"resizable": true,
|
|
||||||
"title": "soybean-admin",
|
|
||||||
"width": 1000
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
16
src/App.vue
@@ -7,20 +7,34 @@
|
|||||||
class="h-full"
|
class="h-full"
|
||||||
>
|
>
|
||||||
<naive-provider>
|
<naive-provider>
|
||||||
<router-view />
|
<fs-ui-context>
|
||||||
|
<router-view />
|
||||||
|
</fs-ui-context>
|
||||||
</naive-provider>
|
</naive-provider>
|
||||||
</n-config-provider>
|
</n-config-provider>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { watch } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
import { dateZhCN, zhCN } from 'naive-ui';
|
import { dateZhCN, zhCN } from 'naive-ui';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
import { subscribeStore, useThemeStore } from '@/store';
|
import { subscribeStore, useThemeStore } from '@/store';
|
||||||
import { useGlobalEvents } from '@/composables';
|
import { useGlobalEvents } from '@/composables';
|
||||||
|
|
||||||
const theme = useThemeStore();
|
const theme = useThemeStore();
|
||||||
|
const { locale, t } = useI18n();
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
subscribeStore();
|
subscribeStore();
|
||||||
useGlobalEvents();
|
useGlobalEvents();
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => locale.value,
|
||||||
|
() => {
|
||||||
|
document.title = route.meta.i18nTitle ? t(route.meta.i18nTitle) : route.meta.title;
|
||||||
|
}
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
@@ -1,34 +1,14 @@
|
|||||||
import { effectScope, onScopeDispose, watch } from 'vue';
|
|
||||||
import { useRoute } from 'vue-router';
|
|
||||||
import { useEventListener } from '@vueuse/core';
|
import { useEventListener } from '@vueuse/core';
|
||||||
import { useI18n } from 'vue-i18n';
|
|
||||||
import { useTabStore, useThemeStore } from '@/store';
|
import { useTabStore, useThemeStore } from '@/store';
|
||||||
|
|
||||||
/** 全局事件 */
|
/** 全局事件 */
|
||||||
export function useGlobalEvents() {
|
export function useGlobalEvents() {
|
||||||
const theme = useThemeStore();
|
const theme = useThemeStore();
|
||||||
const tab = useTabStore();
|
const tab = useTabStore();
|
||||||
const route = useRoute();
|
|
||||||
const { locale, t } = useI18n();
|
|
||||||
const scope = effectScope();
|
|
||||||
|
|
||||||
/** 页面离开时缓存多页签数据 */
|
/** 页面离开时缓存多页签数据 */
|
||||||
useEventListener(window, 'beforeunload', () => {
|
useEventListener(window, 'beforeunload', () => {
|
||||||
theme.cacheThemeSettings();
|
theme.cacheThemeSettings();
|
||||||
tab.cacheTabRoutes();
|
tab.cacheTabRoutes();
|
||||||
});
|
});
|
||||||
|
|
||||||
scope.run(() => {
|
|
||||||
// 国际化切换时更新浏览器标签文本
|
|
||||||
watch(
|
|
||||||
() => locale.value,
|
|
||||||
() => {
|
|
||||||
document.title = route.meta.i18nTitle ? t(route.meta.i18nTitle) : route.meta.title;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
onScopeDispose(() => {
|
|
||||||
scope.stop();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { h } from 'vue';
|
import { h } from 'vue';
|
||||||
import SvgIcon from '@/components/custom/svg-icon.vue';
|
import SvgIcon from '~/src/components/custom/svg-icon.vue';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 图标渲染
|
* 图标渲染
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { computed, watch } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { breakpointsTailwind, useBreakpoints } from '@vueuse/core';
|
import { breakpointsTailwind, useBreakpoints } from '@vueuse/core';
|
||||||
import { useAppStore, useThemeStore } from '@/store';
|
import { useAppStore, useThemeStore } from '@/store';
|
||||||
|
|
||||||
@@ -63,16 +63,6 @@ export function useBasicLayout() {
|
|||||||
return w;
|
return w;
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
|
||||||
isMobile,
|
|
||||||
newValue => {
|
|
||||||
if (newValue) {
|
|
||||||
app.setSiderCollapse(true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ immediate: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
mode,
|
mode,
|
||||||
isMobile,
|
isMobile,
|
||||||
|
@@ -1,6 +0,0 @@
|
|||||||
export function transformObjectToOption<T extends object>(obj: T) {
|
|
||||||
return Object.entries(obj).map(([value, label]) => ({
|
|
||||||
value,
|
|
||||||
label
|
|
||||||
})) as Common.OptionWithKey<keyof T>[];
|
|
||||||
}
|
|
@@ -1,5 +1,3 @@
|
|||||||
import { transformObjectToOption } from './_shared';
|
|
||||||
|
|
||||||
export const loginModuleLabels: Record<UnionKey.LoginModule, string> = {
|
export const loginModuleLabels: Record<UnionKey.LoginModule, string> = {
|
||||||
'pwd-login': '账密登录',
|
'pwd-login': '账密登录',
|
||||||
'code-login': '手机验证码登录',
|
'code-login': '手机验证码登录',
|
||||||
@@ -13,14 +11,23 @@ export const userRoleLabels: Record<Auth.RoleType, string> = {
|
|||||||
admin: '管理员',
|
admin: '管理员',
|
||||||
user: '普通用户'
|
user: '普通用户'
|
||||||
};
|
};
|
||||||
export const userRoleOptions = transformObjectToOption(userRoleLabels);
|
|
||||||
|
export const userRoleOptions: Common.OptionWithKey<Auth.RoleType>[] = [
|
||||||
|
{ value: 'super', label: userRoleLabels.super },
|
||||||
|
{ value: 'admin', label: userRoleLabels.admin },
|
||||||
|
{ value: 'user', label: userRoleLabels.user }
|
||||||
|
];
|
||||||
|
|
||||||
/** 用户性别 */
|
/** 用户性别 */
|
||||||
export const genderLabels: Record<UserManagement.GenderKey, string> = {
|
export const genderLabels: Record<UserManagement.GenderKey, string> = {
|
||||||
0: '女',
|
0: '女',
|
||||||
1: '男'
|
1: '男'
|
||||||
};
|
};
|
||||||
export const genderOptions = transformObjectToOption(genderLabels);
|
|
||||||
|
export const genderOptions: Common.OptionWithKey<UserManagement.GenderKey>[] = [
|
||||||
|
{ value: '0', label: genderLabels['0'] },
|
||||||
|
{ value: '1', label: genderLabels['1'] }
|
||||||
|
];
|
||||||
|
|
||||||
/** 用户状态 */
|
/** 用户状态 */
|
||||||
export const userStatusLabels: Record<UserManagement.UserStatusKey, string> = {
|
export const userStatusLabels: Record<UserManagement.UserStatusKey, string> = {
|
||||||
@@ -29,4 +36,10 @@ export const userStatusLabels: Record<UserManagement.UserStatusKey, string> = {
|
|||||||
3: '冻结',
|
3: '冻结',
|
||||||
4: '软删除'
|
4: '软删除'
|
||||||
};
|
};
|
||||||
export const userStatusOptions = transformObjectToOption(userStatusLabels);
|
|
||||||
|
export const userStatusOptions: Common.OptionWithKey<UserManagement.UserStatusKey>[] = [
|
||||||
|
{ value: '1', label: userStatusLabels['1'] },
|
||||||
|
{ value: '2', label: userStatusLabels['2'] },
|
||||||
|
{ value: '3', label: userStatusLabels['3'] },
|
||||||
|
{ value: '4', label: userStatusLabels['4'] }
|
||||||
|
];
|
||||||
|
@@ -1,31 +1,81 @@
|
|||||||
import { transformObjectToOption } from './_shared';
|
|
||||||
|
|
||||||
export const themeLayoutModeLabels: Record<UnionKey.ThemeLayoutMode, string> = {
|
export const themeLayoutModeLabels: Record<UnionKey.ThemeLayoutMode, string> = {
|
||||||
vertical: '左侧菜单模式',
|
vertical: '左侧菜单模式',
|
||||||
horizontal: '顶部菜单模式',
|
horizontal: '顶部菜单模式',
|
||||||
'vertical-mix': '左侧菜单混合模式',
|
'vertical-mix': '左侧菜单混合模式',
|
||||||
'horizontal-mix': '顶部菜单混合模式'
|
'horizontal-mix': '顶部菜单混合模式'
|
||||||
};
|
};
|
||||||
export const themeLayoutModeOptions = transformObjectToOption(themeLayoutModeLabels);
|
|
||||||
|
export const themeLayoutModeOptions: Common.OptionWithKey<UnionKey.ThemeLayoutMode>[] = [
|
||||||
|
{
|
||||||
|
value: 'vertical',
|
||||||
|
label: themeLayoutModeLabels.vertical
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'horizontal',
|
||||||
|
label: themeLayoutModeLabels.horizontal
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'vertical-mix',
|
||||||
|
label: themeLayoutModeLabels['vertical-mix']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'horizontal-mix',
|
||||||
|
label: themeLayoutModeLabels['horizontal-mix']
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
export const themeScrollModeLabels: Record<UnionKey.ThemeScrollMode, string> = {
|
export const themeScrollModeLabels: Record<UnionKey.ThemeScrollMode, string> = {
|
||||||
wrapper: '外层滚动',
|
wrapper: '外层滚动',
|
||||||
content: '主体滚动'
|
content: '主体滚动'
|
||||||
};
|
};
|
||||||
export const themeScrollModeOptions = transformObjectToOption(themeScrollModeLabels);
|
|
||||||
|
export const themeScrollModeOptions: Common.OptionWithKey<UnionKey.ThemeScrollMode>[] = [
|
||||||
|
{
|
||||||
|
value: 'wrapper',
|
||||||
|
label: themeScrollModeLabels.wrapper
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'content',
|
||||||
|
label: themeScrollModeLabels.content
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
export const themeTabModeLabels: Record<UnionKey.ThemeTabMode, string> = {
|
export const themeTabModeLabels: Record<UnionKey.ThemeTabMode, string> = {
|
||||||
chrome: '谷歌风格',
|
chrome: '谷歌风格',
|
||||||
button: '按钮风格'
|
button: '按钮风格'
|
||||||
};
|
};
|
||||||
export const themeTabModeOptions = transformObjectToOption(themeTabModeLabels);
|
|
||||||
|
export const themeTabModeOptions: Common.OptionWithKey<UnionKey.ThemeTabMode>[] = [
|
||||||
|
{
|
||||||
|
value: 'chrome',
|
||||||
|
label: themeTabModeLabels.chrome
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'button',
|
||||||
|
label: themeTabModeLabels.button
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
export const themeHorizontalMenuPositionLabels: Record<UnionKey.ThemeHorizontalMenuPosition, string> = {
|
export const themeHorizontalMenuPositionLabels: Record<UnionKey.ThemeHorizontalMenuPosition, string> = {
|
||||||
'flex-start': '居左',
|
'flex-start': '居左',
|
||||||
center: '居中',
|
center: '居中',
|
||||||
'flex-end': '居右'
|
'flex-end': '居右'
|
||||||
};
|
};
|
||||||
export const themeHorizontalMenuPositionOptions = transformObjectToOption(themeHorizontalMenuPositionLabels);
|
|
||||||
|
export const themeHorizontalMenuPositionOptions: Common.OptionWithKey<UnionKey.ThemeHorizontalMenuPosition>[] = [
|
||||||
|
{
|
||||||
|
value: 'flex-start',
|
||||||
|
label: themeHorizontalMenuPositionLabels['flex-start']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'center',
|
||||||
|
label: themeHorizontalMenuPositionLabels.center
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'flex-end',
|
||||||
|
label: themeHorizontalMenuPositionLabels['flex-end']
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
export const themeAnimateModeLabels: Record<UnionKey.ThemeAnimateMode, string> = {
|
export const themeAnimateModeLabels: Record<UnionKey.ThemeAnimateMode, string> = {
|
||||||
'zoom-fade': '渐变',
|
'zoom-fade': '渐变',
|
||||||
@@ -35,4 +85,30 @@ export const themeAnimateModeLabels: Record<UnionKey.ThemeAnimateMode, string> =
|
|||||||
'fade-bottom': '底部消退',
|
'fade-bottom': '底部消退',
|
||||||
'fade-scale': '缩放消退'
|
'fade-scale': '缩放消退'
|
||||||
};
|
};
|
||||||
export const themeAnimateModeOptions = transformObjectToOption(themeAnimateModeLabels);
|
|
||||||
|
export const themeAnimateModeOptions: Common.OptionWithKey<UnionKey.ThemeAnimateMode>[] = [
|
||||||
|
{
|
||||||
|
value: 'zoom-fade',
|
||||||
|
label: themeAnimateModeLabels['zoom-fade']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'zoom-out',
|
||||||
|
label: themeAnimateModeLabels['zoom-out']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'fade-slide',
|
||||||
|
label: themeAnimateModeLabels['fade-slide']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'fade',
|
||||||
|
label: themeAnimateModeLabels.fade
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'fade-bottom',
|
||||||
|
label: themeAnimateModeLabels['fade-bottom']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'fade-scale',
|
||||||
|
label: themeAnimateModeLabels['fade-scale']
|
||||||
|
}
|
||||||
|
];
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<admin-layout
|
<admin-layout
|
||||||
:mode="mode"
|
:mode="mode"
|
||||||
:is-mobile="isMobile"
|
|
||||||
:scroll-mode="theme.scrollMode"
|
:scroll-mode="theme.scrollMode"
|
||||||
:scroll-el-id="app.scrollElId"
|
:scroll-el-id="app.scrollElId"
|
||||||
:full-content="app.contentFull"
|
:full-content="app.contentFull"
|
||||||
@@ -17,7 +16,6 @@
|
|||||||
:footer-visible="theme.footer.visible"
|
:footer-visible="theme.footer.visible"
|
||||||
:fixed-footer="theme.footer.fixed"
|
:fixed-footer="theme.footer.fixed"
|
||||||
:right-footer="theme.footer.right"
|
:right-footer="theme.footer.right"
|
||||||
@click-mobile-sider-mask="app.setSiderCollapse(true)"
|
|
||||||
>
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
<global-header v-bind="headerProps" />
|
<global-header v-bind="headerProps" />
|
||||||
@@ -48,7 +46,7 @@ defineOptions({ name: 'BasicLayout' });
|
|||||||
const app = useAppStore();
|
const app = useAppStore();
|
||||||
const theme = useThemeStore();
|
const theme = useThemeStore();
|
||||||
|
|
||||||
const { mode, isMobile, headerProps, siderVisible, siderWidth, siderCollapsedWidth } = useBasicLayout();
|
const { mode, headerProps, siderVisible, siderWidth, siderCollapsedWidth } = useBasicLayout();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
v-if="theme.header.crumb.showIcon"
|
v-if="theme.header.crumb.showIcon"
|
||||||
class="inline-block align-text-bottom mr-4px text-16px"
|
class="inline-block align-text-bottom mr-4px text-16px"
|
||||||
/>
|
/>
|
||||||
<span>{{ breadcrumb.label }}</span>
|
<span>{{ breadcrumb.i18nTitle ? t(breadcrumb.i18nTitle) : breadcrumb.label }}</span>
|
||||||
</span>
|
</span>
|
||||||
</n-dropdown>
|
</n-dropdown>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
@@ -19,9 +19,9 @@
|
|||||||
class="inline-block align-text-bottom mr-4px text-16px"
|
class="inline-block align-text-bottom mr-4px text-16px"
|
||||||
:class="{ 'text-#BBBBBB': theme.header.inverted }"
|
:class="{ 'text-#BBBBBB': theme.header.inverted }"
|
||||||
/>
|
/>
|
||||||
<span :class="{ 'text-#BBBBBB': theme.header.inverted }">
|
<span :class="{ 'text-#BBBBBB': theme.header.inverted }">{{
|
||||||
{{ breadcrumb.label }}
|
breadcrumb.i18nTitle ? t(breadcrumb.i18nTitle) : breadcrumb.label
|
||||||
</span>
|
}}</span>
|
||||||
</template>
|
</template>
|
||||||
</n-breadcrumb-item>
|
</n-breadcrumb-item>
|
||||||
</template>
|
</template>
|
||||||
@@ -45,13 +45,7 @@ const routeStore = useRouteStore();
|
|||||||
const { routerPush } = useRouterPush();
|
const { routerPush } = useRouterPush();
|
||||||
|
|
||||||
const breadcrumbs = computed(() =>
|
const breadcrumbs = computed(() =>
|
||||||
getBreadcrumbByRouteKey(route.name as string, routeStore.menus as App.GlobalMenuOption[], routePath('root')).map(
|
getBreadcrumbByRouteKey(route.name as string, routeStore.menus as App.GlobalMenuOption[], routePath('root'))
|
||||||
item => ({
|
|
||||||
...item,
|
|
||||||
label: item.i18nTitle ? t(item.i18nTitle) : item.label,
|
|
||||||
options: item.options?.map(oItem => ({ ...oItem, label: oItem.i18nTitle ? t(oItem.i18nTitle) : oItem.label }))
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
function dropdownSelect(key: string) {
|
function dropdownSelect(key: string) {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<hover-container class="w-40px h-full" :inverted="theme.header.inverted">
|
<hover-container class="w-40px h-full">
|
||||||
<n-dropdown :options="options" trigger="hover" :value="language" @select="handleSelect">
|
<n-dropdown :options="options" trigger="hover" :value="language" @select="handleSelect">
|
||||||
<icon-cil:language class="text-18px outline-transparent" />
|
<icon-cil:language class="text-18px outline-transparent" />
|
||||||
</n-dropdown>
|
</n-dropdown>
|
||||||
@@ -9,10 +9,8 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useThemeStore } from '@/store';
|
|
||||||
import { localStg } from '@/utils';
|
import { localStg } from '@/utils';
|
||||||
|
|
||||||
const theme = useThemeStore();
|
|
||||||
const { locale } = useI18n();
|
const { locale } = useI18n();
|
||||||
|
|
||||||
const language = ref<I18nType.langType>(localStg.get('lang') || 'zh-CN');
|
const language = ref<I18nType.langType>(localStg.get('lang') || 'zh-CN');
|
||||||
@@ -24,10 +22,6 @@ const options = [
|
|||||||
{
|
{
|
||||||
label: 'English',
|
label: 'English',
|
||||||
key: 'en'
|
key: 'en'
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'ភាសាខ្មែរ',
|
|
||||||
key: 'km-KH'
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
const handleSelect = (key: string) => {
|
const handleSelect = (key: string) => {
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
>
|
>
|
||||||
<component :is="icon" :class="[isMini ? 'text-16px' : 'text-20px']" />
|
<component :is="icon" :class="[isMini ? 'text-16px' : 'text-20px']" />
|
||||||
<p
|
<p
|
||||||
class="w-full text-center ellipsis-text text-12px transition-height duration-300 ease-in-out"
|
class="text-12px overflow-hidden transition-height duration-300 ease-in-out"
|
||||||
:class="[isMini ? 'h-0 pt-0' : 'h-24px pt-4px']"
|
:class="[isMini ? 'h-0 pt-0' : 'h-24px pt-4px']"
|
||||||
>
|
>
|
||||||
{{ label }}
|
{{ label }}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<dark-mode-container class="flex h-full" :inverted="theme.sider.inverted" @mouseleave="resetFirstDegreeMenus">
|
<dark-mode-container class="flex h-full" :inverted="theme.sider.inverted" @mouseleave="resetFirstDegreeMenus">
|
||||||
<div class="flex-1-hidden flex-col-stretch h-full">
|
<div class="flex-1 flex-col-stretch h-full">
|
||||||
<global-logo :show-title="false" :style="{ height: theme.header.height + 'px' }" />
|
<global-logo :show-title="false" :style="{ height: theme.header.height + 'px' }" />
|
||||||
<n-scrollbar class="flex-1-hidden">
|
<n-scrollbar class="flex-1-hidden">
|
||||||
<mix-menu-detail
|
<mix-menu-detail
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div ref="tabRef" class="flex h-full pr-18px" :class="[isChromeMode ? 'items-end' : 'items-center gap-12px']">
|
<div ref="tabRef" class="flex h-full pr-18px" :class="[isChromeMode ? 'items-end' : 'items-center gap-12px']">
|
||||||
<PageTab
|
<AdminTab
|
||||||
v-for="item in tab.tabs"
|
v-for="item in tab.tabs"
|
||||||
:key="item.fullPath"
|
:key="item.fullPath"
|
||||||
:mode="theme.tab.mode"
|
:mode="theme.tab.mode"
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
{{ item.meta.i18nTitle ? t(item.meta.i18nTitle) : item.meta.title }}
|
{{ item.meta.i18nTitle ? t(item.meta.i18nTitle) : item.meta.title }}
|
||||||
</PageTab>
|
</AdminTab>
|
||||||
</div>
|
</div>
|
||||||
<context-menu
|
<context-menu
|
||||||
:visible="dropdown.visible"
|
:visible="dropdown.visible"
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, nextTick, reactive, ref, watch } from 'vue';
|
import { computed, nextTick, reactive, ref, watch } from 'vue';
|
||||||
import { PageTab } from '@soybeanjs/vue-materials';
|
import { AdminTab } from '@soybeanjs/vue-materials';
|
||||||
import { useTabStore, useThemeStore } from '@/store';
|
import { useTabStore, useThemeStore } from '@/store';
|
||||||
import { t } from '@/locales';
|
import { t } from '@/locales';
|
||||||
import { ContextMenu } from './components';
|
import { ContextMenu } from './components';
|
||||||
|
@@ -7,7 +7,7 @@ const locale: LocaleMessages<I18nType.Schema> = {
|
|||||||
},
|
},
|
||||||
routes: {
|
routes: {
|
||||||
dashboard: {
|
dashboard: {
|
||||||
_value: 'Dashboard',
|
dashboard: 'Dashboard',
|
||||||
analysis: 'Analysis',
|
analysis: 'Analysis',
|
||||||
workbench: 'Workbench'
|
workbench: 'Workbench'
|
||||||
},
|
},
|
||||||
|
@@ -1,11 +1,9 @@
|
|||||||
import zhCN from './zh-cn';
|
import zhCN from './zh-cn';
|
||||||
import en from './en';
|
import en from './en';
|
||||||
import kmKH from './km-KH';
|
|
||||||
|
|
||||||
const locales = {
|
const locales = {
|
||||||
'zh-CN': zhCN,
|
'zh-CN': zhCN,
|
||||||
en,
|
en
|
||||||
'km-KH': kmKH
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type LocaleKey = keyof typeof locales;
|
export type LocaleKey = keyof typeof locales;
|
||||||
|
@@ -1,85 +0,0 @@
|
|||||||
import type { LocaleMessages } from 'vue-i18n';
|
|
||||||
|
|
||||||
const locale: LocaleMessages<I18nType.Schema> = {
|
|
||||||
message: {
|
|
||||||
system: {
|
|
||||||
title: 'ប្រព័ន្ធគ្រប់គ្រង'
|
|
||||||
},
|
|
||||||
routes: {
|
|
||||||
dashboard: {
|
|
||||||
_value: 'ផ្ទាំងទិន្នន័យ',
|
|
||||||
analysis: 'ផ្ទាំងវិភាគ',
|
|
||||||
workbench: 'ផ្ទាំងការងារ'
|
|
||||||
},
|
|
||||||
document: {
|
|
||||||
_value: 'ឯកសារ',
|
|
||||||
vue: 'ឯកសារ Vue',
|
|
||||||
vite: 'ឯកសារ Vite',
|
|
||||||
naive: 'ឯកសារ NaiveUI',
|
|
||||||
project: 'ឯកសារគម្រោង',
|
|
||||||
'project-link': 'ឯកសារគម្រោង(href)'
|
|
||||||
},
|
|
||||||
component: {
|
|
||||||
_value: 'សមាសភាគ',
|
|
||||||
button: 'ប៊ូតុង',
|
|
||||||
card: 'កាត',
|
|
||||||
table: 'តារាង'
|
|
||||||
},
|
|
||||||
plugin: {
|
|
||||||
_value: 'មុខងារជំនួយ',
|
|
||||||
charts: {
|
|
||||||
_value: 'តារាង Chart',
|
|
||||||
echarts: 'តារាង ECharts',
|
|
||||||
antv: 'AntV'
|
|
||||||
},
|
|
||||||
copy: 'ចម្លង',
|
|
||||||
editor: {
|
|
||||||
_value: 'កែប្រែ',
|
|
||||||
quill: 'Quill',
|
|
||||||
markdown: 'Markdown'
|
|
||||||
},
|
|
||||||
icon: 'អាយខន',
|
|
||||||
map: 'ផែនទី',
|
|
||||||
print: 'បោះពុម្ភ',
|
|
||||||
swiper: 'Swiper',
|
|
||||||
video: 'វីដេអូ'
|
|
||||||
},
|
|
||||||
'auth-demo': {
|
|
||||||
_value: 'ឌីមូ Auth',
|
|
||||||
permission: 'បិទ/បើកការអនុញ្ញាត',
|
|
||||||
super: 'Super Auth'
|
|
||||||
},
|
|
||||||
function: {
|
|
||||||
_value: 'មុខងារ',
|
|
||||||
tab: 'ថេបប្រព័ន្ធ'
|
|
||||||
},
|
|
||||||
exception: {
|
|
||||||
_value: 'ករណីពិេសស',
|
|
||||||
403: '403',
|
|
||||||
404: '404',
|
|
||||||
500: '500'
|
|
||||||
},
|
|
||||||
'multi-menu': {
|
|
||||||
_value: 'ម៉ឺនុយពហុដឺក្រេ',
|
|
||||||
first: {
|
|
||||||
_value: 'ដឺក្រេទី១',
|
|
||||||
second: 'ដែក្រេទី២',
|
|
||||||
'second-new': {
|
|
||||||
_value: 'ដឺក្រេទី២មានអនុក្រោម',
|
|
||||||
third: 'ដឺក្រេទី៣'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
management: {
|
|
||||||
_value: 'ការគ្រប់គ្រងប្រព័ន្ធ',
|
|
||||||
auth: 'Auth',
|
|
||||||
role: 'សិទ្ធី',
|
|
||||||
route: 'ផ្លូវប្រព័ន្ធ',
|
|
||||||
user: 'អ្នកប្រើប្រាស់'
|
|
||||||
},
|
|
||||||
about: 'អំពីប្រព័ន្ធ'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default locale;
|
|
@@ -7,7 +7,7 @@ const locale: LocaleMessages<I18nType.Schema> = {
|
|||||||
},
|
},
|
||||||
routes: {
|
routes: {
|
||||||
dashboard: {
|
dashboard: {
|
||||||
_value: '仪表盘',
|
dashboard: '仪表盘',
|
||||||
analysis: '分析页',
|
analysis: '分析页',
|
||||||
workbench: '工作台'
|
workbench: '工作台'
|
||||||
},
|
},
|
||||||
|
@@ -3,7 +3,7 @@ import App from './App.vue';
|
|||||||
import AppLoading from './components/common/app-loading.vue';
|
import AppLoading from './components/common/app-loading.vue';
|
||||||
import { setupDirectives } from './directives';
|
import { setupDirectives } from './directives';
|
||||||
import { setupRouter } from './router';
|
import { setupRouter } from './router';
|
||||||
import { setupAssets } from './plugins';
|
import { setupAssets, setupFastCrud } from './plugins';
|
||||||
import { setupStore } from './store';
|
import { setupStore } from './store';
|
||||||
import { setupI18n } from './locales';
|
import { setupI18n } from './locales';
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ async function setupApp() {
|
|||||||
|
|
||||||
setupI18n(app);
|
setupI18n(app);
|
||||||
|
|
||||||
appLoading.unmount();
|
setupFastCrud(app);
|
||||||
|
|
||||||
// mount app
|
// mount app
|
||||||
app.mount('#app');
|
app.mount('#app');
|
||||||
|
11
src/plugins/fast-crud/common.scss
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
html:root {
|
||||||
|
--baseColor: #fff;
|
||||||
|
}
|
||||||
|
/* 深色模式 */
|
||||||
|
html.dark:root {
|
||||||
|
--baseColor: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fs-container {
|
||||||
|
background-color: var(--baseColor);
|
||||||
|
}
|
171
src/plugins/fast-crud/index.tsx
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
import type { App } from 'vue';
|
||||||
|
import type { FsSetupOptions, PageQuery } from '@fast-crud/fast-crud';
|
||||||
|
// eslint-disable-next-line import/order
|
||||||
|
import { FastCrud } from '@fast-crud/fast-crud';
|
||||||
|
import '@fast-crud/fast-crud/dist/style.css';
|
||||||
|
import './common.scss';
|
||||||
|
|
||||||
|
import type { FsUploaderOptions } from '@fast-crud/fast-extends';
|
||||||
|
import {
|
||||||
|
FsExtendsCopyable,
|
||||||
|
FsExtendsEditor,
|
||||||
|
FsExtendsJson,
|
||||||
|
FsExtendsTime,
|
||||||
|
FsExtendsUploader
|
||||||
|
} from '@fast-crud/fast-extends';
|
||||||
|
import '@fast-crud/fast-extends/dist/style.css';
|
||||||
|
import UiNaive from '@fast-crud/ui-naive';
|
||||||
|
import axios from 'axios';
|
||||||
|
import type { VueI18n } from 'vue-i18n';
|
||||||
|
import { mockRequest, request } from '@/service/request';
|
||||||
|
import { setupNaive } from '@/plugins/fast-crud/naive';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fast-crud的安装方法
|
||||||
|
* 注意:在App.vue中,需要用fs-ui-context组件包裹RouterView,让fs-crud拥有message、notification、dialog的能力
|
||||||
|
* @param app
|
||||||
|
* @param options
|
||||||
|
*/
|
||||||
|
export type FsSetupOpts = {
|
||||||
|
i18n?: VueI18n;
|
||||||
|
};
|
||||||
|
function install(app: App, options: FsSetupOpts = {}) {
|
||||||
|
// 安装naive ui 常用组件
|
||||||
|
setupNaive(app);
|
||||||
|
app.use(UiNaive);
|
||||||
|
app.use(FastCrud, {
|
||||||
|
i18n: options.i18n,
|
||||||
|
async dictRequest(context: { url: string }) {
|
||||||
|
const url = context.url;
|
||||||
|
let res: Service.SuccessResult | Service.FailedResult;
|
||||||
|
if (url && url.startsWith('/mock')) {
|
||||||
|
// 如果是crud开头的dict请求视为mock
|
||||||
|
res = await mockRequest.get(url.replace('/mock', ''));
|
||||||
|
} else {
|
||||||
|
res = await request.get(url);
|
||||||
|
}
|
||||||
|
res = res || {};
|
||||||
|
return res.data || [];
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* useCrud时会被执行
|
||||||
|
*/
|
||||||
|
commonOptions() {
|
||||||
|
return {
|
||||||
|
table: {
|
||||||
|
size: 'small',
|
||||||
|
pagination: false
|
||||||
|
},
|
||||||
|
search: {
|
||||||
|
options: {
|
||||||
|
size: 'medium'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rowHandle: {
|
||||||
|
buttons: {
|
||||||
|
view: { text: null, icon: 'EyeOutlined', size: 'small' },
|
||||||
|
edit: { text: null, icon: 'EditOutlined', size: 'small' },
|
||||||
|
remove: { type: 'error', text: null, icon: 'DeleteOutlined', size: 'small' }
|
||||||
|
},
|
||||||
|
dropdown: {
|
||||||
|
more: { size: 'small' }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
request: {
|
||||||
|
// 查询参数转换
|
||||||
|
transformQuery: (query: PageQuery) => {
|
||||||
|
const { page, form, sort } = query;
|
||||||
|
const limit = page.pageSize;
|
||||||
|
const currentPage = page.currentPage ?? 1;
|
||||||
|
const offset = limit * (currentPage - 1);
|
||||||
|
|
||||||
|
return {
|
||||||
|
page: {
|
||||||
|
limit,
|
||||||
|
offset
|
||||||
|
},
|
||||||
|
query: form,
|
||||||
|
sort: sort || {}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
// page请求结果转换
|
||||||
|
transformRes: originPageRes => {
|
||||||
|
const { res } = originPageRes;
|
||||||
|
const pageSize = res.limit;
|
||||||
|
let currentPage = res.offset / pageSize;
|
||||||
|
if (res.offset % pageSize === 0) {
|
||||||
|
currentPage += 1;
|
||||||
|
}
|
||||||
|
return { currentPage, pageSize, ...res };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
display: 'flex', // 表单布局
|
||||||
|
labelWidth: '120px' // 表单label宽度
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 从 useCrud({permission}) 里获取permission参数,去设置各个按钮的权限
|
||||||
|
// const crudPermission = useCrudPermission(context);
|
||||||
|
// return crudPermission.merge(opts);
|
||||||
|
}
|
||||||
|
} as FsSetupOptions);
|
||||||
|
|
||||||
|
// fast-extends里面的扩展组件均为异步组件,只有在使用时才会被加载,并不会影响首页加载速度
|
||||||
|
// 安装editor
|
||||||
|
app.use(FsExtendsEditor, {
|
||||||
|
// 编辑器的公共配置
|
||||||
|
wangEditor: {}
|
||||||
|
});
|
||||||
|
app.use(FsExtendsJson);
|
||||||
|
app.use(FsExtendsCopyable);
|
||||||
|
// 安装uploader 公共参数
|
||||||
|
const uploaderOptions: FsUploaderOptions = {
|
||||||
|
defaultType: 'form',
|
||||||
|
form: {
|
||||||
|
action: 'http://www.docmirror.cn:7070/api/upload/form/upload',
|
||||||
|
name: 'file',
|
||||||
|
withCredentials: false,
|
||||||
|
uploadRequest: async props => {
|
||||||
|
const { action, file, onProgress } = props;
|
||||||
|
const data = new FormData();
|
||||||
|
data.append('file', file);
|
||||||
|
const res = await axios.post(action, data, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data'
|
||||||
|
},
|
||||||
|
timeout: 60000,
|
||||||
|
onUploadProgress(progress) {
|
||||||
|
onProgress({ percent: Math.round((progress.loaded / progress.total!) * 100) });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 上传完成后的结果,一般返回个url 或者key,具体看你的后台返回啥
|
||||||
|
return res.data.data;
|
||||||
|
},
|
||||||
|
async successHandle(ret: string) {
|
||||||
|
// 上传完成后的结果处理, 此处应转换格式为{url:xxx,key:xxx}
|
||||||
|
return {
|
||||||
|
url: `http://www.docmirror.cn:7070${ret}`,
|
||||||
|
key: ret.replace('/api/upload/form/download?key=', '')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
app.use(FsExtendsUploader, uploaderOptions);
|
||||||
|
|
||||||
|
// 安装editor
|
||||||
|
app.use(FsExtendsEditor, {
|
||||||
|
// 编辑器的公共配置
|
||||||
|
wangEditor: {}
|
||||||
|
});
|
||||||
|
app.use(FsExtendsJson);
|
||||||
|
app.use(FsExtendsTime);
|
||||||
|
app.use(FsExtendsCopyable);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
install
|
||||||
|
};
|
||||||
|
|
||||||
|
export function setupFastCrud(app: App<Element>, options: FsSetupOpts = {}) {
|
||||||
|
install(app, options);
|
||||||
|
}
|
59
src/plugins/fast-crud/naive.ts
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import type { App } from 'vue';
|
||||||
|
import * as NaiveUI from 'naive-ui';
|
||||||
|
|
||||||
|
const naive = NaiveUI.create({
|
||||||
|
components: [
|
||||||
|
NaiveUI.NInput,
|
||||||
|
NaiveUI.NButton,
|
||||||
|
NaiveUI.NForm,
|
||||||
|
NaiveUI.NFormItem,
|
||||||
|
NaiveUI.NCheckboxGroup,
|
||||||
|
NaiveUI.NCheckbox,
|
||||||
|
NaiveUI.NIcon,
|
||||||
|
NaiveUI.NDropdown,
|
||||||
|
NaiveUI.NTooltip,
|
||||||
|
NaiveUI.NTabs,
|
||||||
|
NaiveUI.NTabPane,
|
||||||
|
NaiveUI.NCard,
|
||||||
|
NaiveUI.NRow,
|
||||||
|
NaiveUI.NCol,
|
||||||
|
NaiveUI.NDrawer,
|
||||||
|
NaiveUI.NDrawerContent,
|
||||||
|
NaiveUI.NDivider,
|
||||||
|
NaiveUI.NSwitch,
|
||||||
|
NaiveUI.NBadge,
|
||||||
|
NaiveUI.NAlert,
|
||||||
|
NaiveUI.NTag,
|
||||||
|
NaiveUI.NProgress,
|
||||||
|
NaiveUI.NDatePicker,
|
||||||
|
NaiveUI.NGrid,
|
||||||
|
NaiveUI.NGridItem,
|
||||||
|
NaiveUI.NDataTable,
|
||||||
|
NaiveUI.NPagination,
|
||||||
|
NaiveUI.NSelect,
|
||||||
|
NaiveUI.NRadioGroup,
|
||||||
|
NaiveUI.NRadio,
|
||||||
|
NaiveUI.NInputGroup,
|
||||||
|
NaiveUI.NTable,
|
||||||
|
NaiveUI.NInputNumber,
|
||||||
|
NaiveUI.NLoadingBarProvider,
|
||||||
|
NaiveUI.NModal,
|
||||||
|
NaiveUI.NUpload,
|
||||||
|
NaiveUI.NTree,
|
||||||
|
NaiveUI.NSpin,
|
||||||
|
NaiveUI.NTimePicker,
|
||||||
|
|
||||||
|
// add by fs
|
||||||
|
NaiveUI.NCascader,
|
||||||
|
NaiveUI.NRadioButton,
|
||||||
|
NaiveUI.NTreeSelect,
|
||||||
|
NaiveUI.NImageGroup,
|
||||||
|
NaiveUI.NImage,
|
||||||
|
NaiveUI.NCollapse,
|
||||||
|
NaiveUI.NCollapseItem
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
export function setupNaive(app: App<Element>) {
|
||||||
|
app.use(naive);
|
||||||
|
}
|
@@ -1,3 +1,5 @@
|
|||||||
|
import { setupFastCrud } from '@/plugins/fast-crud';
|
||||||
import setupAssets from './assets';
|
import setupAssets from './assets';
|
||||||
|
|
||||||
|
export { setupFastCrud };
|
||||||
export { setupAssets };
|
export { setupAssets };
|
||||||
|
45
src/router/modules/crud.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
const component: any = {
|
||||||
|
name: 'crud',
|
||||||
|
path: '/crud',
|
||||||
|
component: 'basic',
|
||||||
|
meta: {
|
||||||
|
title: 'CRUD示例',
|
||||||
|
requiresAuth: true,
|
||||||
|
icon: 'mdi:table-large',
|
||||||
|
order: 4
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'crud_demo',
|
||||||
|
path: '/crud/demo',
|
||||||
|
component: 'self',
|
||||||
|
meta: {
|
||||||
|
title: '基本示例',
|
||||||
|
requiresAuth: true,
|
||||||
|
icon: 'mdi:button-cursor'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'crud_header_group',
|
||||||
|
path: '/crud/header_group',
|
||||||
|
component: 'self',
|
||||||
|
meta: {
|
||||||
|
title: '多级表头',
|
||||||
|
requiresAuth: true,
|
||||||
|
icon: 'mdi:button-cursor'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'crud_doc',
|
||||||
|
path: '/crud/doc',
|
||||||
|
component: 'self',
|
||||||
|
meta: {
|
||||||
|
title: 'FastCrud文档',
|
||||||
|
requiresAuth: true,
|
||||||
|
icon: 'logos:vue'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
export default component;
|
@@ -30,7 +30,7 @@ const dashboard: AuthRoute.Route = {
|
|||||||
title: '仪表盘',
|
title: '仪表盘',
|
||||||
icon: 'mdi:monitor-dashboard',
|
icon: 'mdi:monitor-dashboard',
|
||||||
order: 1,
|
order: 1,
|
||||||
i18nTitle: 'message.routes.dashboard._value'
|
i18nTitle: 'message.routes.dashboard.dashboard'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { nextTick } from 'vue';
|
import { nextTick } from 'vue';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { LAYOUT_SCROLL_EL_ID } from '@soybeanjs/vue-materials';
|
import { SCROLL_EL_ID } from '@soybeanjs/vue-materials';
|
||||||
|
|
||||||
interface AppState {
|
interface AppState {
|
||||||
/** 滚动元素的id */
|
/** 滚动元素的id */
|
||||||
@@ -21,7 +21,7 @@ interface AppState {
|
|||||||
|
|
||||||
export const useAppStore = defineStore('app-store', {
|
export const useAppStore = defineStore('app-store', {
|
||||||
state: (): AppState => ({
|
state: (): AppState => ({
|
||||||
scrollElId: LAYOUT_SCROLL_EL_ID,
|
scrollElId: SCROLL_EL_ID,
|
||||||
contentFull: false,
|
contentFull: false,
|
||||||
disableMainXScroll: false,
|
disableMainXScroll: false,
|
||||||
reloadFlag: true,
|
reloadFlag: true,
|
||||||
|
2
src/typings/env.d.ts
vendored
@@ -66,8 +66,6 @@ interface ImportMetaEnv {
|
|||||||
readonly VITE_PROD_MOCK?: 'Y' | 'N';
|
readonly VITE_PROD_MOCK?: 'Y' | 'N';
|
||||||
/** hash路由模式 */
|
/** hash路由模式 */
|
||||||
readonly VITE_HASH_ROUTE?: 'Y' | 'N';
|
readonly VITE_HASH_ROUTE?: 'Y' | 'N';
|
||||||
/** 是否应用自动生成路由的插件 */
|
|
||||||
readonly VITE_SOYBEAN_ROUTE_PLUGIN?: 'Y' | 'N';
|
|
||||||
/** 是否是部署的vercel */
|
/** 是否是部署的vercel */
|
||||||
readonly VITE_VERCEL?: 'Y' | 'N';
|
readonly VITE_VERCEL?: 'Y' | 'N';
|
||||||
}
|
}
|
||||||
|
6
src/typings/package.d.ts
vendored
@@ -7,3 +7,9 @@ declare namespace BMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
declare const TMap: any;
|
declare const TMap: any;
|
||||||
|
|
||||||
|
declare module 'unplugin-vue-define-options/vite' {
|
||||||
|
const plugin: (options?: import('unplugin-vue-define-options/dist/unplugin.d-59ddef99').B) => import('vite').Plugin;
|
||||||
|
|
||||||
|
export default plugin;
|
||||||
|
}
|
||||||
|
10
src/typings/page-route.d.ts
vendored
@@ -30,6 +30,12 @@ declare namespace PageRoute {
|
|||||||
| 'component_button'
|
| 'component_button'
|
||||||
| 'component_card'
|
| 'component_card'
|
||||||
| 'component_table'
|
| 'component_table'
|
||||||
|
| 'crud'
|
||||||
|
| 'crud_demo'
|
||||||
|
| 'crud_doc'
|
||||||
|
| 'crud_header'
|
||||||
|
| 'crud_header_group'
|
||||||
|
| 'crud_source'
|
||||||
| 'dashboard'
|
| 'dashboard'
|
||||||
| 'dashboard_analysis'
|
| 'dashboard_analysis'
|
||||||
| 'dashboard_workbench'
|
| 'dashboard_workbench'
|
||||||
@@ -89,6 +95,10 @@ declare namespace PageRoute {
|
|||||||
| 'component_button'
|
| 'component_button'
|
||||||
| 'component_card'
|
| 'component_card'
|
||||||
| 'component_table'
|
| 'component_table'
|
||||||
|
| 'crud_demo'
|
||||||
|
| 'crud_doc'
|
||||||
|
| 'crud_header_group'
|
||||||
|
| 'crud_source'
|
||||||
| 'dashboard_analysis'
|
| 'dashboard_analysis'
|
||||||
| 'dashboard_workbench'
|
| 'dashboard_workbench'
|
||||||
| 'document_naive'
|
| 'document_naive'
|
||||||
|
6
src/typings/system.d.ts
vendored
@@ -254,7 +254,7 @@ declare namespace App {
|
|||||||
hasChildren: boolean;
|
hasChildren: boolean;
|
||||||
icon?: import('vue').Component;
|
icon?: import('vue').Component;
|
||||||
i18nTitle?: string;
|
i18nTitle?: string;
|
||||||
options?: (import('naive-ui/es/dropdown/src/interface').DropdownMixedOption & { i18nTitle?: string })[];
|
options?: import('naive-ui/es/dropdown/src/interface').DropdownMixedOption[];
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 多页签Tab的路由 */
|
/** 多页签Tab的路由 */
|
||||||
@@ -302,7 +302,7 @@ declare namespace App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
declare namespace I18nType {
|
declare namespace I18nType {
|
||||||
type langType = 'en' | 'zh-CN' | 'km-KH';
|
type langType = 'en' | 'zh-CN';
|
||||||
|
|
||||||
interface Schema {
|
interface Schema {
|
||||||
system: {
|
system: {
|
||||||
@@ -310,7 +310,7 @@ declare namespace I18nType {
|
|||||||
};
|
};
|
||||||
routes: {
|
routes: {
|
||||||
dashboard: {
|
dashboard: {
|
||||||
_value: string;
|
dashboard: string;
|
||||||
analysis: string;
|
analysis: string;
|
||||||
workbench: string;
|
workbench: string;
|
||||||
};
|
};
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="h-full">
|
<div class="h-full">
|
||||||
<n-card title="当前页面只有super才能看到" class="h-full shadow-sm rounded-16px"></n-card>
|
<n-card title="当前页面只有super才能看到" class="h-full shadow-sm rounded-16px"> </n-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
43
src/views/crud/demo/api.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import type { UserPageQuery } from '@fast-crud/fast-crud';
|
||||||
|
import { mockRequest } from '@/service/request';
|
||||||
|
|
||||||
|
const request = mockRequest;
|
||||||
|
const apiPrefix = '/crud/demo';
|
||||||
|
|
||||||
|
export type DemoRecord = {
|
||||||
|
id: number;
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
function resHandle(res: any) {
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
export async function GetList(query: UserPageQuery) {
|
||||||
|
const res = await request.post(`${apiPrefix}/page`, query);
|
||||||
|
return resHandle(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function AddObj(obj: DemoRecord) {
|
||||||
|
const res = await request.post(`${apiPrefix}/add`, obj);
|
||||||
|
return resHandle(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function UpdateObj(obj: DemoRecord) {
|
||||||
|
const res = await request.post(`${apiPrefix}/update`, obj);
|
||||||
|
return resHandle(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function DelObj(id: number) {
|
||||||
|
const res = await request.post(`${apiPrefix}/delete`, { id });
|
||||||
|
return resHandle(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GetObj(id: number) {
|
||||||
|
const res = await request.get(`${apiPrefix}/info`, { params: { id } });
|
||||||
|
return resHandle(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function BatchDelete(ids: number[]) {
|
||||||
|
const res = await request.post(`${apiPrefix}/batchDelete`, { ids });
|
||||||
|
return resHandle(res);
|
||||||
|
}
|
114
src/views/crud/demo/crud.tsx
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
import type { AddReq, CreateCrudOptionsRet, DelReq, EditReq, UserPageQuery, UserPageRes } from '@fast-crud/fast-crud';
|
||||||
|
import { dict } from '@fast-crud/fast-crud';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import * as api from './api';
|
||||||
|
|
||||||
|
export default function createCrudOptions(): CreateCrudOptionsRet {
|
||||||
|
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
||||||
|
return api.GetList(query);
|
||||||
|
};
|
||||||
|
const editRequest = async (ctx: EditReq) => {
|
||||||
|
const { form, row } = ctx;
|
||||||
|
form.id = row.id;
|
||||||
|
return api.UpdateObj(form);
|
||||||
|
};
|
||||||
|
const delRequest = async (ctx: DelReq) => {
|
||||||
|
const { row } = ctx;
|
||||||
|
return api.DelObj(row.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addRequest = async (req: AddReq) => {
|
||||||
|
const { form } = req;
|
||||||
|
return api.AddObj(form);
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
crudOptions: {
|
||||||
|
container: {
|
||||||
|
is: 'fs-layout-card'
|
||||||
|
},
|
||||||
|
request: {
|
||||||
|
pageRequest,
|
||||||
|
addRequest,
|
||||||
|
editRequest,
|
||||||
|
delRequest
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
id: {
|
||||||
|
title: 'ID',
|
||||||
|
key: 'id',
|
||||||
|
type: 'number',
|
||||||
|
column: {
|
||||||
|
width: 50
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
datetime: {
|
||||||
|
title: '时间',
|
||||||
|
type: 'datetime',
|
||||||
|
// naive 默认仅支持数字类型时间戳作为日期输入与输出
|
||||||
|
// 字符串类型的时间需要转换格式
|
||||||
|
valueBuilder(context) {
|
||||||
|
const { value, row, key } = context;
|
||||||
|
if (value) {
|
||||||
|
// naive 默认仅支持时间戳作为日期输入与输出
|
||||||
|
row[key] = dayjs(value).valueOf();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
valueResolve(context) {
|
||||||
|
const { value, form, key } = context;
|
||||||
|
if (value) {
|
||||||
|
form[key] = dayjs(value).format('YYYY-MM-DD HH:mm:ss');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
title: '状态',
|
||||||
|
search: { show: true },
|
||||||
|
type: 'dict-select',
|
||||||
|
dict: dict({
|
||||||
|
url: '/mock/crud/demo/dict'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
title: '文本',
|
||||||
|
type: 'text',
|
||||||
|
search: { show: true }
|
||||||
|
},
|
||||||
|
copyable: {
|
||||||
|
title: '可复制',
|
||||||
|
type: ['text', 'copyable'],
|
||||||
|
search: { show: true }
|
||||||
|
},
|
||||||
|
avatar: {
|
||||||
|
title: '头像裁剪',
|
||||||
|
type: 'cropper-uploader'
|
||||||
|
},
|
||||||
|
upload: {
|
||||||
|
title: '文件上传',
|
||||||
|
type: 'file-uploader'
|
||||||
|
},
|
||||||
|
richtext: {
|
||||||
|
title: '富文本',
|
||||||
|
type: 'editor-wang5',
|
||||||
|
column: {
|
||||||
|
// cell中不显示
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
col: {
|
||||||
|
// 横跨两列
|
||||||
|
span: 24
|
||||||
|
},
|
||||||
|
component: {
|
||||||
|
style: {
|
||||||
|
height: '300px'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
28
src/views/crud/demo/index.vue
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<template>
|
||||||
|
<div class="h-full">
|
||||||
|
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, onMounted } from 'vue';
|
||||||
|
import { useFs } from '@fast-crud/fast-crud';
|
||||||
|
import createCrudOptions from './crud';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'ComponentCrud',
|
||||||
|
setup() {
|
||||||
|
const { crudRef, crudBinding, crudExpose } = useFs({ createCrudOptions });
|
||||||
|
|
||||||
|
// 页面打开后获取列表数据
|
||||||
|
onMounted(() => {
|
||||||
|
crudExpose.doRefresh();
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
crudBinding,
|
||||||
|
crudRef
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
13
src/views/crud/doc/index.vue
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<template>
|
||||||
|
<div class="h-full">
|
||||||
|
<iframe class="wh-full" :src="src"></iframe>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
const src = ref('http://fast-crud.docmirror.cn/');
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
43
src/views/crud/header_group/api.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import type { UserPageQuery } from '@fast-crud/fast-crud';
|
||||||
|
import { mockRequest } from '@/service/request';
|
||||||
|
|
||||||
|
const request = mockRequest;
|
||||||
|
const apiPrefix = '/crud/header-group';
|
||||||
|
|
||||||
|
export type HeaderGroupRecord = {
|
||||||
|
id: number;
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
function resHandle(res: any) {
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
export async function GetList(query: UserPageQuery) {
|
||||||
|
const res = await request.post(`${apiPrefix}/page`, query);
|
||||||
|
return resHandle(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function AddObj(obj: HeaderGroupRecord) {
|
||||||
|
const res = await request.post(`${apiPrefix}/add`, obj);
|
||||||
|
return resHandle(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function UpdateObj(obj: HeaderGroupRecord) {
|
||||||
|
const res = await request.post(`${apiPrefix}/update`, obj);
|
||||||
|
return resHandle(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function DelObj(id: number) {
|
||||||
|
const res = await request.post(`${apiPrefix}/delete`, { id });
|
||||||
|
return resHandle(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GetObj(id: number) {
|
||||||
|
const res = await request.get(`${apiPrefix}/info`, { params: { id } });
|
||||||
|
return resHandle(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function BatchDelete(ids: number[]) {
|
||||||
|
const res = await request.post(`${apiPrefix}/batchDelete`, { ids });
|
||||||
|
return resHandle(res);
|
||||||
|
}
|
96
src/views/crud/header_group/crud.tsx
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
import type { CreateCrudOptionsRet, UserPageQuery, UserPageRes } from '@fast-crud/fast-crud';
|
||||||
|
import type { HeaderGroupRecord } from './api';
|
||||||
|
import * as api from './api';
|
||||||
|
|
||||||
|
export default function createCrudOptions(): CreateCrudOptionsRet {
|
||||||
|
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
||||||
|
return api.GetList(query);
|
||||||
|
};
|
||||||
|
const editRequest = async (ctx: { form: HeaderGroupRecord; row: HeaderGroupRecord }) => {
|
||||||
|
const { form, row } = ctx;
|
||||||
|
form.id = row.id;
|
||||||
|
return api.UpdateObj(form);
|
||||||
|
};
|
||||||
|
const delRequest = async (ctx: { row: HeaderGroupRecord }) => {
|
||||||
|
const { row } = ctx;
|
||||||
|
return api.DelObj(row.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addRequest = async (ctx: { form: HeaderGroupRecord }) => {
|
||||||
|
const { form } = ctx;
|
||||||
|
return api.AddObj(form);
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
crudOptions: {
|
||||||
|
container: {
|
||||||
|
// is: 'fs-layout-card'
|
||||||
|
},
|
||||||
|
request: {
|
||||||
|
pageRequest,
|
||||||
|
addRequest,
|
||||||
|
editRequest,
|
||||||
|
delRequest
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
layout: 'flex',
|
||||||
|
labelWidth: '100px' // 表单label宽度
|
||||||
|
},
|
||||||
|
table: { size: 'small' },
|
||||||
|
columns: {
|
||||||
|
id: {
|
||||||
|
title: 'ID',
|
||||||
|
key: 'id',
|
||||||
|
type: 'number',
|
||||||
|
column: {
|
||||||
|
width: 50
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
title: '用户信息',
|
||||||
|
children: {
|
||||||
|
name: {
|
||||||
|
title: '姓名',
|
||||||
|
type: 'text'
|
||||||
|
},
|
||||||
|
age: {
|
||||||
|
title: '年龄',
|
||||||
|
type: 'number'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
address: {
|
||||||
|
title: '地址',
|
||||||
|
children: {
|
||||||
|
area: {
|
||||||
|
title: '地区',
|
||||||
|
children: {
|
||||||
|
province: {
|
||||||
|
title: '省',
|
||||||
|
type: 'text',
|
||||||
|
search: { show: true }
|
||||||
|
},
|
||||||
|
city: {
|
||||||
|
title: '市',
|
||||||
|
search: { show: true },
|
||||||
|
type: 'text'
|
||||||
|
},
|
||||||
|
county: {
|
||||||
|
title: '区',
|
||||||
|
search: { show: true },
|
||||||
|
type: 'text'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
street: {
|
||||||
|
title: '街道',
|
||||||
|
type: 'text'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
32
src/views/crud/header_group/index.vue
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<template>
|
||||||
|
<div class="h-full fs-page-header-group">
|
||||||
|
<fs-crud ref="crudRef" v-bind="crudBinding" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, onMounted } from 'vue';
|
||||||
|
import { useFs } from '@fast-crud/fast-crud';
|
||||||
|
import createCrudOptions from './crud';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'CrudHeaderGroup',
|
||||||
|
setup() {
|
||||||
|
const { crudRef, crudBinding, crudExpose } = useFs({ createCrudOptions });
|
||||||
|
|
||||||
|
// 页面打开后获取列表数据
|
||||||
|
onMounted(() => {
|
||||||
|
crudExpose.doRefresh();
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
crudBinding,
|
||||||
|
crudRef
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
.fs-page-header-group {
|
||||||
|
}
|
||||||
|
</style>
|
13
src/views/crud/source/index.vue
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<template>
|
||||||
|
<div class="h-full">
|
||||||
|
<iframe class="wh-full" :src="src"></iframe>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
const src = ref('https://github.com/fast-crud/fast-crud');
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
@@ -16,6 +16,10 @@ export const views: Record<
|
|||||||
component_button: () => import('./component/button/index.vue'),
|
component_button: () => import('./component/button/index.vue'),
|
||||||
component_card: () => import('./component/card/index.vue'),
|
component_card: () => import('./component/card/index.vue'),
|
||||||
component_table: () => import('./component/table/index.vue'),
|
component_table: () => import('./component/table/index.vue'),
|
||||||
|
crud_demo: () => import('./crud/demo/index.vue'),
|
||||||
|
crud_doc: () => import('./crud/doc/index.vue'),
|
||||||
|
crud_header_group: () => import('./crud/header_group/index.vue'),
|
||||||
|
crud_source: () => import('./crud/source/index.vue'),
|
||||||
dashboard_analysis: () => import('./dashboard/analysis/index.vue'),
|
dashboard_analysis: () => import('./dashboard/analysis/index.vue'),
|
||||||
dashboard_workbench: () => import('./dashboard/workbench/index.vue'),
|
dashboard_workbench: () => import('./dashboard/workbench/index.vue'),
|
||||||
document_naive: () => import('./document/naive/index.vue'),
|
document_naive: () => import('./document/naive/index.vue'),
|
||||||
|
@@ -3,11 +3,7 @@ import presetUno from '@unocss/preset-uno';
|
|||||||
import transformerDirectives from '@unocss/transformer-directives';
|
import transformerDirectives from '@unocss/transformer-directives';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
content: {
|
exclude: ['node_modules', 'dist', '.git', '.husky', '.vscode', 'public', 'build', 'mock', './stats.html'],
|
||||||
pipeline: {
|
|
||||||
exclude: ['node_modules', 'dist', '.git', '.husky', '.vscode', 'public', 'build', 'mock', './stats.html']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
presets: [presetUno({ dark: 'class' })],
|
presets: [presetUno({ dark: 'class' })],
|
||||||
transformers: [transformerDirectives()],
|
transformers: [transformerDirectives()],
|
||||||
shortcuts: {
|
shortcuts: {
|
||||||
|