mirror of
https://github.com/soybeanjs/soybean-admin.git
synced 2025-10-12 21:03:42 +08:00
Compare commits
21 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
de2829fde7 | ||
|
c1bee4046c | ||
|
473095b01b | ||
|
e6abf93457 | ||
|
882f281482 | ||
|
0b2f68ac04 | ||
|
2ca2b766f8 | ||
|
da611fb10b | ||
|
eb8e49e23c | ||
|
0907d38c06 | ||
|
2a9b725c6a | ||
|
8f24a94ed3 | ||
|
4eefc95baa | ||
|
1681c34a52 | ||
|
47ab0184b7 | ||
|
58591f660a | ||
|
3c7e1cf442 | ||
|
055d4cce33 | ||
|
a3dfe61a7b | ||
|
f9d47c081f | ||
|
ff5bf62989 |
8
.vscode/launch.json
vendored
8
.vscode/launch.json
vendored
@@ -7,6 +7,14 @@
|
||||
"name": "Vue debugger",
|
||||
"url": "http://localhost:3200",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "TS debugger",
|
||||
"skipFiles": ["<node_internals>/**"],
|
||||
"runtimeArgs": ["--loader", "tsx"],
|
||||
"program": "${relativeFile}"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
1353
CHANGELOG.md
1353
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
49
README.md
49
README.md
@@ -19,6 +19,19 @@
|
||||
- **权限路由**:提供前端静态和后端动态两种路由模式,基于 mock 的动态路由能快速实现后端动态路由
|
||||
- **请求函数**:基于 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/)
|
||||
@@ -48,25 +61,32 @@
|
||||
|
||||

