├── src ├── pages │ ├── sys │ │ ├── permission.vue │ │ ├── components │ │ │ ├── UserForm.vue │ │ │ ├── RoleForm.vue │ │ │ ├── IconSelect.vue │ │ │ └── menuForm.vue │ │ ├── role.vue │ │ ├── menu.vue │ │ └── user.vue │ ├── layout │ │ ├── Header.vue │ │ ├── PageStack.vue │ │ ├── SideBar.vue │ │ ├── index.vue │ │ └── Breadcrumb.vue │ ├── home │ │ └── index.vue │ ├── form │ │ ├── upload.vue │ │ └── editor.vue │ ├── echart │ │ ├── pie.vue │ │ ├── ring.vue │ │ ├── radar.vue │ │ ├── line.vue │ │ └── bar.vue │ ├── demo │ │ └── demo.vue │ └── login.vue ├── assets │ ├── logo.png │ ├── images │ │ ├── avatar.gif │ │ ├── welcome.png │ │ └── login-bg.jpg │ ├── css │ │ ├── reset.css │ │ └── common.css │ └── langs │ │ └── zh-Hans.js ├── main.js ├── components │ ├── NoRight.vue │ ├── Header.vue │ ├── NotFound.vue │ └── Verify.vue ├── utils │ ├── request.js │ └── toTree.js ├── data │ ├── menu.js │ └── menuOne.js ├── api │ └── sys.js ├── App.vue └── router │ └── index.js ├── .env.production ├── .vscode └── extensions.json ├── public └── favicon.ico ├── mock ├── post-to-get.js ├── menu.json └── db.json ├── .env ├── .env.development ├── .gitignore ├── index.html ├── README.md ├── vite.config.js ├── package.json └── server └── app.js /src/pages/sys/permission.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.env.production: -------------------------------------------------------------------------------- 1 | ENV = 'production' 2 | 3 | VITE_BASE_URL='/api' -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["johnsoncodehk.volar"] 3 | } 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crewray/naiveAdmin/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crewray/naiveAdmin/HEAD/src/assets/logo.png -------------------------------------------------------------------------------- /src/assets/images/avatar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crewray/naiveAdmin/HEAD/src/assets/images/avatar.gif -------------------------------------------------------------------------------- /src/assets/images/welcome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crewray/naiveAdmin/HEAD/src/assets/images/welcome.png -------------------------------------------------------------------------------- /mock/post-to-get.js: -------------------------------------------------------------------------------- 1 | module.exports = function (req, res, next) { 2 | req.method = "GET"; 3 | next(); 4 | } -------------------------------------------------------------------------------- /src/assets/images/login-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crewray/naiveAdmin/HEAD/src/assets/images/login-bg.jpg -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | # VITE_BASE_URL = 'https://www.fastmock.site/mock/60505959b23bddbd187087af3d5e8680/admin' 2 | # VITE_BASE_URL = 'http://127.0.0.1:3005' -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | import router from './router/index' 4 | 5 | 6 | const app=createApp(App) 7 | app.use(router) 8 | app.mount('#app') 9 | -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | # 本地环境 2 | NODE_ENV = 'development' 3 | 4 | # 本地环境接口地址 5 | # VITE_BASE_URL = 'https://www.fastmock.site/mock/60505959b23bddbd187087af3d5e8680/admin' 6 | VITE_BASE_URL = 'http://localhost:3005' -------------------------------------------------------------------------------- /src/components/NoRight.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | -------------------------------------------------------------------------------- /src/pages/layout/Header.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist.rar 13 | dist-ssr 14 | *.local 15 | 16 | # Editor directories and files 17 | .vscode/* 18 | !.vscode/extensions.json 19 | .idea 20 | .DS_Store 21 | *.suo 22 | *.ntvs* 23 | *.njsproj 24 | *.sln 25 | *.sw? 26 | -------------------------------------------------------------------------------- /src/components/Header.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/components/NotFound.vue: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /src/utils/request.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | 3 | 4 | const service=axios.create({ 5 | baseURL:import.meta.env.VITE_BASE_URL, 6 | timeout:2*60*1000, 7 | }) 8 | 9 | export const get= (url,data={})=>{ 10 | return service.get(url,{params:data}) 11 | } 12 | export const post= (url,data)=>{ 13 | return service.post(url,data) 14 | } 15 | 16 | export const put= (url,data)=>{ 17 | return service.put(url+'/'+data.id,data) 18 | } 19 | export const delete_= (url,id)=>{ 20 | return service.delete(url+'/'+id) 21 | } 22 | -------------------------------------------------------------------------------- /src/pages/home/index.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 15 | 16 | 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # naiveAdmin 2 | 3 | 一个基于vite+vue3+naive-ui的admin模板,用与快速搭建后台管理系统 4 | 5 | naive-ui文档:https://www.naiveui.com/zh-CN/os-theme 6 | 7 | vite文档:https://cn.vitejs.dev/ 8 | 9 | vue3文档:https://v3.cn.vuejs.org/guide/introduction.html 10 | 11 | json-server: https://github.com/typicode/json-server 12 | ## 亮点 13 | - 开箱即用, 添加菜单页面无需编写代码 14 | - 基于权限的动态路由 15 | - mock数据 16 | ## 安装 17 | 18 | `npm i或 yarn install` 19 | 20 | ## 启动 21 | 22 | `npm run dev`(前端) 23 | `npm run mock`(json-server) 24 | `npm run service`(node) 25 | 26 | ## 打包 27 | 28 | ` npm run build` 29 | 30 | ## 预览 31 | 可能需要科学上网 32 | [demo](http://13.229.110.98/) 33 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import { resolve } from "path"; 3 | import vue from "@vitejs/plugin-vue"; 4 | import Components from "unplugin-vue-components/vite"; 5 | import { NaiveUiResolver } from "unplugin-vue-components/resolvers"; 6 | 7 | // https://vitejs.dev/config/ 8 | export default defineConfig({ 9 | resolve: { 10 | alias: [{ find: "@", replacement: resolve(__dirname, "./src") }], 11 | }, 12 | plugins: [ 13 | vue(), 14 | Components({ 15 | //按需引入naive-ui 16 | resolvers: [NaiveUiResolver()], 17 | }), 18 | ], 19 | server: { 20 | port: 3000, 21 | open: true, 22 | openPage: "/", 23 | https: false, 24 | host: "0.0.0.0", 25 | 26 | }, 27 | }); 28 | 29 | -------------------------------------------------------------------------------- /src/data/menu.js: -------------------------------------------------------------------------------- 1 | import { h,ref } from "vue"; 2 | import { NIcon } from "naive-ui"; 3 | import * as fa from "@vicons/fa"; 4 | import { getMenuApi } from "@/api/sys.js"; 5 | function renderIcon(icon) { 6 | return () => h(NIcon, null, { default: () => h(icon) }); 7 | } 8 | 9 | const menuList = ref([]); 10 | getMenuApi().then((res) => { 11 | if (res.status == 200) { 12 | // Object.assign(menuList,formatMenu(res.data)); 13 | menuList.value=formatMenu(res.data) 14 | 15 | } 16 | }); 17 | function formatMenu(menu) { 18 | const newMenu = menu.map((item) => { 19 | // console.log(item.icon) 20 | if (item.icon) { 21 | item.icon = renderIcon(fa[item.icon]); 22 | } 23 | // if(item.component){ 24 | // item.component=()=>import(item.component) 25 | // } 26 | if (item.children) { 27 | item.children = formatMenu(item.children); 28 | } 29 | return item 30 | }); 31 | return newMenu 32 | } 33 | // menuList=formatMenu(menuList) 34 | 35 | export { menuList }; 36 | 37 | -------------------------------------------------------------------------------- /src/utils/toTree.js: -------------------------------------------------------------------------------- 1 | // 获取数据同时删除原数据 2 | const myFilter = function (newArr, oldArr, callback) { 3 | for (let i = 0; i < oldArr.length; ) { 4 | const item = oldArr[i]; 5 | let res=callback(item) 6 | if(res){ 7 | newArr.push(item); 8 | oldArr.splice(i, 1); 9 | } 10 | else { 11 | i++; 12 | } 13 | } 14 | }; 15 | 16 | // 还原成树形结构 17 | export const toTree = ( oldMenu) => { 18 | const menu = []; 19 | if (!menu.length) 20 | myFilter(menu,oldMenu,item=>item.pid===0) 21 | for(const i in menu){ 22 | const item=menu[i] 23 | 24 | let index=oldMenu.findIndex(element=>element.pid===item.id) 25 | if(index>=0 && !item.children){ 26 | menu[i]['children']=[] 27 | } 28 | if(item.children){ 29 | 30 | myFilter(item.children,oldMenu,element=>element.pid===item.id) 31 | toTree(item.children,oldMenu) 32 | 33 | } 34 | 35 | } 36 | return menu 37 | }; 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/pages/form/upload.vue: -------------------------------------------------------------------------------- 1 | 34 | 37 | -------------------------------------------------------------------------------- /src/pages/form/editor.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 42 | 43 | 48 | -------------------------------------------------------------------------------- /src/assets/css/reset.css: -------------------------------------------------------------------------------- 1 | html,body,div,span,applet,object,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video { 2 | margin:0; 3 | padding:0; 4 | /* border:0; */ 5 | /* font-size:100%; */ 6 | /* font:inherit; */ 7 | /* font-weight:normal; */ 8 | vertical-align:baseline; 9 | box-sizing: border-box; 10 | } 11 | /* HTML5 display-role reset for older browsers */ 12 | article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section { 13 | display:block; 14 | } 15 | ol,ul,li { 16 | list-style:none; 17 | } 18 | blockquote,q { 19 | quotes:none; 20 | } 21 | blockquote:before,blockquote:after,q:before,q:after { 22 | content:''; 23 | content:none; 24 | } 25 | table { 26 | border-collapse:collapse; 27 | border-spacing:0; 28 | } 29 | th,td { 30 | vertical-align:middle; 31 | } 32 | /* custom */ 33 | a { 34 | outline:none; 35 | color:#16418a; 36 | text-decoration:none; 37 | } 38 | a:focus { 39 | outline:none; 40 | } 41 | input:focus,select:focus,textarea:focus { 42 | outline:-webkit-focus-ring-color auto 0; 43 | } 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "myadmin", 3 | "private": true, 4 | "version": "0.0.0", 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "vite build", 8 | "preview": "vite preview", 9 | "mock": "json-server --watch mock/db.json --port 3005", 10 | "mockdev": "npm run mock | npm run dev", 11 | "serve": " nodemon ./server/app.js | npm run mockdev", 12 | "service": "nodemon ./server/app.js" 13 | }, 14 | "dependencies": { 15 | "@tinymce/tinymce-vue": "^4.0.7", 16 | "@wangeditor/editor": "^5.1.1", 17 | "@wangeditor/editor-for-vue": "^5.1.11", 18 | "echarts": "^5.3.2", 19 | "esbuild-windows-64": "^0.14.42", 20 | "js-md5": "^0.7.3", 21 | "koa2-cors": "^2.0.6", 22 | "tinymce": "^6.0.3", 23 | "vue": "^3.2.25", 24 | "vue-router": "^4.0.12" 25 | }, 26 | "devDependencies": { 27 | "@vicons/antd": "^0.12.0", 28 | "@vicons/fa": "^0.12.0", 29 | "@vicons/fluent": "^0.12.0", 30 | "@vicons/ionicons4": "^0.12.0", 31 | "@vicons/ionicons5": "^0.12.0", 32 | "@vitejs/plugin-vue": "^2.2.0", 33 | "axios": "^0.27.2", 34 | "json-server": "^0.17.0", 35 | "koa": "^2.14.2", 36 | "koa-body": "^6.0.1", 37 | "koa-router": "^12.0.1", 38 | "less": "^4.1.2", 39 | "less-loader": "^6.0.0", 40 | "lodash": "^4.17.21", 41 | "naive-ui": "^2.30.5", 42 | "unplugin-vue-components": "^0.19.6", 43 | "vfonts": "^0.0.3", 44 | "vite": "^2.8.0" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/pages/layout/PageStack.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/pages/echart/pie.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/api/sys.js: -------------------------------------------------------------------------------- 1 | import {get,post,put,delete_} from '@/utils/request' 2 | 3 | export const getUserListApi= (data={})=>{ 4 | return get('/user',data) 5 | } 6 | export const createUserApi=(data)=>{ 7 | return post('/user',data) 8 | } 9 | export const updateUserApi=(data)=>{ 10 | return put('/user',data) 11 | } 12 | export const deleteUserApi=(id)=>{ 13 | return delete_('/user',id) 14 | } 15 | 16 | export const getRoleListApi= (data={})=>{ 17 | return get('/role',data) 18 | } 19 | export const createRoleApi=(data)=>{ 20 | return post('/role',data) 21 | } 22 | export const updateRoleApi=(data)=>{ 23 | return put('/role',data) 24 | } 25 | export const deleteRoleApi=(id)=>{ 26 | return delete_('/role',id) 27 | } 28 | 29 | // 获取菜单 30 | export const getMenuApi=()=>{ 31 | return get('/menu') 32 | } 33 | // 获取角色菜单 34 | export const getRoleMenuApi=(id)=>{ 35 | return get('/role/'+id) 36 | } 37 | //添加菜单 38 | export const createMenuApi=(data)=>{ 39 | return post('/menu',data) 40 | } 41 | //获取菜单项 42 | export const getMenuItemApi=(path)=>{ 43 | return get('/menu'+path) 44 | } 45 | //删除菜单项 46 | export const deleteMenuApi=(id)=>{ 47 | return delete_('/menu',id) 48 | } 49 | 50 | //修改菜单项 51 | export const updateMenuApi=(data)=>{ 52 | return put('/menu',data) 53 | } 54 | 55 | export const test=(data)=>{ 56 | return put('/demo',data) 57 | } 58 | 59 | //登录 60 | export const loginApi=(data)=>{ 61 | let param='' 62 | for(let key in data){ 63 | param+=`${key}=${data[key]}&` 64 | } 65 | if(param) param=param.slice(0,-1) 66 | return get('/user?'+param) 67 | } -------------------------------------------------------------------------------- /src/pages/echart/ring.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /src/pages/echart/radar.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/pages/sys/components/UserForm.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 58 | 59 | 64 | -------------------------------------------------------------------------------- /src/pages/sys/components/RoleForm.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 59 | 60 | 65 | -------------------------------------------------------------------------------- /server/app.js: -------------------------------------------------------------------------------- 1 | const Koa = require("koa"); 2 | const fs = require("fs"); 3 | const app = new Koa(); 4 | const path = require("path"); 5 | const Router = require("koa-router"); 6 | const router = new Router(); 7 | const {koaBody}=require('koa-body') 8 | const cors = require("koa2-cors"); 9 | app.use( 10 | cors({ 11 | origin: function (ctx) { 12 | //设置允许来自指定域名请求 13 | if (ctx.url === "/test") { 14 | return "*"; // 允许来自所有域名请求 15 | } 16 | return "http://localhost:3000"; //只允许http://localhost:3000这个域名的请求 17 | }, 18 | // maxAge: 5, //指定本次预检请求的有效期,单位为秒。 19 | // credentials: true, //是否允许发送Cookie 20 | // allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"], //设置所允许的HTTP请求方法 21 | // allowHeaders: ["Content-Type", "Authorization", "Accept"], //设置服务器支持的所有头信息字段 22 | // exposeHeaders: ["WWW-Authenticate", "Server-Authorization"], //设置获取其他自定义字段 23 | }) 24 | ); 25 | app.use(koaBody()) 26 | app.use(router.routes()); 27 | router.post("/addPage", async (ctx) => { 28 | // return console.log(ctx.request.body) 29 | const param = ctx.request.body; 30 | console.log(param); 31 | if (!param || !param.path) { 32 | ctx.body = { 33 | code: 400, 34 | msg: "path is required", 35 | }; 36 | return; 37 | } 38 | fs.writeFile( 39 | path.join(__dirname,'..', param.path.replace(/^\/\/$/g, "/") + ".vue"), 40 | ``, 41 | (err) => { 42 | console.log(err,42) 43 | if (err) { 44 | 45 | ctx.body = JSON.stringify({ 46 | code: 400, 47 | msg: "create file error", 48 | }); 49 | return 50 | } 51 | ctx.body = JSON.stringify({ 52 | code: 200, 53 | msg: "success", 54 | }); 55 | } 56 | ); 57 | }); 58 | 59 | 60 | 61 | app.listen(4000, () => { 62 | console.log("server is running at http://localhost:4000/"); 63 | }); 64 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 45 | 46 | 69 | -------------------------------------------------------------------------------- /src/pages/sys/components/IconSelect.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 79 | 80 | 87 | -------------------------------------------------------------------------------- /src/pages/demo/demo.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 92 | 93 | 99 | -------------------------------------------------------------------------------- /src/pages/echart/line.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /src/pages/layout/SideBar.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 18 | 110 | -------------------------------------------------------------------------------- /src/pages/layout/index.vue: -------------------------------------------------------------------------------- 1 | 35 | 87 | 88 | 119 | -------------------------------------------------------------------------------- /src/pages/layout/Breadcrumb.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 95 | 96 | 102 | -------------------------------------------------------------------------------- /src/pages/echart/bar.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /src/pages/sys/components/menuForm.vue: -------------------------------------------------------------------------------- 1 | 63 | 64 | 116 | 117 | 122 | -------------------------------------------------------------------------------- /src/components/Verify.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 157 | 158 | 159 | -------------------------------------------------------------------------------- /mock/menu.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id":1, 4 | "pid":0, 5 | "title": "首页", 6 | "path": "/home", 7 | "name": "home", 8 | "icon": "Home", 9 | "component": "/src/pages/home/index.vue", 10 | "meta": { 11 | "title": "首页" 12 | } 13 | }, 14 | { 15 | "id":2, 16 | "pid":0, 17 | "title": "echart组件", 18 | "path": "/echart", 19 | "name": "echart", 20 | "meta": { 21 | "title": "图表" 22 | }, 23 | "icon": "ChartBar", 24 | "children": [ 25 | { 26 | "id":6, 27 | "pid":2, 28 | "title": "折线图", 29 | "path": "/echart/line", 30 | "name": "line", 31 | "meta": { 32 | "title": "折线图" 33 | }, 34 | "icon": "ChartBar", 35 | "component": "/src/pages/echart/line.vue" 36 | }, 37 | { 38 | "id":7, 39 | "pid":2, 40 | "title": "柱状图", 41 | "path": "/echart/bar", 42 | "name": "bar", 43 | "meta": { 44 | "title": "柱状图" 45 | }, 46 | "icon": "ChartBar", 47 | "component": "/src/pages/echart/bar.vue" 48 | }, 49 | { 50 | "id":8, 51 | "pid":2, 52 | "title": "饼图", 53 | "path": "/echart/pie", 54 | "name": "pie", 55 | "meta": { 56 | "title": "饼图" 57 | }, 58 | "icon": "ChartBar", 59 | "component": "/src/pages/echart/pie.vue" 60 | }, 61 | { 62 | "id":9, 63 | "pid":2, 64 | "title": "雷达图", 65 | "path": "/echart/radar", 66 | "name": "radar", 67 | "meta": { 68 | "title": "雷达图" 69 | }, 70 | "icon": "ChartBar", 71 | "component": "/src/pages/echart/radar.vue" 72 | }, 73 | { 74 | "id":10, 75 | "pid":2, 76 | "title": "环形图", 77 | "path": "/echart/ring", 78 | "name": "ring", 79 | "meta": { 80 | "title": "环形图" 81 | }, 82 | "icon": "ChartBar", 83 | "component": "/src/pages/echart/ring.vue" 84 | } 85 | ] 86 | }, 87 | { 88 | "id":3, 89 | "pid":0, 90 | "title": "表单组件", 91 | "path": "/form", 92 | "name": "form", 93 | "meta": { 94 | "title": "表单组件" 95 | }, 96 | "icon": "Wpforms", 97 | "children": [ 98 | { 99 | "id":11, 100 | "pid":3, 101 | "title": "富文本编辑器", 102 | "path": "/form/editor", 103 | "name": "editor", 104 | "meta": { 105 | "title": "富文本编辑器" 106 | }, 107 | "icon": "Edit", 108 | "component": "/src/pages/form/editor.vue" 109 | }, 110 | { 111 | "id":12, 112 | "pid":3, 113 | "title": "上传组件", 114 | "path": "/form/upload", 115 | "name": "upload", 116 | "meta": { 117 | "title": "上传组件" 118 | }, 119 | "icon": "Upload", 120 | "component": "/src/pages/form/upload.vue" 121 | } 122 | ] 123 | }, 124 | { 125 | "id":4, 126 | "pid":0, 127 | "title": "demo", 128 | "path": "/demo", 129 | "name": "demo", 130 | "meta": { 131 | "title": "demo" 132 | }, 133 | "icon": "Wrench", 134 | "component": "/src/pages/demo/demo.vue" 135 | }, 136 | { 137 | "id":5, 138 | "pid":0, 139 | "title": "系统管理", 140 | "path": "/sys", 141 | "name": "system", 142 | "icon": "Wrench", 143 | "meta": { 144 | "title": "系统管理" 145 | }, 146 | "children": [ 147 | { 148 | "id":13, 149 | "pid":5, 150 | "title": "用户管理", 151 | "path": "/sys/user", 152 | "name": "user", 153 | "meta": { 154 | "title": "用户管理" 155 | }, 156 | "icon": "User", 157 | "component": "/src/pages/sys/user.vue" 158 | }, 159 | { 160 | "id":14, 161 | "pid":5, 162 | "title": "角色管理", 163 | "path": "/sys/role", 164 | "name": "role", 165 | "meta": { 166 | "title": "角色管理" 167 | }, 168 | "icon": "UserEdit", 169 | "component": "/src/pages/sys/role.vue" 170 | }, 171 | { 172 | "id":15, 173 | "pid":5, 174 | "title": "菜单管理", 175 | "path": "/sys/menu", 176 | "name": "menu", 177 | "meta": { 178 | "title": "菜单管理" 179 | }, 180 | "icon": "Bars", 181 | "component": "/src/pages/sys/menu.vue" 182 | } 183 | ] 184 | } 185 | ] -------------------------------------------------------------------------------- /src/pages/sys/role.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /src/data/menuOne.js: -------------------------------------------------------------------------------- 1 | export const menuList=[ 2 | { 3 | "id": 1, 4 | "pid": 0, 5 | "title": "首页", 6 | "path": "/home", 7 | "name": "home", 8 | "icon": "Home", 9 | "component": "/src/pages/home/index.vue", 10 | "meta": { 11 | "title": "首页" 12 | } 13 | }, 14 | { 15 | "id": 2, 16 | "pid": 0, 17 | "title": "echart组件", 18 | "path": "/echart", 19 | "name": "echart", 20 | "meta": { 21 | "title": "图表" 22 | }, 23 | "icon": "ChartBar" 24 | }, 25 | { 26 | "id": 6, 27 | "pid": 2, 28 | "title": "折线图", 29 | "path": "/echart/line", 30 | "name": "line", 31 | "meta": { 32 | "title": "折线图" 33 | }, 34 | "icon": "ChartBar", 35 | "component": "/src/pages/echart/line.vue" 36 | }, 37 | { 38 | "id": 7, 39 | "pid": 2, 40 | "title": "柱状图", 41 | "path": "/echart/bar", 42 | "name": "bar", 43 | "meta": { 44 | "title": "柱状图" 45 | }, 46 | "icon": "ChartBar", 47 | "component": "/src/pages/echart/bar.vue" 48 | }, 49 | { 50 | "id": 8, 51 | "pid": 2, 52 | "title": "饼图", 53 | "path": "/echart/pie", 54 | "name": "pie", 55 | "meta": { 56 | "title": "饼图" 57 | }, 58 | "icon": "ChartBar", 59 | "component": "/src/pages/echart/pie.vue" 60 | }, 61 | { 62 | "id": 9, 63 | "pid": 2, 64 | "title": "雷达图", 65 | "path": "/echart/radar", 66 | "name": "radar", 67 | "meta": { 68 | "title": "雷达图" 69 | }, 70 | "icon": "ChartBar", 71 | "component": "/src/pages/echart/radar.vue" 72 | }, 73 | { 74 | "id": 10, 75 | "pid": 2, 76 | "title": "环形图", 77 | "path": "/echart/ring", 78 | "name": "ring", 79 | "meta": { 80 | "title": "环形图" 81 | }, 82 | "icon": "ChartBar", 83 | "component": "/src/pages/echart/ring.vue" 84 | }, 85 | { 86 | "id": 3, 87 | "pid": 0, 88 | "title": "表单组件", 89 | "path": "/form", 90 | "name": "form", 91 | "meta": { 92 | "title": "表单组件" 93 | }, 94 | "icon": "Wpforms" 95 | }, 96 | { 97 | "id": 11, 98 | "pid": 3, 99 | "title": "富文本编辑器", 100 | "path": "/form/editor", 101 | "name": "editor", 102 | "meta": { 103 | "title": "富文本编辑器" 104 | }, 105 | "icon": "Edit", 106 | "component": "/src/pages/form/editor.vue" 107 | }, 108 | { 109 | "id": 12, 110 | "pid": 3, 111 | "title": "上传组件", 112 | "path": "/form/upload", 113 | "name": "upload", 114 | "meta": { 115 | "title": "上传组件" 116 | }, 117 | "icon": "Upload", 118 | "component": "/src/pages/form/upload.vue" 119 | }, 120 | { 121 | "id": 4, 122 | "pid": 0, 123 | "title": "demo", 124 | "path": "/demo", 125 | "name": "demo", 126 | "meta": { 127 | "title": "demo" 128 | }, 129 | "icon": "Wrench", 130 | "component": "/src/pages/demo/demo.vue" 131 | }, 132 | { 133 | "id": 5, 134 | "pid": 0, 135 | "title": "系统管理", 136 | "path": "/sys", 137 | "name": "system", 138 | "icon": "Wrench", 139 | "meta": { 140 | "title": "系统管理" 141 | } 142 | }, 143 | { 144 | "id": 13, 145 | "pid": 5, 146 | "title": "用户管理", 147 | "path": "/sys/user", 148 | "name": "user", 149 | "meta": { 150 | "title": "用户管理" 151 | }, 152 | "icon": "User", 153 | "component": "/src/pages/sys/user.vue" 154 | }, 155 | { 156 | "id": 14, 157 | "pid": 5, 158 | "title": "角色管理", 159 | "path": "/sys/role", 160 | "name": "role", 161 | "meta": { 162 | "title": "角色管理" 163 | }, 164 | "icon": "UserEdit", 165 | "component": "/src/pages/sys/role.vue" 166 | }, 167 | { 168 | "id": 15, 169 | "pid": 5, 170 | "title": "菜单管理", 171 | "path": "/sys/menu", 172 | "name": "menu", 173 | "meta": { 174 | "title": "菜单管理" 175 | }, 176 | "icon": "Bars", 177 | "component": "/src/pages/sys/menu.vue" 178 | } 179 | ] -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | // import Router from 'vue-router' 2 | import { inject } from "vue"; 3 | import { createRouter, createWebHistory } from "vue-router"; 4 | import Layout from "@/pages/layout/index.vue"; 5 | import { getMenuApi, getRoleMenuApi } from "@/api/sys.js"; 6 | 7 | const routes = [ 8 | { 9 | path: "/", 10 | redirect: "/home", 11 | component: Layout, 12 | children: [ 13 | { 14 | path: "/home", 15 | name: "home", 16 | meta: { 17 | title: "首页", 18 | }, 19 | component: () => import("@/pages/home/index.vue"), 20 | }, 21 | ], 22 | }, 23 | 24 | { 25 | path: "/no_right", 26 | name: "no_right", 27 | redirect: "/no_right/index", 28 | meta: { 29 | title: "权限", 30 | }, 31 | component: Layout, 32 | children: [ 33 | { 34 | path: "index", 35 | name: "no_right_index", 36 | meta: { 37 | title: "无权限", 38 | }, 39 | component: () => import("@/components/NoRight.vue"), 40 | }, 41 | ], 42 | }, 43 | 44 | { 45 | path: "/login", 46 | name: "login", 47 | component: () => import("@/pages/login.vue"), 48 | meta: { 49 | title: "登录", 50 | }, 51 | }, 52 | { 53 | path: "/404", 54 | name: "NotFound", 55 | redirect: "/404/notfound", 56 | component: () => Layout, 57 | meta: { 58 | title: "404", 59 | }, 60 | children: [ 61 | { 62 | path: "notfound", 63 | name: "notfound", 64 | meta: { 65 | title: "notfound", 66 | }, 67 | component: () => import("@/components/NotFound.vue"), 68 | }, 69 | ], 70 | }, 71 | ]; 72 | 73 | const router = createRouter({ 74 | history: createWebHistory(), 75 | routes, 76 | }); 77 | 78 | const modules = import.meta.glob("/src/pages/**/*.vue"); 79 | 80 | function formatRoutes(menu) { 81 | const newMenu = menu.map((item) => { 82 | if (item.icon) { 83 | item.icon = null; 84 | } 85 | if (item.component) { 86 | item.component = modules[item.component]; 87 | } 88 | if (item.children) { 89 | item.children = formatRoutes(item.children); 90 | } 91 | return item; 92 | }); 93 | return newMenu; 94 | } 95 | 96 | const menuFilter = (menu = [], access = []) => { 97 | return menu.filter((item) => { 98 | if (item.children) { 99 | item.children = menuFilter(item.children, access); 100 | } 101 | return access.includes(item.path); 102 | }); 103 | }; 104 | 105 | const user = localStorage.getItem("userInfo") 106 | ? JSON.parse(localStorage.getItem("userInfo")) 107 | : null; 108 | 109 | async function getRouteList() { 110 | const res = await getMenuApi(); 111 | let access=null 112 | if (user && user.role_id !== 1) { 113 | access = await getRoleMenuApi(user.role_id); 114 | 115 | } 116 | if (res.status == 200) { 117 | let routeList = formatRoutes(res.data); 118 | if (user && user.role_id !== 1) { 119 | // console.log(access) 120 | if (access.status == 200) { 121 | routeList = menuFilter(routeList, access.data.access); 122 | } 123 | } 124 | 125 | const newRoutes = routeList.map((item) => { 126 | if (item.children) { 127 | return { 128 | ...item, 129 | icon: null, 130 | redirect: item.children[0].path, 131 | component: Layout, 132 | }; 133 | } 134 | return { 135 | ...item, 136 | name: item.name + "Layout", 137 | component: Layout, 138 | children: [ 139 | { 140 | ...item, 141 | path: item.path, 142 | }, 143 | ], 144 | }; 145 | }); 146 | return newRoutes; 147 | } 148 | } 149 | 150 | let hasRoles = true; 151 | 152 | 153 | router.beforeEach(async (to, from, next) => { 154 | if (to.meta.title) { 155 | document.title = to.meta.title; 156 | } 157 | 158 | if (to.path === "/login") { 159 | next(); 160 | } else { 161 | const userStr = localStorage.getItem("userInfo"); 162 | const user = JSON.parse(userStr); 163 | if (user && user.id) { 164 | // if (/^\/sys\/.*/.test(to.path) && user.role_id != 1) { 165 | // next("/no_right/index"); 166 | // } 167 | 168 | if (hasRoles) { 169 | const routeList= await getRouteList(); 170 | routeList.forEach((item) => { 171 | router.addRoute(item); 172 | }); 173 | hasRoles = false; 174 | next({ ...to, replace: true }); 175 | } else { 176 | next(); 177 | } 178 | } else { 179 | console.log("未登录"); 180 | next("/login"); 181 | } 182 | } 183 | }); 184 | 185 | export default router; 186 | -------------------------------------------------------------------------------- /src/assets/css/common.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: #f4f4f4; 3 | 4 | } 5 | 6 | .f999 { 7 | color: #999; 8 | } 9 | 10 | .f666 { 11 | color: #666; 12 | } 13 | 14 | .f333 { 15 | color: #333; 16 | } 17 | 18 | .fff { 19 | color: #ffffff; 20 | } 21 | 22 | .bg-fff { 23 | background: #ffffff; 24 | } 25 | .bg-f4f4f4 { 26 | background: #f4f4f4; 27 | } 28 | 29 | .dsn { 30 | display: none; 31 | } 32 | 33 | .fixed { 34 | position: fixed; 35 | } 36 | 37 | .rel { 38 | position: relative; 39 | } 40 | 41 | .abs { 42 | position: absolute; 43 | } 44 | 45 | .tac { 46 | text-align: center; 47 | } 48 | 49 | .w100 { 50 | width: 100%; 51 | } 52 | .h100 { 53 | height: 100%; 54 | } 55 | 56 | /* flex公共样式 */ 57 | .flex { 58 | display: flex; 59 | } 60 | 61 | .jc-c { 62 | justify-content: center; 63 | } 64 | 65 | .jc-e { 66 | justify-content: flex-end; 67 | } 68 | 69 | .jc-sb { 70 | justify-content: space-between; 71 | } 72 | 73 | .jc-sa { 74 | justify-content: space-around; 75 | } 76 | 77 | .jc-fe{ 78 | justify-content: flex-end; 79 | } 80 | 81 | .aic { 82 | align-items: center; 83 | } 84 | 85 | .fg1 { 86 | flex-grow: 1; 87 | } 88 | 89 | .fdc { 90 | flex-direction: column; 91 | } 92 | 93 | 94 | /* 字体设置 */ 95 | .f0 { 96 | font-size: 0px 97 | } 98 | 99 | .f8 { 100 | font-size: 8px 101 | } 102 | 103 | .f10 { 104 | font-size: 12px; 105 | transform: scale(0.83); 106 | } 107 | 108 | .f12 { 109 | font-size: 12px 110 | } 111 | 112 | .f14 { 113 | font-size: 14px 114 | } 115 | 116 | .f16 { 117 | font-size: 16px 118 | } 119 | 120 | .f18 { 121 | font-size: 18px 122 | } 123 | 124 | .f20 { 125 | font-size: 20px 126 | } 127 | 128 | .f22 { 129 | font-size: 22px 130 | } 131 | 132 | .f24 { 133 | font-size: 24px 134 | } 135 | 136 | .f26 { 137 | font-size: 26px 138 | } 139 | 140 | /* margin-top设置 */ 141 | .mt-5 { 142 | margin-top: 5px; 143 | } 144 | 145 | .mt-10 { 146 | margin-top: 10px; 147 | } 148 | 149 | .mt-15 { 150 | margin-top: 15px; 151 | } 152 | 153 | .mt-20 { 154 | margin-top: 20px; 155 | } 156 | 157 | .mt-25 { 158 | margin-top: 25px; 159 | } 160 | 161 | .mt-30 { 162 | margin-top: 30px; 163 | } 164 | 165 | /* margin-bottom设置 */ 166 | .mb-5 { 167 | margin-bottom: 5px; 168 | } 169 | 170 | .mb-10 { 171 | margin-bottom: 10px; 172 | } 173 | 174 | .mb-15 { 175 | margin-bottom: 15px; 176 | } 177 | 178 | .mb-20 { 179 | margin-bottom: 20px; 180 | } 181 | 182 | .mb-25 { 183 | margin-bottom: 25px; 184 | } 185 | 186 | .mb-30 { 187 | margin-bottom: 30px; 188 | } 189 | 190 | /* margin-left设置 */ 191 | .ml-5 { 192 | margin-left: 5px; 193 | } 194 | 195 | .ml-10 { 196 | margin-left: 10px; 197 | } 198 | 199 | .ml-15 { 200 | margin-left: 15px; 201 | } 202 | 203 | .ml-20 { 204 | margin-left: 20px; 205 | } 206 | 207 | .ml-25 { 208 | margin-left: 25px; 209 | } 210 | 211 | .ml-30 { 212 | margin-left: 30px; 213 | } 214 | 215 | /* margin-right设置 */ 216 | .mr-5 { 217 | margin-right: 5px; 218 | } 219 | 220 | .mr-10 { 221 | margin-right: 10px; 222 | } 223 | 224 | .mr-15 { 225 | margin-right: 15px; 226 | } 227 | 228 | .mr-20 { 229 | margin-right: 20px; 230 | } 231 | 232 | .mr-25 { 233 | margin-right: 25px; 234 | } 235 | 236 | .mr-30 { 237 | margin-right: 30px; 238 | } 239 | 240 | /* padding-top设置 */ 241 | .pt-5 { 242 | padding-top: 5px; 243 | } 244 | 245 | .pt-10 { 246 | padding-top: 10px; 247 | } 248 | 249 | .pt-15 { 250 | padding-top: 15px; 251 | } 252 | 253 | .pt-20 { 254 | padding-top: 20px; 255 | } 256 | 257 | .pt-25 { 258 | padding-top: 25px; 259 | } 260 | 261 | .pt-30 { 262 | padding-top: 30px; 263 | } 264 | 265 | /* padding-bottom设置 */ 266 | .pb-5 { 267 | padding-bottom: 5px; 268 | } 269 | 270 | .pb-10 { 271 | padding-bottom: 10px; 272 | } 273 | 274 | .pb-15 { 275 | padding-bottom: 15px; 276 | } 277 | 278 | .pb-20 { 279 | padding-bottom: 20px; 280 | } 281 | 282 | .pb-25 { 283 | padding-bottom: 25px; 284 | } 285 | 286 | .pb-30 { 287 | padding-bottom: 30px; 288 | } 289 | 290 | /* padding-left设置 */ 291 | .pl-5 { 292 | padding-left: 5px; 293 | } 294 | 295 | .pl-10 { 296 | padding-left: 10px; 297 | } 298 | 299 | .pl-15 { 300 | padding-left: 15px; 301 | } 302 | 303 | .pl-20 { 304 | padding-left: 20px; 305 | } 306 | 307 | .pl-25 { 308 | padding-left: 25px; 309 | } 310 | 311 | .pl-30 { 312 | padding-left: 30px; 313 | } 314 | 315 | /* padding-right设置 */ 316 | .pr-5 { 317 | padding-right: 5px; 318 | } 319 | 320 | .pr-10 { 321 | padding-right: 10px; 322 | } 323 | 324 | .pr-15 { 325 | padding-right: 15px; 326 | } 327 | 328 | .pr-20 { 329 | padding-right: 20px; 330 | } 331 | 332 | .pr-25 { 333 | padding-right: 25px; 334 | } 335 | 336 | .pr-30 { 337 | padding-right: 30px; 338 | } 339 | 340 | /* 文字溢出 */ 341 | .fof { 342 | overflow: hidden; 343 | text-overflow: ellipsis; 344 | white-space: nowrap; 345 | } 346 | 347 | .red{ 348 | color: #c03131; 349 | } 350 | 351 | .pointer{ 352 | cursor: pointer; 353 | } -------------------------------------------------------------------------------- /src/pages/login.vue: -------------------------------------------------------------------------------- 1 | 57 | 58 | 164 | 165 | 188 | -------------------------------------------------------------------------------- /src/pages/sys/menu.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 224 | 225 | 230 | -------------------------------------------------------------------------------- /mock/db.json: -------------------------------------------------------------------------------- 1 | { 2 | "user": [ 3 | { 4 | "username": "superadmin", 5 | "password": "e10adc3949ba59abbe56e057f20f883e", 6 | "role_id": 1, 7 | "id": 1 8 | }, 9 | { 10 | "username": "admin", 11 | "password": "e10adc3949ba59abbe56e057f20f883e", 12 | "role_id": 2, 13 | "id": 2 14 | }, 15 | { 16 | "username": "test1", 17 | "password": "e10adc3949ba59abbe56e057f20f883e", 18 | "role_id": 3, 19 | "id": 3 20 | }, 21 | { 22 | "username": "lei1", 23 | "password": "02bdd5a0d322de0ba211cf5e1c823e69", 24 | "role_id": 2, 25 | "id": 4 26 | } 27 | ], 28 | "role": [ 29 | { 30 | "id": 1, 31 | "name": "superadmin", 32 | "description": "超级管理员" 33 | }, 34 | { 35 | "id": 2, 36 | "name": "admin", 37 | "description": "管理员", 38 | "access": [ 39 | "/home", 40 | "/echart", 41 | "/echart/line", 42 | "/echart/bar", 43 | "/echart/pie", 44 | "/echart/radar", 45 | "/echart/ring", 46 | "/form", 47 | "/form/editor", 48 | "/form/upload", 49 | "/demo", 50 | "/sys/user", 51 | "/sys/role", 52 | "/sys" 53 | ] 54 | }, 55 | { 56 | "id": 3, 57 | "name": "test", 58 | "description": "测试角色", 59 | "access": [ 60 | "/home", 61 | "/echart", 62 | "/echart/line", 63 | "/echart/bar", 64 | "/echart/pie", 65 | "/echart/radar", 66 | "/echart/ring", 67 | "/form", 68 | "/form/editor", 69 | "/form/upload" 70 | ] 71 | } 72 | ], 73 | "demo": [ 74 | { 75 | "id": 1, 76 | "name": "demo1", 77 | "description": "demo1" 78 | }, 79 | { 80 | "id": 2, 81 | "name": "demo2", 82 | "description": "demo2" 83 | }, 84 | { 85 | "id": 3, 86 | "name": "demo3", 87 | "description": "demo3" 88 | } 89 | ], 90 | "menu": [ 91 | { 92 | "id": 1, 93 | "pid": 0, 94 | "title": "首页", 95 | "path": "/home", 96 | "name": "home", 97 | "icon": "Home", 98 | "component": "/src/pages/home/index.vue", 99 | "meta": { 100 | "title": "首页" 101 | } 102 | }, 103 | { 104 | "id": 2, 105 | "pid": 0, 106 | "title": "echart组件", 107 | "path": "/echart", 108 | "name": "echart", 109 | "meta": { 110 | "title": "echart组件" 111 | }, 112 | "icon": "ChartBar" 113 | }, 114 | { 115 | "id": 6, 116 | "pid": 2, 117 | "title": "折线图", 118 | "path": "/echart/line", 119 | "name": "line", 120 | "meta": { 121 | "title": "折线图" 122 | }, 123 | "icon": "ChartBar", 124 | "component": "/src/pages/echart/line.vue" 125 | }, 126 | { 127 | "id": 7, 128 | "pid": 2, 129 | "title": "柱状图", 130 | "path": "/echart/bar", 131 | "name": "bar", 132 | "meta": { 133 | "title": "柱状图" 134 | }, 135 | "icon": "ChartBar", 136 | "component": "/src/pages/echart/bar.vue" 137 | }, 138 | { 139 | "id": 8, 140 | "pid": 2, 141 | "title": "饼图", 142 | "path": "/echart/pie", 143 | "name": "pie", 144 | "meta": { 145 | "title": "饼图" 146 | }, 147 | "icon": "ChartBar", 148 | "component": "/src/pages/echart/pie.vue" 149 | }, 150 | { 151 | "id": 9, 152 | "pid": 2, 153 | "title": "雷达图", 154 | "path": "/echart/radar", 155 | "name": "radar", 156 | "meta": { 157 | "title": "雷达图" 158 | }, 159 | "icon": "ChartBar", 160 | "component": "/src/pages/echart/radar.vue" 161 | }, 162 | { 163 | "id": 10, 164 | "pid": 2, 165 | "title": "环形图", 166 | "path": "/echart/ring", 167 | "name": "ring", 168 | "meta": { 169 | "title": "环形图" 170 | }, 171 | "icon": "ChartBar", 172 | "component": "/src/pages/echart/ring.vue" 173 | }, 174 | { 175 | "id": 3, 176 | "pid": 0, 177 | "title": "表单组件", 178 | "path": "/form", 179 | "name": "form", 180 | "meta": { 181 | "title": "表单组件" 182 | }, 183 | "icon": "Wpforms" 184 | }, 185 | { 186 | "id": 11, 187 | "pid": 3, 188 | "title": "富文本编辑器", 189 | "path": "/form/editor", 190 | "name": "editor", 191 | "meta": { 192 | "title": "富文本编辑器" 193 | }, 194 | "icon": "Edit", 195 | "component": "/src/pages/form/editor.vue" 196 | }, 197 | { 198 | "id": 12, 199 | "pid": 3, 200 | "title": "上传组件", 201 | "path": "/form/upload", 202 | "name": "upload", 203 | "meta": { 204 | "title": "上传组件" 205 | }, 206 | "icon": "Upload", 207 | "component": "/src/pages/form/upload.vue" 208 | }, 209 | { 210 | "id": 4, 211 | "pid": 0, 212 | "title": "demo", 213 | "path": "/demo", 214 | "name": "demo", 215 | "meta": { 216 | "title": "demo" 217 | }, 218 | "icon": "Wrench", 219 | "component": "/src/pages/demo/demo.vue" 220 | }, 221 | { 222 | "id": 5, 223 | "pid": 0, 224 | "title": "系统管理", 225 | "path": "/sys", 226 | "name": "system", 227 | "icon": "Wrench", 228 | "meta": { 229 | "title": "系统管理" 230 | } 231 | }, 232 | { 233 | "id": 13, 234 | "pid": 5, 235 | "title": "用户管理", 236 | "path": "/sys/user", 237 | "name": "user", 238 | "meta": { 239 | "title": "用户管理" 240 | }, 241 | "icon": "User", 242 | "component": "/src/pages/sys/user.vue" 243 | }, 244 | { 245 | "id": 14, 246 | "pid": 5, 247 | "title": "角色管理", 248 | "path": "/sys/role", 249 | "name": "role", 250 | "meta": { 251 | "title": "角色管理" 252 | }, 253 | "icon": "UserEdit", 254 | "component": "/src/pages/sys/role.vue" 255 | }, 256 | { 257 | "id": 15, 258 | "pid": 5, 259 | "title": "菜单管理", 260 | "path": "/sys/menu", 261 | "name": "menu", 262 | "meta": { 263 | "title": "菜单管理" 264 | }, 265 | "icon": "Bars", 266 | "component": "/src/pages/sys/menu.vue" 267 | }, 268 | { 269 | "icon": "AngryRegular", 270 | "name": "test1", 271 | "title": "test1", 272 | "path": "/form/test", 273 | "component": "/src/pages//form/test.vue", 274 | "pid": 3, 275 | "meta": { 276 | "title": "test1" 277 | }, 278 | "id": 16 279 | } 280 | ] 281 | } -------------------------------------------------------------------------------- /src/pages/sys/user.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 249 | -------------------------------------------------------------------------------- /src/assets/langs/zh-Hans.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * TinyMCE Language Pack 3 | * 4 | * Copyright (c) 2022 Ephox Corporation DBA Tiny Technologies, Inc. 5 | * Licensed under the Tiny commercial license. See https://www.tiny.cloud/legal/ 6 | */ 7 | tinymce.addI18n("zh-Hans",{"Redo":"\u91cd\u505a","Undo":"\u64a4\u9500","Cut":"\u526a\u5207","Copy":"\u590d\u5236","Paste":"\u7c98\u8d34","Select all":"\u5168\u9009","New document":"\u65b0\u6587\u4ef6","Ok":"\u786e\u5b9a","Cancel":"\u53d6\u6d88","Visual aids":"\u7f51\u683c\u7ebf","Bold":"\u7c97\u4f53","Italic":"\u659c\u4f53","Underline":"\u4e0b\u5212\u7ebf","Strikethrough":"\u5220\u9664\u7ebf","Superscript":"\u4e0a\u6807","Subscript":"\u4e0b\u6807","Clear formatting":"\u6e05\u9664\u683c\u5f0f","Remove":"\u79fb\u9664","Align left":"\u5de6\u5bf9\u9f50","Align center":"\u5c45\u4e2d\u5bf9\u9f50","Align right":"\u53f3\u5bf9\u9f50","No alignment":"\u672a\u5bf9\u9f50","Justify":"\u4e24\u7aef\u5bf9\u9f50","Bullet list":"\u65e0\u5e8f\u5217\u8868","Numbered list":"\u7f16\u53f7\u5217\u8868","Decrease indent":"\u51cf\u5c11\u7f29\u8fdb","Increase indent":"\u589e\u52a0\u7f29\u8fdb","Close":"\u5173\u95ed","Formats":"\u683c\u5f0f","Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X/C/V keyboard shortcuts instead.":"\u4f60\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301\u6253\u5f00\u526a\u8d34\u677f\uff0c\u8bf7\u4f7f\u7528Ctrl+X/C/V\u7b49\u5feb\u6377\u952e\u3002","Headings":"\u6807\u9898","Heading 1":"\u4e00\u7ea7\u6807\u9898","Heading 2":"\u4e8c\u7ea7\u6807\u9898","Heading 3":"\u4e09\u7ea7\u6807\u9898","Heading 4":"\u56db\u7ea7\u6807\u9898","Heading 5":"\u4e94\u7ea7\u6807\u9898","Heading 6":"\u516d\u7ea7\u6807\u9898","Preformatted":"\u9884\u5148\u683c\u5f0f\u5316\u7684","Div":"Div","Pre":"\u524d\u8a00","Code":"\u4ee3\u7801","Paragraph":"\u6bb5\u843d","Blockquote":"\u5f15\u6587\u533a\u5757","Inline":"\u6587\u672c","Blocks":"\u6837\u5f0f","Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.":"\u5f53\u524d\u4e3a\u7eaf\u6587\u672c\u7c98\u8d34\u6a21\u5f0f\uff0c\u518d\u6b21\u70b9\u51fb\u53ef\u4ee5\u56de\u5230\u666e\u901a\u7c98\u8d34\u6a21\u5f0f\u3002","Fonts":"\u5b57\u4f53","Font sizes":"\u5b57\u4f53\u5927\u5c0f","Class":"\u7c7b\u578b","Browse for an image":"\u6d4f\u89c8\u56fe\u50cf","OR":"\u6216","Drop an image here":"\u62d6\u653e\u4e00\u5f20\u56fe\u50cf\u81f3\u6b64","Upload":"\u4e0a\u4f20","Uploading image":"\u4e0a\u4f20\u56fe\u7247","Block":"\u5757","Align":"\u5bf9\u9f50","Default":"\u9884\u8bbe","Circle":"\u7a7a\u5fc3\u5706","Disc":"\u5b9e\u5fc3\u5706","Square":"\u5b9e\u5fc3\u65b9\u5757","Lower Alpha":"\u5c0f\u5199\u82f1\u6587\u5b57\u6bcd","Lower Greek":"\u5c0f\u5199\u5e0c\u814a\u5b57\u6bcd","Lower Roman":"\u5c0f\u5199\u7f57\u9a6c\u6570\u5b57","Upper Alpha":"\u5927\u5199\u82f1\u6587\u5b57\u6bcd","Upper Roman":"\u5927\u5199\u7f57\u9a6c\u6570\u5b57","Anchor...":"\u951a\u70b9...","Anchor":"\u951a\u70b9","Name":"\u540d\u79f0","ID":"ID","ID should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.":"ID\u5e94\u8be5\u4ee5\u82f1\u6587\u5b57\u6bcd\u5f00\u5934\uff0c\u540e\u9762\u53ea\u80fd\u6709\u82f1\u6587\u5b57\u6bcd\u3001\u6570\u5b57\u3001\u7834\u6298\u53f7\u3001\u70b9\u3001\u5192\u53f7\u6216\u4e0b\u5212\u7ebf\u3002","You have unsaved changes are you sure you want to navigate away?":"\u4f60\u8fd8\u6709\u6587\u6863\u5c1a\u672a\u4fdd\u5b58\uff0c\u786e\u5b9a\u8981\u79bb\u5f00\uff1f","Restore last draft":"\u6062\u590d\u4e0a\u6b21\u7684\u8349\u7a3f","Special character...":"\u7279\u6b8a\u5b57\u7b26...","Special Character":"\u7279\u6b8a\u5b57\u7b26","Source code":"\u6e90\u4ee3\u7801","Insert/Edit code sample":"\u63d2\u5165/\u7f16\u8f91\u4ee3\u7801\u793a\u4f8b","Language":"\u8bed\u8a00","Code sample...":"\u793a\u4f8b\u4ee3\u7801...","Left to right":"\u7531\u5de6\u5230\u53f3","Right to left":"\u7531\u53f3\u5230\u5de6","Title":"\u6807\u9898","Fullscreen":"\u5168\u5c4f","Action":"\u52a8\u4f5c","Shortcut":"\u5feb\u6377\u65b9\u5f0f","Help":"\u5e2e\u52a9","Address":"\u5730\u5740","Focus to menubar":"\u79fb\u52a8\u7126\u70b9\u5230\u83dc\u5355\u680f","Focus to toolbar":"\u79fb\u52a8\u7126\u70b9\u5230\u5de5\u5177\u680f","Focus to element path":"\u79fb\u52a8\u7126\u70b9\u5230\u5143\u7d20\u8def\u5f84","Focus to contextual toolbar":"\u79fb\u52a8\u7126\u70b9\u5230\u4e0a\u4e0b\u6587\u83dc\u5355","Insert link (if link plugin activated)":"\u63d2\u5165\u94fe\u63a5 (\u5982\u679c\u94fe\u63a5\u63d2\u4ef6\u5df2\u6fc0\u6d3b)","Save (if save plugin activated)":"\u4fdd\u5b58(\u5982\u679c\u4fdd\u5b58\u63d2\u4ef6\u5df2\u6fc0\u6d3b)","Find (if searchreplace plugin activated)":"\u67e5\u627e(\u5982\u679c\u67e5\u627e\u66ff\u6362\u63d2\u4ef6\u5df2\u6fc0\u6d3b)","Plugins installed ({0}):":"\u5df2\u5b89\u88c5\u63d2\u4ef6 ({0}):","Premium plugins:":"\u4f18\u79c0\u63d2\u4ef6\uff1a","Learn more...":"\u4e86\u89e3\u66f4\u591a...","You are using {0}":"\u4f60\u6b63\u5728\u4f7f\u7528 {0}","Plugins":"\u63d2\u4ef6","Handy Shortcuts":"\u5feb\u6377\u952e","Horizontal line":"\u6c34\u5e73\u5206\u5272\u7ebf","Insert/edit image":"\u63d2\u5165/\u7f16\u8f91\u56fe\u7247","Alternative description":"\u66ff\u4ee3\u63cf\u8ff0","Accessibility":"\u8f85\u52a9\u529f\u80fd","Image is decorative":"\u56fe\u50cf\u662f\u88c5\u9970\u6027\u7684","Source":"\u6e90","Dimensions":"\u5c3a\u5bf8","Constrain proportions":"\u4fdd\u6301\u6bd4\u4f8b","General":"\u4e00\u822c","Advanced":"\u9ad8\u7ea7","Style":"\u6837\u5f0f","Vertical space":"\u5782\u76f4\u95f4\u8ddd","Horizontal space":"\u6c34\u5e73\u95f4\u8ddd","Border":"\u6846\u7ebf","Insert image":"\u63d2\u5165\u56fe\u7247","Image...":"\u56fe\u7247...","Image list":"\u56fe\u7247\u6e05\u5355","Resize":"\u8c03\u6574\u5927\u5c0f","Insert date/time":"\u63d2\u5165\u65e5\u671f/\u65f6\u95f4","Date/time":"\u65e5\u671f/\u65f6\u95f4","Insert/edit link":"\u63d2\u5165/\u7f16\u8f91\u94fe\u63a5","Text to display":"\u8981\u663e\u793a\u7684\u6587\u672c","Url":"\u5730\u5740","Open link in...":"\u94fe\u63a5\u6253\u5f00\u4f4d\u7f6e...","Current window":"\u5f53\u524d\u7a97\u53e3","None":"\u65e0","New window":"\u65b0\u7a97\u53e3","Open link":"\u6253\u5f00\u94fe\u63a5","Remove link":"\u79fb\u9664\u94fe\u63a5","Anchors":"\u951a\u70b9","Link...":"\u94fe\u63a5...","Paste or type a link":"\u7c98\u8d34\u6216\u8f93\u5165\u94fe\u63a5","The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?":"\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u4e3a\u90ae\u4ef6\u5730\u5740\uff0c\u9700\u8981\u52a0\u4e0amailto:\u524d\u7f00\u5417\uff1f","The URL you entered seems to be an external link. Do you want to add the required http:// prefix?":"\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u5c5e\u4e8e\u5916\u90e8\u94fe\u63a5\uff0c\u9700\u8981\u52a0\u4e0ahttp://:\u524d\u7f00\u5417\uff1f","The URL you entered seems to be an external link. Do you want to add the required https:// prefix?":"\u60a8\u8f93\u5165\u7684 URL \u4f3c\u4e4e\u662f\u4e00\u4e2a\u5916\u90e8\u94fe\u63a5\u3002\u60a8\u60f3\u6dfb\u52a0\u6240\u9700\u7684 https:// \u524d\u7f00\u5417\uff1f","Link list":"\u94fe\u63a5\u6e05\u5355","Insert video":"\u63d2\u5165\u89c6\u9891","Insert/edit video":"\u63d2\u5165/\u7f16\u8f91\u89c6\u9891","Insert/edit media":"\u63d2\u5165/\u7f16\u8f91\u5a92\u4f53","Alternative source":"\u955c\u50cf","Alternative source URL":"\u66ff\u4ee3\u6765\u6e90\u7f51\u5740","Media poster (Image URL)":"\u5c01\u9762(\u56fe\u7247\u5730\u5740)","Paste your embed code below:":"\u5c06\u5185\u5d4c\u4ee3\u7801\u7c98\u8d34\u5728\u4e0b\u9762:","Embed":"\u5185\u5d4c","Media...":"\u591a\u5a92\u4f53...","Nonbreaking space":"\u4e0d\u95f4\u65ad\u7a7a\u683c","Page break":"\u5206\u9875\u7b26","Paste as text":"\u7c98\u8d34\u4e3a\u6587\u672c","Preview":"\u9884\u89c8","Print":"\u6253\u5370","Print...":"\u6253\u5370...","Save":"\u4fdd\u5b58","Find":"\u5bfb\u627e","Replace with":"\u66ff\u6362\u4e3a","Replace":"\u66ff\u6362","Replace all":"\u66ff\u6362\u5168\u90e8","Previous":"\u4e0a\u4e00\u4e2a","Next":"\u4e0b\u4e00\u4e2a","Find and Replace":"\u67e5\u627e\u548c\u66ff\u6362","Find and replace...":"\u67e5\u627e\u5e76\u66ff\u6362...","Could not find the specified string.":"\u672a\u627e\u5230\u641c\u7d22\u5185\u5bb9\u3002","Match case":"\u5927\u5c0f\u5199\u5339\u914d","Find whole words only":"\u5168\u5b57\u5339\u914d","Find in selection":"\u5728\u9009\u533a\u4e2d\u67e5\u627e","Insert table":"\u63d2\u5165\u8868\u683c","Table properties":"\u8868\u683c\u5c5e\u6027","Delete table":"\u5220\u9664\u8868\u683c","Cell":"\u5355\u5143\u683c","Row":"\u884c","Column":"\u680f\u76ee","Cell properties":"\u5355\u5143\u683c\u5c5e\u6027","Merge cells":"\u5408\u5e76\u5355\u5143\u683c","Split cell":"\u62c6\u5206\u5355\u5143\u683c","Insert row before":"\u5728\u4e0a\u65b9\u63d2\u5165\u884c","Insert row after":"\u5728\u4e0b\u65b9\u63d2\u5165\u884c","Delete row":"\u5220\u9664\u884c","Row properties":"\u884c\u5c5e\u6027","Cut row":"\u526a\u5207\u884c","Cut column":"\u526a\u5207\u5217","Copy row":"\u590d\u5236\u884c","Copy column":"\u590d\u5236\u5217","Paste row before":"\u7c98\u8d34\u884c\u5230\u4e0a\u65b9","Paste column before":"\u7c98\u8d34\u6b64\u5217\u524d","Paste row after":"\u7c98\u8d34\u884c\u5230\u4e0b\u65b9","Paste column after":"\u7c98\u8d34\u540e\u9762\u7684\u5217","Insert column before":"\u5728\u5de6\u4fa7\u63d2\u5165\u5217","Insert column after":"\u5728\u53f3\u4fa7\u63d2\u5165\u5217","Delete column":"\u5220\u9664\u5217","Cols":"\u5217","Rows":"\u884c\u6570","Width":"\u5bbd\u5ea6","Height":"\u9ad8\u5ea6","Cell spacing":"\u5355\u5143\u683c\u5916\u95f4\u8ddd","Cell padding":"\u5355\u5143\u683c\u5185\u8fb9\u8ddd","Row clipboard actions":"\u884c\u526a\u8d34\u677f\u64cd\u4f5c","Column clipboard actions":"\u5217\u526a\u8d34\u677f\u64cd\u4f5c","Table styles":"\u8868\u683c\u6837\u5f0f","Cell styles":"\u5355\u5143\u683c\u6837\u5f0f","Column header":"\u5217\u6807\u9898","Row header":"\u884c\u5934","Table caption":"\u8868\u683c\u6807\u9898","Caption":"\u6807\u9898","Show caption":"\u663e\u793a\u6807\u9898","Left":"\u5de6","Center":"\u5c45\u4e2d","Right":"\u53f3","Cell type":"\u50a8\u5b58\u683c\u522b","Scope":"\u8303\u56f4","Alignment":"\u5bf9\u9f50","Horizontal align":"\u6c34\u5e73\u5bf9\u9f50","Vertical align":"\u5782\u76f4\u5bf9\u9f50","Top":"\u4e0a\u65b9\u5bf9\u9f50","Middle":"\u5c45\u4e2d\u5bf9\u9f50","Bottom":"\u4e0b\u65b9\u5bf9\u9f50","Header cell":"\u8868\u5934\u5355\u5143\u683c","Row group":"\u884c\u7ec4","Column group":"\u5217\u7ec4","Row type":"\u884c\u7c7b\u578b","Header":"\u8868\u5934","Body":"\u8868\u4f53","Footer":"\u8868\u5c3e","Border color":"\u6846\u7ebf\u989c\u8272","Solid":"\u5b9e\u7ebf","Dotted":"\u865a\u7ebf","Dashed":"\u865a\u7ebf","Double":"\u53cc\u7cbe\u5ea6","Groove":"\u51f9\u69fd","Ridge":"\u6d77\u810a\u5ea7","Inset":"\u5d4c\u5165","Outset":"\u5916\u7f6e","Hidden":"\u9690\u85cf","Insert template...":"\u63d2\u5165\u6a21\u677f...","Templates":"\u6a21\u677f","Template":"\u6a21\u677f","Insert Template":"\u63d2\u5165\u6a21\u677f","Text color":"\u6587\u672c\u989c\u8272","Background color":"\u80cc\u666f\u989c\u8272","Custom...":"\u81ea\u5b9a\u4e49......","Custom color":"\u81ea\u5b9a\u4e49\u989c\u8272","No color":"\u65e0","Remove color":"\u79fb\u9664\u989c\u8272","Show blocks":"\u663e\u793a\u533a\u5757\u8fb9\u6846","Show invisible characters":"\u663e\u793a\u4e0d\u53ef\u89c1\u5b57\u7b26","Word count":"\u5b57\u6570","Count":"\u8ba1\u6570","Document":"\u6587\u6863","Selection":"\u9009\u62e9","Words":"\u5355\u8bcd","Words: {0}":"\u5b57\u6570\uff1a{0}","{0} words":"{0} \u5b57","File":"\u6587\u4ef6","Edit":"\u7f16\u8f91","Insert":"\u63d2\u5165","View":"\u67e5\u770b","Format":"\u683c\u5f0f","Table":"\u8868\u683c","Tools":"\u5de5\u5177","Powered by {0}":"\u7531{0}\u9a71\u52a8","Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help":"\u7f16\u8f91\u533a\u3002\u6309ALT-F9\u6253\u5f00\u83dc\u5355\uff0c\u6309ALT-F10\u6253\u5f00\u5de5\u5177\u680f\uff0c\u6309ALT-0\u67e5\u770b\u5e2e\u52a9","Image title":"\u56fe\u7247\u6807\u9898","Border width":"\u8fb9\u6846\u5bbd\u5ea6","Border style":"\u8fb9\u6846\u6837\u5f0f","Error":"\u9519\u8bef","Warn":"\u8b66\u544a","Valid":"\u6709\u6548","To open the popup, press Shift+Enter":"\u6309Shitf+Enter\u952e\u6253\u5f00\u5bf9\u8bdd\u6846","Rich Text Area":"\u5bcc\u6587\u672c\u533a\u57df","Rich Text Area. Press ALT-0 for help.":"\u7f16\u8f91\u533a\u3002\u6309Alt+0\u952e\u6253\u5f00\u5e2e\u52a9\u3002","System Font":"\u7cfb\u7edf\u5b57\u4f53","Failed to upload image: {0}":"\u56fe\u7247\u4e0a\u4f20\u5931\u8d25: {0}","Failed to load plugin: {0} from url {1}":"\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25: {0} \u6765\u81ea\u94fe\u63a5 {1}","Failed to load plugin url: {0}":"\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25 \u94fe\u63a5: {0}","Failed to initialize plugin: {0}":"\u63d2\u4ef6\u521d\u59cb\u5316\u5931\u8d25: {0}","example":"\u793a\u4f8b","Search":"\u641c\u7d22","All":"\u5168\u90e8","Currency":"\u8d27\u5e01","Text":"\u6587\u5b57","Quotations":"\u5f15\u7528","Mathematical":"\u6570\u5b66","Extended Latin":"\u62c9\u4e01\u8bed\u6269\u5145","Symbols":"\u7b26\u53f7","Arrows":"\u7bad\u5934","User Defined":"\u81ea\u5b9a\u4e49","dollar sign":"\u7f8e\u5143\u7b26\u53f7","currency sign":"\u8d27\u5e01\u7b26\u53f7","euro-currency sign":"\u6b27\u5143\u7b26\u53f7","colon sign":"\u5192\u53f7","cruzeiro sign":"\u514b\u9c81\u8d5b\u7f57\u5e01\u7b26\u53f7","french franc sign":"\u6cd5\u90ce\u7b26\u53f7","lira sign":"\u91cc\u62c9\u7b26\u53f7","mill sign":"\u5bc6\u5c14\u7b26\u53f7","naira sign":"\u5948\u62c9\u7b26\u53f7","peseta sign":"\u6bd4\u585e\u5854\u7b26\u53f7","rupee sign":"\u5362\u6bd4\u7b26\u53f7","won sign":"\u97e9\u5143\u7b26\u53f7","new sheqel sign":"\u65b0\u8c22\u514b\u5c14\u7b26\u53f7","dong sign":"\u8d8a\u5357\u76fe\u7b26\u53f7","kip sign":"\u8001\u631d\u57fa\u666e\u7b26\u53f7","tugrik sign":"\u56fe\u683c\u91cc\u514b\u7b26\u53f7","drachma sign":"\u5fb7\u62c9\u514b\u9a6c\u7b26\u53f7","german penny symbol":"\u5fb7\u56fd\u4fbf\u58eb\u7b26\u53f7","peso sign":"\u6bd4\u7d22\u7b26\u53f7","guarani sign":"\u74dc\u62c9\u5c3c\u7b26\u53f7","austral sign":"\u6fb3\u5143\u7b26\u53f7","hryvnia sign":"\u683c\u91cc\u592b\u5c3c\u4e9a\u7b26\u53f7","cedi sign":"\u585e\u5730\u7b26\u53f7","livre tournois sign":"\u91cc\u5f17\u5f17\u5c14\u7b26\u53f7","spesmilo sign":"spesmilo\u7b26\u53f7","tenge sign":"\u575a\u6208\u7b26\u53f7","indian rupee sign":"\u5370\u5ea6\u5362\u6bd4","turkish lira sign":"\u571f\u8033\u5176\u91cc\u62c9","nordic mark sign":"\u5317\u6b27\u9a6c\u514b","manat sign":"\u9a6c\u7eb3\u7279\u7b26\u53f7","ruble sign":"\u5362\u5e03\u7b26\u53f7","yen character":"\u65e5\u5143\u5b57\u6837","yuan character":"\u4eba\u6c11\u5e01\u5143\u5b57\u6837","yuan character, in hong kong and taiwan":"\u5143\u5b57\u6837\uff08\u6e2f\u53f0\u5730\u533a\uff09","yen/yuan character variant one":"\u5143\u5b57\u6837\uff08\u5927\u5199\uff09","Emojis":"Emojis","Emojis...":"Emojis...","Loading emojis...":"\u6b63\u5728\u52a0\u8f7dEmojis...","Could not load emojis":"\u65e0\u6cd5\u52a0\u8f7dEmojis","People":"\u4eba\u7c7b","Animals and Nature":"\u52a8\u7269\u548c\u81ea\u7136","Food and Drink":"\u98df\u7269\u548c\u996e\u54c1","Activity":"\u6d3b\u52a8","Travel and Places":"\u65c5\u6e38\u548c\u5730\u70b9","Objects":"\u7269\u4ef6","Flags":"\u65d7\u5e1c","Characters":"\u5b57\u7b26","Characters (no spaces)":"\u5b57\u7b26(\u65e0\u7a7a\u683c)","{0} characters":"{0} \u4e2a\u5b57\u7b26","Error: Form submit field collision.":"\u9519\u8bef: \u8868\u5355\u63d0\u4ea4\u5b57\u6bb5\u51b2\u7a81\u3002","Error: No form element found.":"\u9519\u8bef: \u6ca1\u6709\u8868\u5355\u63a7\u4ef6\u3002","Color swatch":"\u989c\u8272\u6837\u672c","Color Picker":"\u9009\u8272\u5668","Invalid hex color code: {0}":"\u5341\u516d\u8fdb\u5236\u989c\u8272\u4ee3\u7801\u65e0\u6548\uff1a {0}","Invalid input":"\u65e0\u6548\u8f93\u5165","R":"R","Red component":"\u7ea2\u8272\u90e8\u5206","G":"G","Green component":"\u7eff\u8272\u90e8\u5206","B":"B","Blue component":"\u767d\u8272\u90e8\u5206","#":"#","Hex color code":"\u5341\u516d\u8fdb\u5236\u989c\u8272\u4ee3\u7801","Range 0 to 255":"\u8303\u56f40\u81f3255","Turquoise":"\u9752\u7eff\u8272","Green":"\u7eff\u8272","Blue":"\u84dd\u8272","Purple":"\u7d2b\u8272","Navy Blue":"\u6d77\u519b\u84dd","Dark Turquoise":"\u6df1\u84dd\u7eff\u8272","Dark Green":"\u6df1\u7eff\u8272","Medium Blue":"\u4e2d\u84dd\u8272","Medium Purple":"\u4e2d\u7d2b\u8272","Midnight Blue":"\u6df1\u84dd\u8272","Yellow":"\u9ec4\u8272","Orange":"\u6a59\u8272","Red":"\u7ea2\u8272","Light Gray":"\u6d45\u7070\u8272","Gray":"\u7070\u8272","Dark Yellow":"\u6697\u9ec4\u8272","Dark Orange":"\u6df1\u6a59\u8272","Dark Red":"\u6df1\u7ea2\u8272","Medium Gray":"\u4e2d\u7070\u8272","Dark Gray":"\u6df1\u7070\u8272","Light Green":"\u6d45\u7eff\u8272","Light Yellow":"\u6d45\u9ec4\u8272","Light Red":"\u6d45\u7ea2\u8272","Light Purple":"\u6d45\u7d2b\u8272","Light Blue":"\u6d45\u84dd\u8272","Dark Purple":"\u6df1\u7d2b\u8272","Dark Blue":"\u6df1\u84dd\u8272","Black":"\u9ed1\u8272","White":"\u767d\u8272","Switch to or from fullscreen mode":"\u5207\u6362\u5168\u5c4f\u6a21\u5f0f","Open help dialog":"\u6253\u5f00\u5e2e\u52a9\u5bf9\u8bdd\u6846","history":"\u5386\u53f2","styles":"\u6837\u5f0f","formatting":"\u683c\u5f0f\u5316","alignment":"\u5bf9\u9f50","indentation":"\u7f29\u8fdb","Font":"\u5b57\u4f53","Size":"\u5b57\u53f7","More...":"\u66f4\u591a...","Select...":"\u9009\u62e9...","Preferences":"\u9996\u9009\u9879","Yes":"\u662f","No":"\u5426","Keyboard Navigation":"\u952e\u76d8\u6307\u5f15","Version":"\u7248\u672c","Code view":"\u4ee3\u7801\u89c6\u56fe","Open popup menu for split buttons":"\u6253\u5f00\u5f39\u51fa\u5f0f\u83dc\u5355\uff0c\u7528\u4e8e\u62c6\u5206\u6309\u94ae","List Properties":"\u5217\u8868\u5c5e\u6027","List properties...":"\u6807\u9898\u5b57\u4f53\u5c5e\u6027","Start list at number":"\u4ee5\u6570\u5b57\u5f00\u59cb\u5217\u8868","Line height":"\u884c\u9ad8","Dropped file type is not supported":"\u6b64\u6587\u4ef6\u7c7b\u578b\u4e0d\u652f\u6301\u62d6\u653e","Loading...":"\u52a0\u8f7d\u4e2d...","ImageProxy HTTP error: Rejected request":"\u56fe\u7247\u4ee3\u7406\u8bf7\u6c42\u9519\u8bef\uff1a\u8bf7\u6c42\u88ab\u62d2\u7edd","ImageProxy HTTP error: Could not find Image Proxy":"\u56fe\u7247\u4ee3\u7406\u8bf7\u6c42\u9519\u8bef\uff1a\u65e0\u6cd5\u627e\u5230\u56fe\u7247\u4ee3\u7406","ImageProxy HTTP error: Incorrect Image Proxy URL":"\u56fe\u7247\u4ee3\u7406\u8bf7\u6c42\u9519\u8bef\uff1a\u56fe\u7247\u4ee3\u7406\u5730\u5740\u9519\u8bef","ImageProxy HTTP error: Unknown ImageProxy error":"\u56fe\u7247\u4ee3\u7406\u8bf7\u6c42\u9519\u8bef\uff1a\u672a\u77e5\u7684\u56fe\u7247\u4ee3\u7406\u9519\u8bef"}); --------------------------------------------------------------------------------