|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
<div align="center">
|
||||
<img style="width:380px;margin-right:18px;border:1px solid #dedede;" src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin10-v2.png" />
|
||||
<img style="width:380px;border:1px solid #dedede;" src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin11-v2.png" />
|
||||
<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>
|
||||
|
||||
## 安装使用
|
||||
@@ -120,11 +140,6 @@ docker run --name soybean -p 80:80 -d soybeanjs/soybean-admin:v0.9.6
|
||||
|
||||
项目已用 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+` 浏览器
|
||||
@@ -146,11 +161,11 @@ docker run --name soybean -p 80:80 -d soybeanjs/soybean-admin:v0.9.6
|
||||
<div style="display:flex;">
|
||||
<div style="padding-right:24px;">
|
||||
<p>QQ交流群</p>
|
||||
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/qq-soybean-admin.jpg" style="width:200px" />
|
||||
<img src="https://i.loli.net/2021/11/24/1J6REWXiHomU2kM.jpg" style="width:200px" />
|
||||
</div>
|
||||
<div>
|
||||
<p>添加本人微信,欢迎来技术交流,业务咨询</p>
|
||||
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybeanjs.jpeg" style="width:180px" />
|
||||
<img src="https://s2.loli.net/2023/06/07/sVyCUFBvzQ9f5b7.jpg" style="width:200px" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -162,4 +177,4 @@ docker run --name soybean -p 80:80 -d soybeanjs/soybean-admin:v0.9.6
|
||||
|
||||
## License
|
||||
|
||||
[MIT © Soybean-2021](./LICENSE)
|
||||
本项目基于[MIT © Soybean-2021](./LICENSE) 协议,仅供参考学习,商用时请保留作者的版权信息,作者不对软件做担保和负责。
|
||||
|
@@ -3,6 +3,7 @@ import vue from '@vitejs/plugin-vue';
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx';
|
||||
import unocss from '@unocss/vite';
|
||||
import progress from 'vite-plugin-progress';
|
||||
import VueDevtools from 'vite-plugin-vue-devtools';
|
||||
import pageRoute from '@soybeanjs/vite-plugin-vue-page-route';
|
||||
import unplugin from './unplugin';
|
||||
import mock from './mock';
|
||||
@@ -22,6 +23,7 @@ export function setupVitePlugins(viteEnv: ImportMetaEnv): (PluginOption | Plugin
|
||||
}
|
||||
}),
|
||||
vueJsx(),
|
||||
VueDevtools(),
|
||||
...unplugin(viteEnv),
|
||||
unocss(),
|
||||
mock(viteEnv),
|
||||
|
51
package.json
51
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "soybean-admin",
|
||||
"version": "0.10.2",
|
||||
"version": "0.10.3",
|
||||
"description": "A fresh and elegant admin template, based on Vue3、Vite3、TypeScript、NaiveUI and UnoCSS. 一个基于Vue3、Vite3、TypeScript、NaiveUI and UnoCSS的清新优雅的中后台模版。",
|
||||
"author": {
|
||||
"name": "Soybean",
|
||||
@@ -45,14 +45,14 @@
|
||||
"preview": "vite preview",
|
||||
"typecheck": "vue-tsc --noEmit --skipLibCheck",
|
||||
"lint": "eslint . --fix",
|
||||
"format": "soy prettier-format",
|
||||
"format": "soy prettier-write",
|
||||
"commit": "soy git-commit",
|
||||
"cleanup": "soy cleanup",
|
||||
"update-pkg": "soy update-pkg",
|
||||
"update-pkg": "soy ncu",
|
||||
"release": "soy release",
|
||||
"tsx": "tsx",
|
||||
"logo": "tsx ./scripts/logo.ts",
|
||||
"update-version": "bumpp --commit --push --tag",
|
||||
"prepare": "soy init-git-hooks"
|
||||
"prepare": "soy init-simple-git-hooks"
|
||||
},
|
||||
"dependencies": {
|
||||
"@antv/data-set": "0.11.8",
|
||||
@@ -64,15 +64,15 @@
|
||||
"clipboard": "2.0.11",
|
||||
"colord": "2.9.3",
|
||||
"crypto-js": "4.1.1",
|
||||
"dayjs": "1.11.7",
|
||||
"dayjs": "1.11.8",
|
||||
"echarts": "5.4.2",
|
||||
"form-data": "4.0.0",
|
||||
"lodash-es": "4.17.21",
|
||||
"naive-ui": "2.34.4",
|
||||
"pinia": "2.1.3",
|
||||
"pinia": "2.1.4",
|
||||
"print-js": "1.6.0",
|
||||
"qs": "6.11.2",
|
||||
"swiper": "9.3.2",
|
||||
"swiper": "9.4.1",
|
||||
"ua-parser-js": "1.0.35",
|
||||
"vditor": "3.9.3",
|
||||
"vue": "3.3.4",
|
||||
@@ -80,42 +80,42 @@
|
||||
"vue-router": "4.2.2",
|
||||
"vuedraggable": "4.1.0",
|
||||
"wangeditor": "4.7.15",
|
||||
"xgplayer": "3.0.2"
|
||||
"xgplayer": "3.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@amap/amap-jsapi-types": "0.0.13",
|
||||
"@iconify/json": "2.2.72",
|
||||
"@iconify/json": "2.2.78",
|
||||
"@iconify/vue": "4.1.1",
|
||||
"@soybeanjs/cli": "0.4.1",
|
||||
"@soybeanjs/cli": "0.6.2",
|
||||
"@soybeanjs/vite-plugin-vue-page-route": "0.0.5",
|
||||
"@types/bmapgl": "0.0.7",
|
||||
"@types/crypto-js": "4.1.1",
|
||||
"@types/node": "20.2.5",
|
||||
"@types/node": "20.3.1",
|
||||
"@types/qs": "6.9.7",
|
||||
"@types/ua-parser-js": "0.7.36",
|
||||
"@unocss/preset-uno": "0.52.7",
|
||||
"@unocss/transformer-directives": "0.52.7",
|
||||
"@unocss/vite": "0.52.7",
|
||||
"@unocss/preset-uno": "0.53.1",
|
||||
"@unocss/transformer-directives": "0.53.1",
|
||||
"@unocss/vite": "0.53.1",
|
||||
"@vitejs/plugin-vue": "4.2.3",
|
||||
"@vitejs/plugin-vue-jsx": "3.0.1",
|
||||
"bumpp": "9.1.0",
|
||||
"cross-env": "7.0.3",
|
||||
"eslint": "8.41.0",
|
||||
"eslint-config-soybeanjs": "0.4.8",
|
||||
"eslint": "8.42.0",
|
||||
"eslint-config-soybeanjs": "0.4.9",
|
||||
"mockjs": "1.1.0",
|
||||
"rollup-plugin-visualizer": "5.9.0",
|
||||
"sass": "1.62.1",
|
||||
"rollup-plugin-visualizer": "5.9.2",
|
||||
"sass": "1.63.4",
|
||||
"simple-git-hooks": "2.8.1",
|
||||
"tsx": "3.12.7",
|
||||
"typescript": "5.0.4",
|
||||
"unplugin-icons": "0.16.1",
|
||||
"unplugin-vue-components": "0.25.0",
|
||||
"typescript": "5.1.3",
|
||||
"unplugin-icons": "0.16.3",
|
||||
"unplugin-vue-components": "0.25.1",
|
||||
"vite": "4.3.9",
|
||||
"vite-plugin-compression": "0.5.1",
|
||||
"vite-plugin-mock": "2.9.8",
|
||||
"vite-plugin-progress": "0.0.7",
|
||||
"vite-plugin-pwa": "0.15.2",
|
||||
"vite-plugin-pwa": "0.16.4",
|
||||
"vite-plugin-svg-icons": "2.0.1",
|
||||
"vite-plugin-vue-devtools": "0.2.0",
|
||||
"vue-tsc": "1.6.5"
|
||||
},
|
||||
"pnpm": {
|
||||
@@ -126,5 +126,8 @@
|
||||
"simple-git-hooks": {
|
||||
"commit-msg": "pnpm soy git-commit-verify",
|
||||
"pre-commit": "pnpm typecheck && pnpm soy lint-staged"
|
||||
},
|
||||
"soybean": {
|
||||
"useSoybeanToken": true
|
||||
}
|
||||
}
|
||||
|
4098
pnpm-lock.yaml
generated
4098
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
import { h } from 'vue';
|
||||
import SvgIcon from '~/src/components/custom/svg-icon.vue';
|
||||
import SvgIcon from '@/components/custom/svg-icon.vue';
|
||||
|
||||
/**
|
||||
* 图标渲染
|
||||
|
6
src/constants/_shared.ts
Normal file
6
src/constants/_shared.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export function transformObjectToOption<T extends object>(obj: T) {
|
||||
return Object.entries(obj).map(([value, label]) => ({
|
||||
value,
|
||||
label
|
||||
})) as Common.OptionWithKey<keyof T>[];
|
||||
}
|
@@ -1,3 +1,5 @@
|
||||
import { transformObjectToOption } from './_shared';
|
||||
|
||||
export const loginModuleLabels: Record<UnionKey.LoginModule, string> = {
|
||||
'pwd-login': '账密登录',
|
||||
'code-login': '手机验证码登录',
|
||||
@@ -11,23 +13,14 @@ export const userRoleLabels: Record<Auth.RoleType, string> = {
|
||||
admin: '管理员',
|
||||
user: '普通用户'
|
||||
};
|
||||
|
||||
export const userRoleOptions: Common.OptionWithKey<Auth.RoleType>[] = [
|
||||
{ value: 'super', label: userRoleLabels.super },
|
||||
{ value: 'admin', label: userRoleLabels.admin },
|
||||
{ value: 'user', label: userRoleLabels.user }
|
||||
];
|
||||
export const userRoleOptions = transformObjectToOption(userRoleLabels);
|
||||
|
||||
/** 用户性别 */
|
||||
export const genderLabels: Record<UserManagement.GenderKey, string> = {
|
||||
0: '女',
|
||||
1: '男'
|
||||
};
|
||||
|
||||
export const genderOptions: Common.OptionWithKey<UserManagement.GenderKey>[] = [
|
||||
{ value: '0', label: genderLabels['0'] },
|
||||
{ value: '1', label: genderLabels['1'] }
|
||||
];
|
||||
export const genderOptions = transformObjectToOption(genderLabels);
|
||||
|
||||
/** 用户状态 */
|
||||
export const userStatusLabels: Record<UserManagement.UserStatusKey, string> = {
|
||||
@@ -36,10 +29,4 @@ export const userStatusLabels: Record<UserManagement.UserStatusKey, string> = {
|
||||
3: '冻结',
|
||||
4: '软删除'
|
||||
};
|
||||
|
||||
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'] }
|
||||
];
|
||||
export const userStatusOptions = transformObjectToOption(userStatusLabels);
|
||||
|
@@ -1,81 +1,31 @@
|
||||
import { transformObjectToOption } from './_shared';
|
||||
|
||||
export const themeLayoutModeLabels: Record<UnionKey.ThemeLayoutMode, string> = {
|
||||
vertical: '左侧菜单模式',
|
||||
horizontal: '顶部菜单模式',
|
||||
'vertical-mix': '左侧菜单混合模式',
|
||||
'horizontal-mix': '顶部菜单混合模式'
|
||||
};
|
||||
|
||||
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 themeLayoutModeOptions = transformObjectToOption(themeLayoutModeLabels);
|
||||
|
||||
export const themeScrollModeLabels: Record<UnionKey.ThemeScrollMode, string> = {
|
||||
wrapper: '外层滚动',
|
||||
content: '主体滚动'
|
||||
};
|
||||
|
||||
export const themeScrollModeOptions: Common.OptionWithKey<UnionKey.ThemeScrollMode>[] = [
|
||||
{
|
||||
value: 'wrapper',
|
||||
label: themeScrollModeLabels.wrapper
|
||||
},
|
||||
{
|
||||
value: 'content',
|
||||
label: themeScrollModeLabels.content
|
||||
}
|
||||
];
|
||||
export const themeScrollModeOptions = transformObjectToOption(themeScrollModeLabels);
|
||||
|
||||
export const themeTabModeLabels: Record<UnionKey.ThemeTabMode, string> = {
|
||||
chrome: '谷歌风格',
|
||||
button: '按钮风格'
|
||||
};
|
||||
|
||||
export const themeTabModeOptions: Common.OptionWithKey<UnionKey.ThemeTabMode>[] = [
|
||||
{
|
||||
value: 'chrome',
|
||||
label: themeTabModeLabels.chrome
|
||||
},
|
||||
{
|
||||
value: 'button',
|
||||
label: themeTabModeLabels.button
|
||||
}
|
||||
];
|
||||
export const themeTabModeOptions = transformObjectToOption(themeTabModeLabels);
|
||||
|
||||
export const themeHorizontalMenuPositionLabels: Record<UnionKey.ThemeHorizontalMenuPosition, string> = {
|
||||
'flex-start': '居左',
|
||||
center: '居中',
|
||||
'flex-end': '居右'
|
||||
};
|
||||
|
||||
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 themeHorizontalMenuPositionOptions = transformObjectToOption(themeHorizontalMenuPositionLabels);
|
||||
|
||||
export const themeAnimateModeLabels: Record<UnionKey.ThemeAnimateMode, string> = {
|
||||
'zoom-fade': '渐变',
|
||||
@@ -85,30 +35,4 @@ export const themeAnimateModeLabels: Record<UnionKey.ThemeAnimateMode, string> =
|
||||
'fade-bottom': '底部消退',
|
||||
'fade-scale': '缩放消退'
|
||||
};
|
||||
|
||||
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']
|
||||
}
|
||||
];
|
||||
export const themeAnimateModeOptions = transformObjectToOption(themeAnimateModeLabels);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<hover-container class="w-40px h-full">
|
||||
<hover-container class="w-40px h-full" :inverted="theme.header.inverted">
|
||||
<n-dropdown :options="options" trigger="hover" :value="language" @select="handleSelect">
|
||||
<icon-cil:language class="text-18px outline-transparent" />
|
||||
</n-dropdown>
|
||||
@@ -9,8 +9,10 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useThemeStore } from '@/store';
|
||||
import { localStg } from '@/utils';
|
||||
|
||||
const theme = useThemeStore();
|
||||
const { locale } = useI18n();
|
||||
|
||||
const language = ref<I18nType.langType>(localStg.get('lang') || 'zh-CN');
|
||||
|
6
src/typings/package.d.ts
vendored
6
src/typings/package.d.ts
vendored
@@ -7,9 +7,3 @@ declare namespace BMap {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@@ -3,7 +3,11 @@ import presetUno from '@unocss/preset-uno';
|
||||
import transformerDirectives from '@unocss/transformer-directives';
|
||||
|
||||
export default defineConfig({
|
||||
exclude: ['node_modules', 'dist', '.git', '.husky', '.vscode', 'public', 'build', 'mock', './stats.html'],
|
||||
content: {
|
||||
pipeline: {
|
||||
exclude: ['node_modules', 'dist', '.git', '.husky', '.vscode', 'public', 'build', 'mock', './stats.html']
|
||||
}
|
||||
},
|
||||
presets: [presetUno({ dark: 'class' })],
|
||||
transformers: [transformerDirectives()],
|
||||
shortcuts: {
|
||||
|
Reference in New Issue
Block a user