初始化
2
admin-web/javascript-ant-design-vue/.env
Normal file
@ -0,0 +1,2 @@
|
||||
|
||||
VITE_APP_PROJECT_TITLE = 'SmartAdmin'
|
7
admin-web/javascript-ant-design-vue/.env.development
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
VITE_APP_API_URL = 'http://localhost:10086/'
|
||||
|
||||
VITE_APP_PROJECT_TITLE = 'SmartAdmin Dev'
|
||||
|
||||
VITE_APP_PROFILE = 'dev'
|
||||
VITE_APP_MODE = 'development'
|
7
admin-web/javascript-ant-design-vue/.env.localhost
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
VITE_APP_API_URL = 'http://127.0.0.1:10086/admin'
|
||||
|
||||
VITE_APP_PROJECT_TITLE = 'SmartAdmin Localhost'
|
||||
|
||||
VITE_APP_PROFILE = 'local'
|
||||
VITE_APP_MODE = 'local'
|
8
admin-web/javascript-ant-design-vue/.env.pre
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
VITE_APP_API_URL = 'http://localhost:10086/api'
|
||||
|
||||
VITE_APP_PROJECT_TITLE = 'SmartAdmin PRE'
|
||||
|
||||
VITE_APP_PROFILE = 'pre'
|
||||
|
||||
VITE_APP_MODE = 'development'
|
6
admin-web/javascript-ant-design-vue/.env.production
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
VITE_APP_API_URL = 'http://localhost:10086/api'
|
||||
|
||||
VITE_APP_PROFILE = 'prod'
|
||||
|
||||
VITE_APP_MODE = 'production'
|
7
admin-web/javascript-ant-design-vue/.env.sit
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
VITE_APP_API_URL = 'http://sit-xmf-crm.renminyixue.cn/api/admin'
|
||||
|
||||
VITE_APP_PROJECT_TITLE = 'SmartAdmin Sit'
|
||||
|
||||
VITE_APP_PROFILE = 'sit'
|
||||
VITE_APP_MODE = 'development'
|
17
admin-web/javascript-ant-design-vue/.eslintignore
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
*.sh
|
||||
node_modules
|
||||
lib
|
||||
*.md
|
||||
*.woff
|
||||
*.ttf
|
||||
.vscode
|
||||
.idea
|
||||
dist
|
||||
public
|
||||
/docs
|
||||
.husky
|
||||
.local
|
||||
/bin
|
||||
Dockerfile
|
||||
src/assets
|
76
admin-web/javascript-ant-design-vue/.eslintrc.js
Normal file
@ -0,0 +1,76 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
browser: true,
|
||||
es2021: true,
|
||||
node: true,
|
||||
},
|
||||
parser: 'vue-eslint-parser',
|
||||
parserOptions: {
|
||||
ecmaVersion: 12,
|
||||
parser: '@typescript-eslint/parser',
|
||||
sourceType: 'module',
|
||||
},
|
||||
extends: [
|
||||
'plugin:vue/vue3-essential',
|
||||
'eslint:recommended',
|
||||
'plugin:vue/base'
|
||||
],
|
||||
globals: {
|
||||
defineProps: "readonly",
|
||||
defineEmits: "readonly",
|
||||
defineExpose: "readonly",
|
||||
withDefaults: "readonly"
|
||||
},
|
||||
plugins: ['vue', '@typescript-eslint'],
|
||||
rules: {
|
||||
'@typescript-eslint/ban-ts-ignore': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-var-requires': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
'vue/custom-event-name-casing': 'off',
|
||||
'no-use-before-define': 'off',
|
||||
'@typescript-eslint/no-use-before-define': 'off',
|
||||
'@typescript-eslint/ban-ts-comment': 'off',
|
||||
'@typescript-eslint/ban-types': 'off',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
// we are only using this rule to check for unused arguments since TS
|
||||
// catches unused variables but not args.
|
||||
{ varsIgnorePattern: '.*', args: 'none' }
|
||||
],
|
||||
'no-unused-vars': [
|
||||
'error',
|
||||
// we are only using this rule to check for unused arguments since TS
|
||||
// catches unused variables but not args.
|
||||
{ varsIgnorePattern: '.*', args: 'none' }
|
||||
],
|
||||
'space-before-function-paren': 'off',
|
||||
|
||||
'vue/attributes-order': 'off',
|
||||
'vue/one-component-per-file': 'off',
|
||||
'vue/html-closing-bracket-newline': 'off',
|
||||
'vue/max-attributes-per-line': 'off',
|
||||
'vue/multiline-html-element-content-newline': 'off',
|
||||
'vue/singleline-html-element-content-newline': 'off',
|
||||
'vue/attribute-hyphenation': 'off',
|
||||
'vue/require-default-prop': 'off',
|
||||
'vue/html-self-closing': [
|
||||
'error',
|
||||
{
|
||||
html: {
|
||||
void: 'always',
|
||||
normal: 'never',
|
||||
component: 'always',
|
||||
},
|
||||
svg: 'always',
|
||||
math: 'always',
|
||||
},
|
||||
],
|
||||
// Enable vue/script-setup-uses-vars rule
|
||||
'vue/script-setup-uses-vars': 'error',
|
||||
}
|
||||
};
|
6
admin-web/javascript-ant-design-vue/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
.idea
|
21
admin-web/javascript-ant-design-vue/.prettierrc.js
Normal file
@ -0,0 +1,21 @@
|
||||
module.exports = {
|
||||
printWidth: 150,// 每行字符长度
|
||||
tabWidth: 2,// 缩进空格数
|
||||
useTabs: false,//不用tab缩进
|
||||
semi: true,//// 在语句末尾打印分号
|
||||
singleQuote: true,// 使用单引号而不是双引号
|
||||
vueIndentScriptAndStyle: true,//Vue文件脚本和样式标签缩进
|
||||
quoteProps: 'as-needed',// 更改引用对象属性的时间 可选值"<as-needed|consistent|preserve>"
|
||||
jsxSingleQuote: false,// 在JSX中使用单引号而不是双引号
|
||||
trailingComma: 'es5',//多行时尽可能打印尾随逗号。(例如,单行数组永远不会出现逗号结尾。) 可选值"<none|es5|all>",默认none
|
||||
bracketSpacing: true,// 在对象文字中的括号之间打印空格
|
||||
jsxBracketSameLine: false,//jsx 标签的反尖括号需要换行
|
||||
arrowParens: 'always',// 在单独的箭头函数参数周围包括括号 always:(x) => x \ avoid:x => x
|
||||
rangeStart: 0,// 这两个选项可用于格式化以给定字符偏移量(分别包括和不包括)开始和结束的代码
|
||||
rangeEnd: Infinity,
|
||||
requirePragma: false,// 指定要使用的解析器,不需要写文件开头的 @prettier
|
||||
insertPragma: false,// 不需要自动在文件开头插入 @prettier
|
||||
proseWrap: 'preserve',// 使用默认的折行标准 always\never\preserve
|
||||
htmlWhitespaceSensitivity: 'css',// 指定HTML文件的全局空格敏感度 css\strict\ignore
|
||||
endOfLine: 'lf',// 换行符使用 lf 结尾是 可选值"<auto|lf|crlf|cr>"
|
||||
};
|
3
admin-web/javascript-ant-design-vue/.stylelintignore
Normal file
@ -0,0 +1,3 @@
|
||||
/dist/*
|
||||
/public/*
|
||||
public/*
|
70
admin-web/javascript-ant-design-vue/.stylelintrc.js
Normal file
@ -0,0 +1,70 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
plugins: ['stylelint-order'],
|
||||
extends: ['stylelint-config-standard', 'stylelint-config-prettier'],
|
||||
rules: {
|
||||
'selector-pseudo-class-no-unknown': [
|
||||
true,
|
||||
{
|
||||
ignorePseudoClasses: ['global'],
|
||||
},
|
||||
],
|
||||
'selector-pseudo-element-no-unknown': [
|
||||
true,
|
||||
{
|
||||
ignorePseudoElements: ['v-deep'],
|
||||
},
|
||||
],
|
||||
'at-rule-no-unknown': [
|
||||
true,
|
||||
{
|
||||
ignoreAtRules: [
|
||||
'tailwind',
|
||||
'apply',
|
||||
'variants',
|
||||
'responsive',
|
||||
'screen',
|
||||
'function',
|
||||
'if',
|
||||
'each',
|
||||
'include',
|
||||
'mixin',
|
||||
],
|
||||
},
|
||||
],
|
||||
'no-empty-source': null,
|
||||
'named-grid-areas-no-invalid': null,
|
||||
'unicode-bom': 'never',
|
||||
'no-descending-specificity': null,
|
||||
'font-family-no-missing-generic-family-keyword': null,
|
||||
'declaration-colon-space-after': 'always-single-line',
|
||||
'declaration-colon-space-before': 'never',
|
||||
// 'declaration-block-trailing-semicolon': 'always',
|
||||
'rule-empty-line-before': [
|
||||
'always',
|
||||
{
|
||||
ignore: ['after-comment', 'first-nested'],
|
||||
},
|
||||
],
|
||||
'unit-no-unknown': [true, { ignoreUnits: ['rpx'] }],
|
||||
'order/order': [
|
||||
[
|
||||
'dollar-variables',
|
||||
'custom-properties',
|
||||
'at-rules',
|
||||
'declarations',
|
||||
{
|
||||
type: 'at-rule',
|
||||
name: 'supports',
|
||||
},
|
||||
{
|
||||
type: 'at-rule',
|
||||
name: 'media',
|
||||
},
|
||||
'rules',
|
||||
],
|
||||
{ severity: 'warning' },
|
||||
],
|
||||
},
|
||||
ignoreFiles: ['**/*.js', '**/*.jsx', '**/*.tsx', '**/*.ts'],
|
||||
};
|
36
admin-web/javascript-ant-design-vue/README.en.md
Normal file
@ -0,0 +1,36 @@
|
||||
__# smart-admin2
|
||||
|
||||
#### Description
|
||||
{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}
|
||||
|
||||
#### Software Architecture
|
||||
Software architecture description
|
||||
|
||||
#### Installation
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Instructions
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Contribution
|
||||
|
||||
1. Fork the repository
|
||||
2. Create Feat_xxx branch
|
||||
3. Commit your code
|
||||
4. Create Pull Request
|
||||
|
||||
|
||||
#### Gitee Feature
|
||||
|
||||
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
|
||||
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
|
||||
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
|
||||
4. The most valuable open source project [GVP](https://gitee.com/gvp)
|
||||
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
|
||||
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
0
admin-web/javascript-ant-design-vue/README.md
Normal file
24
admin-web/javascript-ant-design-vue/index.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!--
|
||||
* @Description:
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-03
|
||||
* @LastEditTime: 2021-09-01
|
||||
* @LastEditors: zhuoda
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" id="htmlRoot">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
|
||||
<meta name="renderer" content="webkit"/>
|
||||
<meta name="viewport"
|
||||
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
|
||||
/>
|
||||
<title>SmartAdmin</title>
|
||||
<link rel="icon" href="/favicon.ico"/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
5012
admin-web/javascript-ant-design-vue/package-lock.json
generated
Normal file
64
admin-web/javascript-ant-design-vue/package.json
Normal file
@ -0,0 +1,64 @@
|
||||
{
|
||||
"version": "0.0.0",
|
||||
"author": {
|
||||
"name": "1024lab",
|
||||
"email": "1024lab@sina.com",
|
||||
"url": "https://1024lab.net"
|
||||
},
|
||||
"license": "MIT",
|
||||
"homepage": "https://smartadmin.1024lab.net",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"sit": "vite build --base=/manage/ --mode sit",
|
||||
"localhost": "vite --mode localhost",
|
||||
"build": "vue-tsc --noEmit && vite build",
|
||||
"serve": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"ant-design-vue": "2.2.4",
|
||||
"axios": "^0.21.1",
|
||||
"clipboard": "^2.0.8",
|
||||
"crypto-js": "^4.0.0",
|
||||
"echarts": "^5.1.2",
|
||||
"js-cookie": "^2.2.1",
|
||||
"mitt": "^3.0.0",
|
||||
"moment": "2.29.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.0.0-beta.3",
|
||||
"vue-enum": "~1.0.5",
|
||||
"vue": "^3.2.1",
|
||||
"vue-i18n": "9.1.6",
|
||||
"vue-router": "^4.0.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-legacy": "^1.5.1",
|
||||
"@vitejs/plugin-vue": "^1.4.0",
|
||||
"@vue/compiler-sfc": "^3.2.1",
|
||||
"dotenv": "^10.0.0",
|
||||
"eslint": "^7.29.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-prettier": "^3.4.0",
|
||||
"eslint-plugin-vue": "^7.16.0",
|
||||
"less": "^4.1.1",
|
||||
"less-loader": "^10.0.1",
|
||||
"postcss": "^8.3.5",
|
||||
"prettier": "^2.3.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"stylelint": "^13.13.1",
|
||||
"stylelint-config-prettier": "^8.0.2",
|
||||
"stylelint-config-standard": "^22.0.0",
|
||||
"stylelint-order": "^4.1.0",
|
||||
"v-viewer": "^1.5.1",
|
||||
"vite": "^2.4.4",
|
||||
"vite-plugin-mock": "^2.9.4",
|
||||
"vite-plugin-style-import": "^1.1.1",
|
||||
"vue-eslint-parser": "^7.10.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/1024-lab/smart-admin.git"
|
||||
}
|
||||
}
|
5
admin-web/javascript-ant-design-vue/postcss.config.js
Normal file
@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
BIN
admin-web/javascript-ant-design-vue/public/favicon.ico
Normal file
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 27 KiB |
BIN
admin-web/javascript-ant-design-vue/public/images/ali-icon.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 6.1 KiB |
BIN
admin-web/javascript-ant-design-vue/public/images/login-bg.png
Normal file
After Width: | Height: | Size: 1.7 MiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 6.4 KiB |
After Width: | Height: | Size: 98 KiB |
BIN
admin-web/javascript-ant-design-vue/public/images/login-qr.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
admin-web/javascript-ant-design-vue/public/images/logo-min.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
admin-web/javascript-ant-design-vue/public/images/logo.png
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
admin-web/javascript-ant-design-vue/public/images/qq-icon.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 6.5 KiB |
BIN
admin-web/javascript-ant-design-vue/public/images/weibo-icon.png
Normal file
After Width: | Height: | Size: 7.6 KiB |
50
admin-web/javascript-ant-design-vue/src/App.vue
Normal file
@ -0,0 +1,50 @@
|
||||
<!--
|
||||
* @Description: App
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-03
|
||||
* @LastEditTime: 2021-08-28
|
||||
* @LastEditors: zhuoda
|
||||
-->
|
||||
<template>
|
||||
<a-config-provider :locale="zh_CN">
|
||||
<!---全局loading,常用于表单提交--->
|
||||
<a-spin :spinning="spinning" size="large">
|
||||
<RouterView />
|
||||
</a-spin>
|
||||
</a-config-provider>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import zh_CN from "ant-design-vue/lib/locale-provider/zh_CN";
|
||||
import { onMounted, computed } from "vue";
|
||||
import { loginApi } from "./api/system/login/login";
|
||||
import { useUserStore } from "./store/modules/system/user";
|
||||
import { useAppConfigStore } from "/@/store/modules/system/app-config";
|
||||
import { useSpinStore } from "/@/store/modules/system/spin";
|
||||
|
||||
let spinStore = useSpinStore();
|
||||
const spinning = computed(() => spinStore.loading);
|
||||
|
||||
async function getLoginInfo() {
|
||||
let token = useUserStore().getToken;
|
||||
if (!token) return;
|
||||
const res = await loginApi.getLogin();
|
||||
useUserStore().setUserMenu(res.data);
|
||||
}
|
||||
|
||||
// 更新屏幕宽度,以判断是否为isMobile模式,进行适配
|
||||
let appConfigStore = useAppConfigStore();
|
||||
function triggerReSize() {
|
||||
appConfigStore.setCurrentScreenWidth(document.body.clientWidth);
|
||||
}
|
||||
onMounted(() => {
|
||||
//获取登录信息
|
||||
getLoginInfo();
|
||||
//更新屏幕宽度
|
||||
triggerReSize();
|
||||
});
|
||||
|
||||
window.onresize = () => {
|
||||
triggerReSize();
|
||||
};
|
||||
</script>
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-12 16:46:21
|
||||
* @LastEditTime: 2021-08-12 16:47:04
|
||||
* @LastEditors: zhuoda
|
||||
*/
|
||||
import { postRequest } from '/@/lib/axios';
|
||||
|
||||
export const categoryApi = {
|
||||
// 添加类目 by zhuoda
|
||||
addCategory: (param) => {
|
||||
return postRequest('/category/add', param);
|
||||
},
|
||||
// GET
|
||||
// 删除类目 by zhuoda
|
||||
deleteCategoryById: (categoryId) => {
|
||||
return getRequest(`/category/del/${categoryId}`);
|
||||
},
|
||||
// 查询类目层级树 by zhuoda
|
||||
queryCategoryTree: (param) => {
|
||||
return postRequest('/category/tree', param);
|
||||
},
|
||||
// 更新类目 by zhuoda
|
||||
updateCategory: (param) => {
|
||||
return postRequest('/category/update', param);
|
||||
},
|
||||
// 查询类目详情 by zhuoda
|
||||
getCategory: (categoryId) => {
|
||||
// POST /admin/clue/user/track/add
|
||||
return getRequest(`/category/${categoryId}`);
|
||||
},
|
||||
};
|
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @version:
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-17 23:32:36
|
||||
* @LastEditors: zhuoda
|
||||
* @LastEditTime: 2021-08-18 14:35:52
|
||||
*/
|
||||
import { postRequest } from '/@/lib/axios';
|
||||
|
||||
export const fileApi = {
|
||||
// 文件上传 by zhuoda
|
||||
uploadUrl: '/file/upload',
|
||||
uploadFile: (param, folder) => {
|
||||
return postRequest(`/file/upload?folder=${folder}`, param);
|
||||
},
|
||||
};
|
@ -0,0 +1,23 @@
|
||||
import { postRequest } from '/@/lib/axios';
|
||||
|
||||
export const goodsApi = {
|
||||
// 添加商品 by zhuoda
|
||||
addGoods: (param) => {
|
||||
return postRequest('/goods/add', param);
|
||||
},
|
||||
// POST /admin/goods/del
|
||||
// 删除 by zhuoda
|
||||
deleteGoods: (param) => {
|
||||
return postRequest('/goods/del', param);
|
||||
},
|
||||
// POST /admin/goods/query
|
||||
// 分页查询 by zhuoda
|
||||
queryGoodsList: (param) => {
|
||||
return postRequest('/goods/query', param);
|
||||
},
|
||||
// POST /admin/goods/update
|
||||
// 更新商品 by zhuoda
|
||||
updateGoods: (param) => {
|
||||
return postRequest('/goods/update', param);
|
||||
}
|
||||
};
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-12 17:56:25
|
||||
* @LastEditTime: 2021-08-16 10:45:05
|
||||
* @LastEditors: zhuoda
|
||||
* @Description:
|
||||
* @FilePath: /smart-admin/src/api/system/department/department-api.ts
|
||||
*/
|
||||
import { getRequest, postRequest } from '/@/lib/axios';
|
||||
|
||||
export const departmentApi = {
|
||||
/**
|
||||
* @description: 查询部门列表
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
queryAllDepartment: () => {
|
||||
return getRequest('/department/listAll');
|
||||
},
|
||||
|
||||
/**
|
||||
* @description: 查询部门树形列表
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
departmentTree: () => {
|
||||
return getRequest('/department/treeList');
|
||||
},
|
||||
|
||||
/**
|
||||
* @description: 获取校区列表 by zhuoda
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
querySchoolDepartmentList: () => {
|
||||
return getRequest('/department/querySchoolList');
|
||||
},
|
||||
|
||||
/**
|
||||
* @description: 添加部门 by zhuoda
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
addDepartment: (param) => {
|
||||
return postRequest('/department/add', param);
|
||||
},
|
||||
/**
|
||||
* @description: 更新部门信息 by zhuoda
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
updateDepartment: (param) => {
|
||||
return postRequest('/department/update', param);
|
||||
},
|
||||
/**
|
||||
* @description: 获取校区列表 by zhuoda
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
deleteDepartment: (deptId) => {
|
||||
return getRequest(`/department/delete/${deptId}`);
|
||||
},
|
||||
};
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* @Description: 员工api
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-12 18:00:56
|
||||
* @LastEditTime: 2021-08-25 11:24:51
|
||||
* @LastEditors: zhuoda
|
||||
*/
|
||||
|
||||
import { getRequest, postRequest } from '/@/lib/axios';
|
||||
|
||||
export const employeeApi = {
|
||||
/**
|
||||
* @description: 查询所有员工 by zhuoda
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
queryAll: () => {
|
||||
return getRequest('/employee/queryAll');
|
||||
},
|
||||
/**
|
||||
* @description: 员工管理查询
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
queryEmployee: (params) => {
|
||||
return postRequest('/employee/query', params);
|
||||
},
|
||||
/**
|
||||
* @description: 添加员工
|
||||
* @param {EmployeeAddDto} params
|
||||
* @return {*}
|
||||
*/
|
||||
addEmployee: (params) => {
|
||||
return postRequest('/employee/add', params);
|
||||
},
|
||||
/**
|
||||
* @description: 更新员工信息
|
||||
* @param {EmployeeUpdateDto} params
|
||||
* @return {*}
|
||||
*/
|
||||
updateEmployee: (params) => {
|
||||
return postRequest('/employee/update', params);
|
||||
},
|
||||
/**
|
||||
* @description: 删除员工
|
||||
* @param {number} employeeId
|
||||
* @return {*}
|
||||
*/
|
||||
deleteEmployee: (employeeId) => {
|
||||
return getRequest(`/employee/delete/${employeeId}`);
|
||||
},
|
||||
/**
|
||||
* @description: 批量删除员工
|
||||
* @param {number} employeeIdList
|
||||
* @return {*}
|
||||
*/
|
||||
batchDeleteEmployee: (employeeIdList) => {
|
||||
return getRequest(`/employee/update/batch/delete?employeeIdList=${employeeIdList}`);
|
||||
},
|
||||
/**
|
||||
* @description: 批量调整员工部门
|
||||
* @param {EmployeeDepartmentUpdateDto} updateDto
|
||||
* @return {*}
|
||||
*/
|
||||
batchUpdateDepartmentEmployee: (updateDto) => {
|
||||
return postRequest('/employee/update/batch/department', updateDto);
|
||||
},
|
||||
/**
|
||||
* @description: 重置员工密码
|
||||
* @param {number} employeeId
|
||||
* @return {*}
|
||||
*/
|
||||
resetPassword: (employeeId) => {
|
||||
return getRequest(`employee/update/pwd/reset/${employeeId}`);
|
||||
},
|
||||
/**
|
||||
* @description: 更新员工禁用状态
|
||||
* @param {number} employeeId
|
||||
* @return {*}
|
||||
*/
|
||||
updateDisabled: (employeeId) => {
|
||||
return getRequest(`employee/update/disabled/${employeeId}`);
|
||||
},
|
||||
/**
|
||||
* @description: 查询员工-根据校区id
|
||||
* @param {number} deptId
|
||||
* @return {*}
|
||||
*/
|
||||
querySchoolEmployee: (deptId) => {
|
||||
return getRequest(`/employee/query/school/${deptId}`);
|
||||
},
|
||||
// 查询员工-根据部门id
|
||||
queryEmployeeByDeptId: (deptId) => {
|
||||
return getRequest(`/employee/query/dept/${deptId}`);
|
||||
},
|
||||
};
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-24 17:21:35
|
||||
* @LastEditTime: 2021-08-24 17:24:31
|
||||
* @LastEditors: zhuoda
|
||||
* @Description:
|
||||
* @FilePath: /smart-admin/src/api/system/home/home-api.ts
|
||||
*/
|
||||
import { getRequest } from '/@/lib/axios';
|
||||
|
||||
export const homeApi = {
|
||||
/**
|
||||
* @description: 首页-金额统计(业绩、收款、订单数等) by zhuoda
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
homeAmountStatistics: () => {
|
||||
return getRequest('/home/amount/statistics');
|
||||
},
|
||||
/**
|
||||
* @description: 首页-待办信息 by zhuoda
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
homeWaitHandle: () => {
|
||||
return getRequest('home/wait/handle');
|
||||
},
|
||||
};
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-03 10:27:11
|
||||
* @LastEditTime: 2021-08-18 20:04:05
|
||||
* @LastEditors: zhuoda
|
||||
* @Description:
|
||||
* @FilePath: /smart-admin/src/api/system/login/login.ts
|
||||
*/
|
||||
import { getRequest, postRequest } from '/@/lib/axios';
|
||||
|
||||
export const loginApi = {
|
||||
/**
|
||||
* 登录
|
||||
* @param param
|
||||
*/
|
||||
login: (param) => {
|
||||
return postRequest('/system/login', param);
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取登录信息
|
||||
* @param param
|
||||
*/
|
||||
getLogin: () => {
|
||||
return getRequest('/system/login/get');
|
||||
},
|
||||
};
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-11 22:15:04
|
||||
* @LastEditTime: 2021-09-01 20:21:29
|
||||
* @LastEditors: zhuoda
|
||||
* @Description:
|
||||
* @FilePath: /smart-admin/src/api/system/menu/menu-api.ts
|
||||
*/
|
||||
import { getRequest, postRequest } from '/@/lib/axios';
|
||||
|
||||
export const menuApi = {
|
||||
/**
|
||||
* 添加菜单
|
||||
*/
|
||||
addMenu: (param) => {
|
||||
return postRequest('/menu/add', param);
|
||||
},
|
||||
|
||||
/**
|
||||
* 更新菜单
|
||||
*/
|
||||
updateMenu: (pa) => {
|
||||
return postRequest('/menu/update', param);
|
||||
},
|
||||
|
||||
/**
|
||||
* 批量删除菜单
|
||||
*/
|
||||
batchDeleteMenu: (menuIdList) => {
|
||||
return getRequest(`/menu/batchDelete?menuIdList=${menuIdList}`);
|
||||
},
|
||||
|
||||
/**
|
||||
* 查询所有菜单列表
|
||||
*/
|
||||
queryMenu: () => {
|
||||
return getRequest('/menu/query');
|
||||
},
|
||||
|
||||
/**
|
||||
* 查询菜单树
|
||||
*/
|
||||
queryMenuTree: (onlyMenu) => {
|
||||
return getRequest(`/menu/tree?onlyMenu=${onlyMenu}`);
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取所有请求路径
|
||||
*/
|
||||
getAllUrl: () => {
|
||||
return getRequest('/menu/getAllUrl');
|
||||
},
|
||||
};
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-28 14:16:46
|
||||
* @LastEditTime: 2021-08-28 14:25:36
|
||||
* @LastEditors: zhuoda
|
||||
* @Description:
|
||||
* @FilePath: /smart-admin/src/api/system/role-menu/role-menu-api.ts
|
||||
*/
|
||||
import { getRequest, postRequest } from '/@/lib/axios';
|
||||
export const roleMenuApi = {
|
||||
/**
|
||||
* @description: 获取角色关联菜单权限
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
getRoleSelectedMenu: (roleId) => {
|
||||
return getRequest(`role/menu/getRoleSelectedMenu/${roleId}`);
|
||||
},
|
||||
/**
|
||||
* @description: 更新角色权限
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
updateRoleMenu: (data) => {
|
||||
return postRequest('role/menu/updateRoleMenu', data);
|
||||
},
|
||||
};
|
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-16 15:53:46
|
||||
* @LastEditTime: 2021-08-30 15:18:18
|
||||
* @LastEditors: zhuoda
|
||||
* @Description:
|
||||
* @FilePath: /smart-admin/src/api/system/role/role-api.ts
|
||||
*/
|
||||
import { getRequest, postRequest } from '/@/lib/axios';
|
||||
|
||||
export const roleApi = {
|
||||
/**
|
||||
* @description: 获取所有角色
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
queryAll: () => {
|
||||
return getRequest('role/getAll');
|
||||
},
|
||||
/**
|
||||
* @description:添加角色
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
addRole: (data) => {
|
||||
return postRequest('role/add', data);
|
||||
},
|
||||
/**
|
||||
* @description:更新角色
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
updateRole: (data) => {
|
||||
return postRequest('role/update', data);
|
||||
},
|
||||
/**
|
||||
* @description: 删除角色
|
||||
* @param {number} roleId
|
||||
* @return {*}
|
||||
*/
|
||||
deleteRole: (roleId) => {
|
||||
return getRequest(`role/delete/${roleId}`);
|
||||
},
|
||||
/**
|
||||
* @description: 批量设置某角色数据范围
|
||||
* @param {DataScopeBatchSetRoleDto} data
|
||||
* @return {*}
|
||||
*/
|
||||
updateDataScope: (data) => {
|
||||
return postRequest('/dataScope/batchSet', data);
|
||||
},
|
||||
/**
|
||||
* @description: 获取当前系统所配置的所有数据范围
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
getDataScopeList: () => {
|
||||
return getRequest('/dataScope/list');
|
||||
},
|
||||
/**
|
||||
* @description: 获取某角色所设置的数据范围
|
||||
* @param {number} roleId
|
||||
* @return {*}
|
||||
*/
|
||||
getDataScopeByRoleId: (roleId) => {
|
||||
return getRequest(`/dataScope/listByRole/${roleId}`);
|
||||
},
|
||||
/**
|
||||
* @description: 获取角色成员-员工列表
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
queryRoleEmployee: (params) => {
|
||||
return postRequest('/role/listEmployee', params);
|
||||
},
|
||||
/**
|
||||
* @description: 从角色成员列表中移除员工
|
||||
* @param {number} employeeId
|
||||
* @param {number} roleId
|
||||
* @return {*}
|
||||
*/
|
||||
deleteEmployeeRole: (employeeId, roleId) => {
|
||||
return getRequest('/role/removeEmployee?employeeId=' + employeeId + '&roleId=' + roleId);
|
||||
},
|
||||
/**
|
||||
* @description: 从角色成员列表中批量移除员工
|
||||
* @param {RoleEmployeeBatchDto} data
|
||||
* @return {*}
|
||||
*/
|
||||
deleteEmployeeList: (data) => {
|
||||
return postRequest('/role/removeEmployeeList', data);
|
||||
},
|
||||
/**
|
||||
* @description: 根据角色id获取角色员工列表(无分页)
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
getRoleAllEmployee: (roleId) => {
|
||||
return getRequest(`role/listAllEmployee/${roleId}`);
|
||||
},
|
||||
/**
|
||||
* @description: 角色成员列表中批量添加员工
|
||||
* @param {RoleEmployeeBatchDto} data
|
||||
* @return {*}
|
||||
*/
|
||||
addRoleEmployeeList: (data) => {
|
||||
return postRequest('/role/addEmployeeList', data);
|
||||
},
|
||||
};
|
BIN
admin-web/javascript-ant-design-vue/src/assets/img/logo.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
BIN
admin-web/javascript-ant-design-vue/src/assets/logo.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
@ -0,0 +1,70 @@
|
||||
<template>
|
||||
<h1>{{ msg }}</h1>
|
||||
|
||||
<p>
|
||||
Recommended IDE setup:
|
||||
<a href="https://code.visualstudio.com/" target="_blank">VSCode</a>
|
||||
+
|
||||
<a
|
||||
href="https://marketplace.visualstudio.com/items?itemName=octref.vetur"
|
||||
target="_blank"
|
||||
>
|
||||
Vetur
|
||||
</a>
|
||||
or
|
||||
<a href="https://github.com/johnsoncodehk/volar" target="_blank">Volar</a>
|
||||
(if using
|
||||
<code><script setup></code>)
|
||||
</p>
|
||||
|
||||
<p>See <code>README.md</code> for more information.</p>
|
||||
|
||||
<p>
|
||||
<a href="https://vitejs.dev/guide/features.html" target="_blank">
|
||||
Vite Docs
|
||||
</a>
|
||||
|
|
||||
<a href="https://v3.vuejs.org/" target="_blank">Vue 3 Docs</a>
|
||||
</p>
|
||||
|
||||
<button type="button" @click="count++">count is: {{ count }}</button>
|
||||
<p>
|
||||
Edit
|
||||
<code>components/HelloWorld.vue</code> to test hot module replacement.
|
||||
</p>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { ref, defineComponent } from 'vue'
|
||||
export default defineComponent({
|
||||
name: 'HelloWorld',
|
||||
props: {
|
||||
msg: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
setup: () => {
|
||||
const count = ref(0)
|
||||
return { count }
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
|
||||
label {
|
||||
margin: 0 0.5em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: #eee;
|
||||
padding: 2px 4px;
|
||||
border-radius: 4px;
|
||||
color: #304455;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,90 @@
|
||||
<!--
|
||||
* @Description:
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-12
|
||||
* @LastEditTime: 2021-08-18
|
||||
* @LastEditors: zhuoda
|
||||
-->
|
||||
<template>
|
||||
<a-tree-select
|
||||
v-model:value="selectValue"
|
||||
:style="`width:${width}`"
|
||||
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
||||
:tree-data="categoryTree"
|
||||
:placeholder="placeholder"
|
||||
tree-default-expand-all
|
||||
@change="handleChange"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch, onMounted } from "vue";
|
||||
import { categoryApi } from "@/api/business/category/category-api";
|
||||
|
||||
// ========================
|
||||
interface CategoryTreeSelectProps {
|
||||
placeholder?: string;
|
||||
value?: string | number;
|
||||
categoryType?: number; // 分组类型 CATEGORY_TYPE_ENUM
|
||||
width: string;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<CategoryTreeSelectProps>(), {
|
||||
value: undefined,
|
||||
placeholder: "请选择",
|
||||
categoryType: undefined,
|
||||
width: "100%",
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "update:value", value);
|
||||
(e: "change", value);
|
||||
}>();
|
||||
const categoryTree = ref<[]>([]);
|
||||
// ======================== 逻辑
|
||||
|
||||
async function queryCategoryTree() {
|
||||
if (!props.categoryType) {
|
||||
categoryTree.value = [];
|
||||
return;
|
||||
}
|
||||
try {
|
||||
let param = {
|
||||
categoryType: props.categoryType,
|
||||
};
|
||||
let resp = await categoryApi.queryCategoryTree(
|
||||
param
|
||||
);
|
||||
categoryTree.value = resp.data;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} finally {
|
||||
console.log(1);
|
||||
}
|
||||
}
|
||||
|
||||
const selectValue = ref(props.value);
|
||||
|
||||
// 箭头value变化
|
||||
watch(
|
||||
() => props.value,
|
||||
(newValue) => {
|
||||
selectValue.value = newValue;
|
||||
}
|
||||
);
|
||||
|
||||
// 监听类型变化
|
||||
watch(
|
||||
() => props.categoryType,
|
||||
() => {
|
||||
queryCategoryTree();
|
||||
}
|
||||
);
|
||||
|
||||
function handleChange(value: any): void {
|
||||
emit("update:value", value);
|
||||
emit("change", value);
|
||||
}
|
||||
|
||||
onMounted(queryCategoryTree);
|
||||
</script>
|
@ -0,0 +1,70 @@
|
||||
<!--
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-10 16:53:06
|
||||
* @LastEditTime: 2021-08-16 15:59:21
|
||||
* @LastEditors: zhuoda
|
||||
* @Description: 部门树下拉选择
|
||||
* @FilePath: /smart-admin/src/views/system/employee/department/components/department-tree-select/index.vue
|
||||
-->
|
||||
<template>
|
||||
<a-tree-select
|
||||
:value="props.value"
|
||||
:treeData="treeData"
|
||||
:replaceFields="{ title: 'name', key: 'id', value: 'id' }"
|
||||
show-search
|
||||
style="width: 100%"
|
||||
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
||||
placeholder="请选择部门"
|
||||
allow-clear
|
||||
tree-default-expand-all
|
||||
:multiple="props.multiple"
|
||||
@change="treeSelectChange"
|
||||
/>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue';
|
||||
import _ from 'lodash';
|
||||
import { departmentApi } from '/@/api/system/department/department-api';
|
||||
// ----------------------- 以下是字段定义 emits props ------------------------
|
||||
interface Props {
|
||||
// 绑定值
|
||||
value?: number | number[];
|
||||
// 单选多选
|
||||
multiple?: boolean;
|
||||
// 是否内部初始化数据
|
||||
init?: boolean;
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
value: undefined,
|
||||
multiple: false,
|
||||
init: true,
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:value', value: number | number[]);
|
||||
}>();
|
||||
|
||||
let treeData = ref([]);
|
||||
// ----------------------- 以下是计算属性 watch监听 ------------------------
|
||||
// ----------------------- 以下是生命周期 ------------------------
|
||||
onMounted(() => {
|
||||
if (props.init) {
|
||||
queryDepartmentTree();
|
||||
}
|
||||
});
|
||||
// ----------------------- 以下是方法 ------------------------
|
||||
// 外部调用初始化
|
||||
async function queryDepartmentTree() {
|
||||
let res = await departmentApi.departmentTree();
|
||||
treeData.value = res.data;
|
||||
}
|
||||
|
||||
function treeSelectChange(e: number | number[]) {
|
||||
emit('update:value', e);
|
||||
}
|
||||
|
||||
// ----------------------- 以下是暴露的方法内容 ------------------------
|
||||
defineExpose({
|
||||
queryDepartmentTree,
|
||||
});
|
||||
</script>
|
@ -0,0 +1,78 @@
|
||||
<!--
|
||||
* @Description:
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-12 18:23:56
|
||||
* @LastEditTime: 2021-08-18
|
||||
* @LastEditors: zhuoda
|
||||
-->
|
||||
<template>
|
||||
<a-select
|
||||
v-model:value="selectValue"
|
||||
:style="`width: ${width}`"
|
||||
:placeholder="props.placeholder"
|
||||
:showSearch="true"
|
||||
:allowClear="true"
|
||||
:size="size"
|
||||
@change="handleChange"
|
||||
@deselect="handleChange"
|
||||
>
|
||||
<a-select-option v-for="item in employeeList" :key="item.id" :value="item.id">
|
||||
{{ item.actualName }}({{ item.departmentName }})
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch, onMounted } from "vue";
|
||||
import { employeeApi } from "/@/api/system/employee/employee-api";
|
||||
|
||||
// =========== 属性定义 和 事件方法暴露 =============
|
||||
interface EmployeeSelectProps {
|
||||
placeholder?: string;
|
||||
value?: number;
|
||||
width: string;
|
||||
size?: string;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<EmployeeSelectProps>(), {
|
||||
value: undefined,
|
||||
placeholder: "请选择",
|
||||
width: "100%",
|
||||
size: "default",
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "update:value", value: any): void;
|
||||
(e: "change", value: any): void;
|
||||
}>();
|
||||
|
||||
// =========== 业务逻辑 =============
|
||||
|
||||
//员工列表数据
|
||||
const employeeList = ref([]);
|
||||
async function query() {
|
||||
try {
|
||||
let resp = await employeeApi.queryAll();
|
||||
employeeList.value = resp.data;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} finally {
|
||||
console.log(1);
|
||||
}
|
||||
}
|
||||
onMounted(query);
|
||||
|
||||
// 监听value变化
|
||||
const selectValue = ref(props.value);
|
||||
watch(
|
||||
() => props.value,
|
||||
(newValue) => {
|
||||
selectValue.value = newValue;
|
||||
}
|
||||
);
|
||||
|
||||
function handleChange(value: any): void {
|
||||
emit("update:value", value);
|
||||
emit("change", value);
|
||||
}
|
||||
</script>
|
@ -0,0 +1,31 @@
|
||||
<!--
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-03 10:27:11
|
||||
* @LastEditTime: 2021-08-25 21:20:10
|
||||
* @LastEditors: zhuoda
|
||||
* @Description:
|
||||
* @FilePath: /smart-admin/src/components/menu-location-breadcrumb/index.vue
|
||||
-->
|
||||
<template>
|
||||
<a-breadcrumb separator=">" style="display: inline">
|
||||
<a-breadcrumb-item v-for="(item, index) in parentMenuList" :key="index">{{ item.title }}</a-breadcrumb-item>
|
||||
<a-breadcrumb-item>{{ currentRoute.meta.title }}</a-breadcrumb-item>
|
||||
</a-breadcrumb>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed } from '@vue/reactivity';
|
||||
import { useRoute } from 'vue-router';
|
||||
// ----------------------- 以下是字段定义 emits props ---------------------
|
||||
let currentRoute = useRoute();
|
||||
// ----------------------- 以下是计算属性 watch监听 ------------------------
|
||||
const parentMenuList = computed(() => {
|
||||
return currentRoute.meta.parentMenuList || [];
|
||||
});
|
||||
// ----------------------- 以下是生命周期 ---------------------------------
|
||||
|
||||
// ----------------------- 以下是方法 ------------------------------------
|
||||
|
||||
// ----------------------- 以下是暴露的方法内容 ----------------------------
|
||||
defineExpose({});
|
||||
</script>
|
||||
<style scoped lang="less"></style>
|
@ -0,0 +1,115 @@
|
||||
<!--
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-17 19:09:40
|
||||
* @LastEditTime: 2021-08-27
|
||||
* @LastEditors: zhuoda
|
||||
* @Description:
|
||||
* @FilePath: /smart-admin/src/components/recursion-menu/index.vue
|
||||
-->
|
||||
<template>
|
||||
<a-menu
|
||||
:selectedKeys="selectedKeys"
|
||||
:openKeys="openKeys"
|
||||
mode="inline"
|
||||
theme="dark"
|
||||
:inline-collapsed="collapsed"
|
||||
>
|
||||
<template v-for="item in menuTree" :key="item.name">
|
||||
<template v-if="!item.meta.hideInMenu">
|
||||
<template v-if="$lodash.isEmpty(item.children)">
|
||||
<a-menu-item :key="item.name" @click="turnToPage(item)">
|
||||
<template #icon>
|
||||
<component :is="$antIcons[item.meta.icon]" />
|
||||
</template>
|
||||
{{ item.meta.title }}
|
||||
</a-menu-item>
|
||||
</template>
|
||||
<template v-else>
|
||||
<sub-menu :menu-info="item" :key="item.name" @turnToPage="turnToPage" />
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
</a-menu>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, computed } from "vue";
|
||||
import SubMenu from "./sub-menu.vue";
|
||||
import { router } from "/@/router/index";
|
||||
import { MENU_TYPE_ENUM } from "/@/constants/system/menu/menu-enum";
|
||||
import { RouteRecord, useRoute } from "vue-router";
|
||||
|
||||
export default defineComponent({
|
||||
name: "RecursionMenu",
|
||||
components: {
|
||||
SubMenu,
|
||||
},
|
||||
props: {
|
||||
menuList: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
collapsed: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup(prop, context) {
|
||||
const collapsed = ref<boolean>(false);
|
||||
let currentRoute = useRoute();
|
||||
const toggleCollapsed = () => {
|
||||
collapsed.value = !collapsed.value;
|
||||
};
|
||||
|
||||
// 菜单树
|
||||
let routes = router.getRoutes();
|
||||
const menuTree = computed(() => {
|
||||
return routes.filter((e) => e.meta.menuType == MENU_TYPE_ENUM.CATALOG.value);
|
||||
});
|
||||
|
||||
const selectedKeys = computed(() => {
|
||||
return [currentRoute.name];
|
||||
});
|
||||
|
||||
const openKeys = computed(() => {
|
||||
return (currentRoute.meta.parentMenuList || []).map(
|
||||
(e: Record<string, string>) => e.name
|
||||
);
|
||||
});
|
||||
|
||||
// 页面跳转
|
||||
const turnToPage = (route: RouteRecord | string) => {
|
||||
console.log(route);
|
||||
let { name, params, query } = {};
|
||||
if (typeof route === "string") {
|
||||
name = route;
|
||||
} else {
|
||||
name = route.name;
|
||||
params = route.params;
|
||||
query = route.query;
|
||||
}
|
||||
if (name.indexOf("isTurnByHref_") > -1) {
|
||||
window.open(name.split("_")[1]);
|
||||
return;
|
||||
}
|
||||
router.push({
|
||||
name,
|
||||
params,
|
||||
query,
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
selectedKeys,
|
||||
openKeys,
|
||||
turnToPage,
|
||||
toggleCollapsed,
|
||||
menuTree,
|
||||
};
|
||||
},
|
||||
components: {
|
||||
SubMenu,
|
||||
},
|
||||
});
|
||||
</script>
|
@ -0,0 +1,56 @@
|
||||
<!--
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-03 10:27:11
|
||||
* @LastEditTime: 2021-08-17 16:57:59
|
||||
* @LastEditors: zhuoda
|
||||
* @Description:
|
||||
* @FilePath: /smart-admin/src/components/recursion-menu/sub-menu.vue
|
||||
-->
|
||||
<template>
|
||||
<a-sub-menu :key="menuInfo.name">
|
||||
<template #icon>
|
||||
<component :is="$antIcons[menuInfo.meta.icon]"/>
|
||||
</template>
|
||||
<template #title>{{ menuInfo.meta.title }}</template>
|
||||
<template v-for="item in menuInfo.children" :key="item.name">
|
||||
<template v-if="!item.meta.hideInMenu">
|
||||
<template v-if="!item.children">
|
||||
<a-menu-item :key="item.name" @click="turnToPage(item)">
|
||||
<template #icon>
|
||||
<component :is="$antIcons[item.meta.icon]"/>
|
||||
</template>
|
||||
{{ item.meta.title }}
|
||||
</a-menu-item>
|
||||
</template>
|
||||
<template v-else>
|
||||
<sub-menu :menu-info="item" :key="item.name" @turnToPage="turnToPage"/>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
</a-sub-menu>
|
||||
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import {defineComponent} from "vue";
|
||||
import {RouteRecord} from "vue-router";
|
||||
|
||||
export default defineComponent({
|
||||
name: "SubMenu",
|
||||
components: {},
|
||||
props: {
|
||||
menuInfo: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
setup(prop,context) {
|
||||
const turnToPage = (route:RouteRecord | string) => {
|
||||
context.emit('turnToPage',route)
|
||||
}
|
||||
return {
|
||||
turnToPage
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
</script>
|
@ -0,0 +1,92 @@
|
||||
<!--
|
||||
* @Description: 校区部门选择
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-12 18:23:56
|
||||
* @LastEditTime: 2021-08-25 11:48:26
|
||||
* @LastEditors: Please set LastEditors
|
||||
-->
|
||||
<template>
|
||||
<a-select
|
||||
v-model:value="selectValue"
|
||||
:style="`width: ${width}`"
|
||||
:placeholder="props.placeholder"
|
||||
:showSearch="true"
|
||||
:allowClear="true"
|
||||
:size="size"
|
||||
@change="handleChange"
|
||||
@deselect="handleChange"
|
||||
>
|
||||
<a-select-option v-for="item in list" :key="item.id" :value="item.id">
|
||||
{{ item.name }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch, onMounted } from "vue";
|
||||
import { departmentApi } from "/@/api/system/department/department-api";
|
||||
|
||||
// =========== 属性定义 和 事件方法暴露 =============
|
||||
interface ShoolDepartmentSelectProps {
|
||||
placeholder?: string;
|
||||
value?: number;
|
||||
width: string;
|
||||
size?: string;
|
||||
showFirst?:boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<ShoolDepartmentSelectProps>(), {
|
||||
value: undefined,
|
||||
placeholder: "请选择",
|
||||
width: "100%",
|
||||
size: "default",
|
||||
showFirst:false,
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "update:value", value);
|
||||
(e: "change", value);
|
||||
}>();
|
||||
|
||||
// =========== 业务逻辑 =============
|
||||
|
||||
//列表数据
|
||||
const list = ref([]);
|
||||
async function query() {
|
||||
try {
|
||||
let resp = await departmentApi.querySchoolDepartmentList();
|
||||
list.value = resp.data;
|
||||
if(props.showFirst){
|
||||
showFirst()
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} finally {
|
||||
console.log(1);
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(query);
|
||||
|
||||
// 监听value变化
|
||||
const selectValue = ref(props.value);
|
||||
watch(
|
||||
() => props.value,
|
||||
(newValue) => {
|
||||
selectValue.value = newValue;
|
||||
}
|
||||
);
|
||||
|
||||
function handleChange(value): void {
|
||||
emit("update:value", value);
|
||||
emit("change", value);
|
||||
}
|
||||
|
||||
//展示第一个
|
||||
function showFirst(){
|
||||
if(list.value && list.value.length > 0){
|
||||
selectValue.value = list.value[0].id;
|
||||
handleChange(selectValue.value )
|
||||
}
|
||||
}
|
||||
</script>
|
@ -0,0 +1,175 @@
|
||||
<!--
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-30 14:38:05
|
||||
* @LastEditTime: 2021-08-30 15:14:06
|
||||
* @LastEditors: zhuoda
|
||||
* @Description:
|
||||
* @FilePath: /smart-admin/src/components/select-employee-modal/index.vue
|
||||
-->
|
||||
<template>
|
||||
<a-modal v-model:visible="visible" :width="900" title="选择人员" @cancel="closeModal" @ok="selectData">
|
||||
<a-form class="smart-query-form">
|
||||
<a-row class="smart-query-form-row">
|
||||
<a-form-item label="关键字" class="smart-query-form-item">
|
||||
<a-input style="width: 150px" v-model:value="params.keyword" placeholder="商品名称" />
|
||||
</a-form-item>
|
||||
<a-form-item label="部门" class="smart-query-form-item">
|
||||
<DepartmentTreeSelect style="width: 150px" ref="departmentTreeSelect" v-model:value="params.departmentId" />
|
||||
</a-form-item>
|
||||
<a-form-item label="状态" class="smart-query-form-item">
|
||||
<a-select style="width: 150px" v-model:value="params.disabledFlag" placeholder="请选择状态" allowClear>
|
||||
<a-select-option :key="1"> 禁用 </a-select-option>
|
||||
<a-select-option :key="0"> 启用 </a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item class="smart-query-form-item smart-margin-left10">
|
||||
<a-button type="primary" @click="queryEmployee">
|
||||
<template #icon>
|
||||
<ReloadOutlined />
|
||||
</template>
|
||||
查询
|
||||
</a-button>
|
||||
<a-button @click="reset" class="smart-margin-left10">
|
||||
<template #icon>
|
||||
<SearchOutlined />
|
||||
</template>
|
||||
重置
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</a-row>
|
||||
</a-form>
|
||||
<a-table
|
||||
:row-selection="{ selectedRowKeys: selectedRowKeyList, onChange: onSelectChange }"
|
||||
:loading="tableLoading"
|
||||
size="small"
|
||||
:columns="columns"
|
||||
:data-source="tableData"
|
||||
:pagination="false"
|
||||
rowKey="id"
|
||||
:scroll="{ y: 300 }"
|
||||
>
|
||||
<template #disabledFlag="{ text }">
|
||||
<span>{{ text ? '禁用' : '启用' }}</span>
|
||||
</template>
|
||||
<template #gender="{ text }">
|
||||
<span>{{ $smartEnumPlugin.getDescByValue('GENDER_ENUM', text) }}</span>
|
||||
</template>
|
||||
</a-table>
|
||||
<div class="smart-query-table-page">
|
||||
<a-pagination
|
||||
showSizeChanger
|
||||
showQuickJumper
|
||||
show-less-items
|
||||
:pageSizeOptions="PAGE_SIZE_OPTIONS"
|
||||
:defaultPageSize="params.pageSize"
|
||||
v-model:current="params.pageNum"
|
||||
v-model:pageSize="params.pageSize"
|
||||
:total="total"
|
||||
@change="queryEmployee"
|
||||
@showSizeChange="queryEmployee"
|
||||
:show-total="(total) => `共${total}条`"
|
||||
/>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive, ref } from 'vue';
|
||||
import { employeeApi } from '/@/api/system/employee/employee-api';
|
||||
import { PAGE_SIZE, PAGE_SIZE_OPTIONS } from '/@/constants/common';
|
||||
import DepartmentTreeSelect from '/@/components/department-tree-select/index.vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
// ----------------------- 以下是字段定义 emits props ---------------------
|
||||
const emits = defineEmits<{
|
||||
(e: 'selectData', value);
|
||||
}>();
|
||||
const visible = ref(false);
|
||||
const tableLoading = ref<boolean>(false);
|
||||
const departmentTreeSelect = ref();
|
||||
//字段
|
||||
const columns = [
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'actualName',
|
||||
},
|
||||
{
|
||||
title: '手机号',
|
||||
dataIndex: 'phone',
|
||||
},
|
||||
{
|
||||
title: '性别',
|
||||
dataIndex: 'gender',
|
||||
slots: { customRender: 'gender' },
|
||||
},
|
||||
{
|
||||
title: '登录账号',
|
||||
dataIndex: 'loginName',
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'disabledFlag',
|
||||
slots: { customRender: 'disabledFlag' },
|
||||
},
|
||||
];
|
||||
const tableData = ref([]);
|
||||
let defaultParams = {
|
||||
departmentId: undefined,
|
||||
disabledFlag: undefined,
|
||||
employeeIdList: undefined,
|
||||
keyword: undefined,
|
||||
searchCount: undefined,
|
||||
pageNum: 1,
|
||||
pageSize: PAGE_SIZE,
|
||||
sortItemList: undefined,
|
||||
};
|
||||
const params = reactive({ ...defaultParams });
|
||||
const total = ref<number>();
|
||||
let selectedRowKeyList = ref<number[]>([]);
|
||||
// ----------------------- 以下是计算属性 watch监听 ------------------------
|
||||
const hasSelected = computed(() => selectedRowKeyList.value.length > 0);
|
||||
// ----------------------- 以下是生命周期 ---------------------------------
|
||||
|
||||
// ----------------------- 以下是方法 ------------------------------------
|
||||
async function showModal(selectEmployeeId) {
|
||||
selectedRowKeyList.value = selectEmployeeId || [];
|
||||
visible.value = true;
|
||||
queryEmployee();
|
||||
}
|
||||
function reset() {
|
||||
Object.assign(params, defaultParams);
|
||||
queryEmployee();
|
||||
}
|
||||
async function queryEmployee() {
|
||||
tableLoading.value = true;
|
||||
try {
|
||||
let res = await employeeApi.queryEmployee(params);
|
||||
tableData.value = res.data.list;
|
||||
total.value = res.data.total;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
tableLoading.value = false;
|
||||
}
|
||||
}
|
||||
function onSelectChange(selectedRowKeys: number[]) {
|
||||
selectedRowKeyList.value = selectedRowKeys;
|
||||
}
|
||||
function closeModal() {
|
||||
Object.assign(params, defaultParams);
|
||||
selectedRowKeyList.value = [];
|
||||
visible.value = false;
|
||||
}
|
||||
function selectData() {
|
||||
if (!hasSelected.value) {
|
||||
message.warning('请选择角色人员');
|
||||
return;
|
||||
}
|
||||
let selectVoList = tableData.value.filter((e) => selectedRowKeyList.value.includes(e.id));
|
||||
emits('selectData', selectVoList);
|
||||
closeModal();
|
||||
}
|
||||
// ----------------------- 以下是暴露的方法内容 ----------------------------
|
||||
defineExpose({
|
||||
showModal,
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="less"></style>
|
@ -0,0 +1,60 @@
|
||||
<!--
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-25 17:07:41
|
||||
* @LastEditTime: 2021-08-28 16:46:25
|
||||
* @LastEditors: zhuoda
|
||||
* @Description:
|
||||
* @FilePath: /smart-admin/src/components/side-expand/side-menu/index.vue
|
||||
-->
|
||||
<template>
|
||||
<div class="menu-container">
|
||||
<!-- logo 一级导航 -->
|
||||
<TopMenu ref="topMenu" class="topMenu" :menuTree="menuTree" />
|
||||
<!-- 次级导航 -->
|
||||
<RecursionMenu v-if="showRecursionMenu" class="recursionMenu" :selectedMenu="selectedMenu" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import TopMenu from './top-menu.vue';
|
||||
import RecursionMenu from './recursion-menu.vue';
|
||||
import { useUserStore } from '/@/store/modules/system/user';
|
||||
import { computed } from '@vue/reactivity';
|
||||
import { ref } from 'vue';
|
||||
// ----------------------- 以下是字段定义 emits props ---------------------
|
||||
defineProps<{
|
||||
value;
|
||||
}>();
|
||||
defineEmits<{
|
||||
(e: 'update:value');
|
||||
}>();
|
||||
const topMenu = ref();
|
||||
// ----------------------- 以下是计算属性 watch监听 ------------------------
|
||||
const menuTree = computed(() => useUserStore().getMenuTree || []);
|
||||
const selectedMenu = computed(() => {
|
||||
if (topMenu.value) {
|
||||
return topMenu.value.selectedMenu;
|
||||
}
|
||||
return {};
|
||||
});
|
||||
const showRecursionMenu = computed(() => selectedMenu.value && selectedMenu.value.children && selectedMenu.value.children.some((e) => e.visibleFlag));
|
||||
// ----------------------- 以下是生命周期 ---------------------------------
|
||||
|
||||
// ----------------------- 以下是方法 ------------------------------------
|
||||
|
||||
// ----------------------- 以下是暴露的方法内容 ----------------------------
|
||||
defineExpose({});
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.menu-container {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
.topMenu {
|
||||
width: 114px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.recursionMenu {
|
||||
min-width: 126px;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,86 @@
|
||||
<!--
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-25 17:52:43
|
||||
* @LastEditTime: 2021-08-27
|
||||
* @LastEditors: zhuoda
|
||||
* @Description:
|
||||
* @FilePath: /smart-admin/src/components/side-expand/side-menu/recursion-menu.vue
|
||||
-->
|
||||
<template>
|
||||
<div class="resursion-container">
|
||||
<!-- 顶部顶级菜单名称 -->
|
||||
<div class="top-menu">
|
||||
<span class="ant-menu">{{ props.selectedMenu?.menuName }}</span>
|
||||
</div>
|
||||
<!-- 次级菜单展示 -->
|
||||
<a-menu :selectedKeys="selectedKeys" :openKeys="openKeys" mode="inline">
|
||||
<template v-for="item in props.selectedMenu?.children" :key="item.menuId">
|
||||
<template v-if="item.visibleFlag">
|
||||
<template v-if="$lodash.isEmpty(item.children)">
|
||||
<a-menu-item :key="item.menuId.toString()" @click="turnToPage(item)">
|
||||
<template #icon v-if="item.icon">
|
||||
<component :is="$antIcons[item.icon]" />
|
||||
</template>
|
||||
{{ item.menuName }}
|
||||
</a-menu-item>
|
||||
</template>
|
||||
<template v-else>
|
||||
<sub-menu :menu-info="item" :key="item.menuId" @turnToPage="turnToPage" />
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
</a-menu>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
import { router } from "/@/router";
|
||||
import SubMenu from "./sub-menu.vue";
|
||||
|
||||
// ----------------------- 以下是字段定义 emits props ---------------------
|
||||
|
||||
let props = defineProps<{
|
||||
selectedMenu?: any;
|
||||
}>();
|
||||
defineEmits<{
|
||||
(e: "update:value"): void;
|
||||
}>();
|
||||
let currentRoute = useRoute();
|
||||
// ----------------------- 以下是计算属性 watch监听 ------------------------
|
||||
const selectedKeys = computed(() => {
|
||||
return [currentRoute.name];
|
||||
});
|
||||
|
||||
const openKeys = computed(() => {
|
||||
return (currentRoute.meta.parentMenuList || []).map(
|
||||
(e: Record<string, string>) => e.name
|
||||
);
|
||||
});
|
||||
// ----------------------- 以下是生命周期 ---------------------------------
|
||||
|
||||
// ----------------------- 以下是方法 ------------------------------------
|
||||
// 页面跳转
|
||||
function turnToPage(route) {
|
||||
router.push({ name: route.menuId.toString() });
|
||||
}
|
||||
// ----------------------- 以下是暴露的方法内容 ----------------------------
|
||||
defineExpose({});
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.resursion-container {
|
||||
height: 100%;
|
||||
background: #ffffff;
|
||||
}
|
||||
.top-menu {
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: @header-user-height;
|
||||
font-size: 16px;
|
||||
color: #515a6e;
|
||||
border-bottom: 1px solid #f3f3f3;
|
||||
border-right: 1px solid #f3f3f3;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,55 @@
|
||||
<!--
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-03 10:27:11
|
||||
* @LastEditTime: 2021-08-26
|
||||
* @LastEditors: zhuoda
|
||||
* @Description:
|
||||
* @FilePath: /smart-admin/src/components/side-expand/side-menu/sub-menu.vue
|
||||
-->
|
||||
<template>
|
||||
<a-sub-menu :key="props.menuInfo?.menuId">
|
||||
<template #icon>
|
||||
<component :is="$antIcons[props.menuInfo?.icon]" />
|
||||
</template>
|
||||
<template #title>{{ props.menuInfo?.menuName }}</template>
|
||||
<template v-for="item in props.menuInfo?.children" :key="item.menuId">
|
||||
<template v-if="item.visibleFlag">
|
||||
<template v-if="!item.children">
|
||||
<a-menu-item :key="item.menuId" @click="turnToPage(item)">
|
||||
<template #icon>
|
||||
<component :is="$antIcons[item.icon]" />
|
||||
</template>
|
||||
{{ item.menuName }}
|
||||
</a-menu-item>
|
||||
</template>
|
||||
<template v-else>
|
||||
<sub-menu :menu-info="item" :key="item.menuId" @turnToPage="turnToPage" />
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
</a-sub-menu>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
// ----------------------- 以下是字段定义 emits props ---------------------
|
||||
let props = defineProps<{
|
||||
menuInfo:any;
|
||||
}>();
|
||||
let emits = defineEmits<{
|
||||
(e: "turnToPage", value);
|
||||
}>();
|
||||
// ----------------------- 以下是计算属性 watch监听 ------------------------
|
||||
|
||||
// ----------------------- 以下是生命周期 ---------------------------------
|
||||
|
||||
// ----------------------- 以下是方法 ------------------------------------
|
||||
const turnToPage = (route) => {
|
||||
emits("turnToPage", route);
|
||||
};
|
||||
// ----------------------- 以下是暴露的方法内容 ----------------------------
|
||||
defineExpose({});
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
::v-deep(.ant-menu-item-selected) {
|
||||
border-right: 3px !important;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,112 @@
|
||||
<!--
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-25 17:09:44
|
||||
* @LastEditTime: 2021-09-01
|
||||
* @LastEditors: zhuoda
|
||||
* @Description:
|
||||
* @FilePath: /smart-admin/src/components/side-expand/side-menu/top-menu.vue
|
||||
-->
|
||||
<template>
|
||||
<div class="top-menu-container">
|
||||
<!-- 顶部logo区域 -->
|
||||
<div class="logo">
|
||||
<h3 style="color: white">SmartAdmin</h3>
|
||||
</div>
|
||||
<!-- 一级菜单展示 -->
|
||||
<a-menu
|
||||
:selectedKeys="selectedKeys"
|
||||
mode="inline"
|
||||
theme="dark"
|
||||
:inline-collapsed="collapsed"
|
||||
>
|
||||
<template v-for="item in props.menuTree" :key="item.menuId">
|
||||
<template v-if="item.visibleFlag">
|
||||
<a-menu-item :key="item.menuId.toString()" @click="selectMenu(item)">
|
||||
<template #icon>
|
||||
<component :is="$antIcons[item.icon]" />
|
||||
</template>
|
||||
{{ item.menuName }}
|
||||
</a-menu-item>
|
||||
</template>
|
||||
</template>
|
||||
</a-menu>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import _ from "lodash";
|
||||
import { computed, ref, watch } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
import { appDefaultConfig } from "/@/config/app-config";
|
||||
import { MENU_TYPE_ENUM } from "/@/constants/system/menu/menu-enum";
|
||||
import { router } from "/@/router";
|
||||
|
||||
// ----------------------- 以下是字段定义 emits props ---------------------
|
||||
|
||||
let props = defineProps<{
|
||||
menuTree:any;
|
||||
}>();
|
||||
const collapsed = ref<boolean>(false);
|
||||
const selectedMenu = ref();
|
||||
let currentRoute = useRoute();
|
||||
// ----------------------- 以下是计算属性 watch监听 ------------------------
|
||||
const selectedKeys = computed(() => {
|
||||
if (selectedMenu.value) {
|
||||
return [selectedMenu.value.menuId.toString()];
|
||||
}
|
||||
return (currentRoute.meta.parentMenuList || []).map(
|
||||
(e: Record<string, string>) => e.name
|
||||
);
|
||||
});
|
||||
watch(
|
||||
currentRoute,
|
||||
() => {
|
||||
selectedMenu.value = undefined;
|
||||
let menuList = props.menuTree?.map((e) => e.menuId.toString());
|
||||
let parentIdList = _.intersection(menuList, <string[]>selectedKeys.value);
|
||||
if (parentIdList.length > 0) {
|
||||
let parentId = parentIdList[0];
|
||||
let parentItem = props.menuTree?.find((e) => e.menuId == Number(parentId));
|
||||
selectedMenu.value = parentItem;
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
// ----------------------- 以下是生命周期 ---------------------------------
|
||||
// ----------------------- 以下是方法 ------------------------------------
|
||||
// 页面跳转
|
||||
function selectMenu(route) {
|
||||
selectedMenu.value = route;
|
||||
if (
|
||||
route.menuType == MENU_TYPE_ENUM.MENU.value &&
|
||||
(_.isEmpty(route.children) || route.children?.every((e) => !e.visibleFlag))
|
||||
) {
|
||||
router.push({ name: route.menuId.toString() });
|
||||
}
|
||||
}
|
||||
function goHome() {
|
||||
router.push({ name: appDefaultConfig.homePageName });
|
||||
}
|
||||
// ----------------------- 以下是暴露的方法内容 ----------------------------
|
||||
defineExpose({
|
||||
selectedMenu,
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.top-menu-container {
|
||||
height: 100%;
|
||||
background: #001529;
|
||||
}
|
||||
.logo {
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 67px;
|
||||
img {
|
||||
width: 83px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,38 @@
|
||||
.shadow{
|
||||
box-shadow: 2px 0 6px rgba(0, 21, 41, .35);
|
||||
}
|
||||
.side-menu{
|
||||
min-height: 100vh;
|
||||
overflow-y: auto;
|
||||
z-index: 10;
|
||||
.logo{
|
||||
height: @header-user-height;
|
||||
position: relative;
|
||||
line-height: @header-user-height;
|
||||
padding-left: 24px;
|
||||
-webkit-transition: all .3s;
|
||||
transition: all .3s;
|
||||
overflow: hidden;
|
||||
background-color: @layout-trigger-background;
|
||||
&.light{
|
||||
background-color: #fff;
|
||||
h1{
|
||||
color: @primary-color;
|
||||
}
|
||||
}
|
||||
h1{
|
||||
color: @menu-dark-highlight-color;
|
||||
font-size: 20px;
|
||||
margin: 0 0 0 12px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
img{
|
||||
width: 32px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
.menu{
|
||||
padding: 16px 0;
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<!--
|
||||
左侧菜单分为两部分:
|
||||
1、顶部logo区域,包含 logo和名称
|
||||
2、下方菜单区域
|
||||
-->
|
||||
|
||||
<!-- 顶部logo区域 -->
|
||||
<div :class="['logo', theme]">
|
||||
<img src="/@/assets/img/logo.png"/>
|
||||
<h1>{{ projectName }}</h1>
|
||||
</div>
|
||||
|
||||
<!-- 下方菜单区域: 这里使用一个递归菜单解决 -->
|
||||
<recursion-menu :collapsed="collapsed" />
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import RecursionMenu from "/@/components/recursion-menu/index.vue";
|
||||
import {computed, defineComponent} from "vue";
|
||||
import {useAppConfigStore} from "/@/store/modules/system/app-config";
|
||||
import {useProjectConfigStore} from "/@/store/modules/system/project-config";
|
||||
|
||||
|
||||
export default defineComponent({
|
||||
name: "SideMenu",
|
||||
components: {RecursionMenu},
|
||||
props: {
|
||||
collapsible: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
collapsed: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
menuData: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
theme: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "dark"
|
||||
}
|
||||
},
|
||||
setup(props, {emit}) {
|
||||
let appConfigStore = useAppConfigStore();
|
||||
let projectConfigStore = useProjectConfigStore();
|
||||
|
||||
const onSelect = (obj) => {
|
||||
emit("menuSelect", obj);
|
||||
};
|
||||
|
||||
return {
|
||||
onSelect,
|
||||
isMobile: computed(() => appConfigStore.isMobile),
|
||||
projectName: computed(() => projectConfigStore.projectName)
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import "index";
|
||||
</style>
|
@ -0,0 +1,87 @@
|
||||
<!--
|
||||
* @Description: 地区级联选择
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-17
|
||||
* @LastEditTime: 2021-08-18
|
||||
* @LastEditors: zhuoda
|
||||
-->
|
||||
|
||||
<template>
|
||||
<a-cascader
|
||||
:style="`width:${width}`"
|
||||
v-model:value="areaValue"
|
||||
:show-search="{ filter }"
|
||||
:options="areaOptionData"
|
||||
:placeholder="placeholder"
|
||||
:size="size"
|
||||
@change="handleChange"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PROVINCE_CITY_DISTRICT } from "./province-city-district";
|
||||
import { PROVINCE_CITY } from "./province-city";
|
||||
import { ref, toRaw, watch } from "vue";
|
||||
|
||||
// ============ 组件属性 ============
|
||||
|
||||
const TYPE_PROVINCE_CITY_DISTRICT = "province_city_district";
|
||||
const TYPE_PROVINCE_CITY = "province_city";
|
||||
import { SmartAreaOption } from "./smart-area-option";
|
||||
|
||||
interface SmartAreaCascaderProps {
|
||||
// 类型
|
||||
type: string;
|
||||
value: SmartAreaOption[];
|
||||
width: string;
|
||||
size?: string;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<SmartAreaCascaderProps>(), {
|
||||
size: "default",
|
||||
value: undefined,
|
||||
width: "200px",
|
||||
placeholder: "请选择地区",
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "update:value", value);
|
||||
(e: "change", value, selectedOptions);
|
||||
}>();
|
||||
|
||||
// ============ 组件业务 ============
|
||||
const areaOptionData =
|
||||
props.type === TYPE_PROVINCE_CITY_DISTRICT ? PROVINCE_CITY_DISTRICT : PROVINCE_CITY;
|
||||
|
||||
// 绑定地区数据
|
||||
const areaValue = ref<number[]>([]);
|
||||
// 监听value变化
|
||||
watch(
|
||||
() => props.value,
|
||||
(newValue) => {
|
||||
if (newValue) {
|
||||
let array = [];
|
||||
for (let index = 0; index < 3; index++) {
|
||||
if (newValue[index]) {
|
||||
array.push(newValue[index].value);
|
||||
}
|
||||
}
|
||||
areaValue.value = array;
|
||||
} else {
|
||||
areaValue.value = [];
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
function handleChange(value: number[], selectedOptions: SmartAreaOption[]): void {
|
||||
emit("update:value", toRaw(selectedOptions));
|
||||
emit("change", value, toRaw(selectedOptions));
|
||||
}
|
||||
|
||||
const filter = (inputValue: string, path: SmartAreaOption[]) => {
|
||||
return path.some(
|
||||
(option) => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1
|
||||
);
|
||||
};
|
||||
</script>
|
@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<a-select
|
||||
v-model:value="selectValue"
|
||||
:style="`width: ${width}px`"
|
||||
:placeholder="placeholder"
|
||||
:showSearch="true"
|
||||
:allowClear="true"
|
||||
:size="size"
|
||||
@change="handleChange"
|
||||
@deselect="handleChange"
|
||||
>
|
||||
<a-select-option
|
||||
v-for="item in $smartEnumPlugin.getValueDescList('FLAG_NUMBER_ENUM')"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
>
|
||||
{{ item.desc }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import _ from "lodash";
|
||||
import { ref, watch } from "vue";
|
||||
|
||||
interface SmartBooleanSelectProps {
|
||||
value?: boolean;
|
||||
width: number;
|
||||
size?: string;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<SmartBooleanSelectProps>(), {
|
||||
value: undefined,
|
||||
width: 100,
|
||||
placeholder: "请选择",
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "update:value", value);
|
||||
(e: "change", value);
|
||||
}>();
|
||||
|
||||
function convertBoolean2number(value: null | boolean | undefined): null | number {
|
||||
let result: null | number = null;
|
||||
if (_.isNaN(value) || _.isNull(value) || _.isUndefined(value)) {
|
||||
result = null;
|
||||
} else {
|
||||
result = value ? 1 : 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const selectValue = ref<any>(convertBoolean2number(props.value));
|
||||
|
||||
// 箭头value变化
|
||||
watch(
|
||||
() => props.value,
|
||||
(newValue) => {
|
||||
selectValue.value = convertBoolean2number(newValue);
|
||||
}
|
||||
);
|
||||
|
||||
const handleChange = (value) => {
|
||||
console.log("boolean enum select", value);
|
||||
let booleanResult = null;
|
||||
if (!_.isUndefined(value)) {
|
||||
booleanResult = value === 1 ? true : false;
|
||||
}
|
||||
emit("update:value", booleanResult);
|
||||
emit("change", booleanResult);
|
||||
};
|
||||
</script>
|
@ -0,0 +1,71 @@
|
||||
<!--
|
||||
* @Description:
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-03
|
||||
* @LastEditTime: 2021-08-28 15:31:50
|
||||
* @LastEditors: zhuoda
|
||||
-->
|
||||
<template>
|
||||
<a-select
|
||||
v-model:value="selectValue"
|
||||
:style="`width: ${width}px`"
|
||||
:placeholder="props.placeholder"
|
||||
:showSearch="true"
|
||||
:allowClear="true"
|
||||
:size="size"
|
||||
@change="handleChange"
|
||||
@deselect="handleChange"
|
||||
:disabled="disabled"
|
||||
>
|
||||
<a-select-option
|
||||
v-for="item in $smartEnumPlugin.getValueDescList(props.enumName)"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
>
|
||||
{{ item.desc }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from "vue";
|
||||
|
||||
// ========================
|
||||
interface SmartEnumSelectProps {
|
||||
enumName: string;
|
||||
value?: string | number | string[] | number[];
|
||||
width?: number;
|
||||
size?: string;
|
||||
placeholder?: string;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<SmartEnumSelectProps>(), {
|
||||
enumName: undefined,
|
||||
value: undefined,
|
||||
width: 100,
|
||||
placeholder: "请选择",
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "update:value", value: any): void;
|
||||
(e: "change", value: any): void;
|
||||
}>();
|
||||
|
||||
// ======================== 逻辑
|
||||
|
||||
const selectValue = ref(props.value);
|
||||
|
||||
// 箭头value变化
|
||||
watch(
|
||||
() => props.value,
|
||||
(newValue) => {
|
||||
selectValue.value = newValue;
|
||||
}
|
||||
);
|
||||
|
||||
function handleChange(value: any): void {
|
||||
emit("update:value", value);
|
||||
emit("change", value);
|
||||
}
|
||||
</script>
|
@ -0,0 +1,13 @@
|
||||
import {useSpinStore} from "/@/store/modules/system/spin";
|
||||
|
||||
|
||||
export const SmartLoading = {
|
||||
|
||||
show: () => {
|
||||
useSpinStore().show();
|
||||
},
|
||||
|
||||
hide: () => {
|
||||
useSpinStore().hide();
|
||||
}
|
||||
};
|
@ -0,0 +1,60 @@
|
||||
<template>
|
||||
|
||||
<div class="smart-table-wrapper">
|
||||
<a-button type="primary" shape="circle" @click="v2showColumnOperator">
|
||||
<template #icon>
|
||||
<SettingOutlined/>
|
||||
</template>
|
||||
</a-button>
|
||||
<a-button type="primary" shape="circle">
|
||||
<template #icon>
|
||||
<ExportOutlined/>
|
||||
</template>
|
||||
</a-button>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {SettingOutlined, ExportOutlined} from "@ant-design/icons-vue";
|
||||
import {defineComponent, reactive, UnwrapRef} from "vue";
|
||||
import _ from "lodash";
|
||||
|
||||
export default defineComponent({
|
||||
name: "SmartTableOperator",
|
||||
components: {
|
||||
SettingOutlined, ExportOutlined
|
||||
},
|
||||
props: {
|
||||
columnArray: Array,
|
||||
obj:Object,
|
||||
text:String
|
||||
},
|
||||
methods:{
|
||||
v2showColumnOperator(){
|
||||
// this.obj.a = 1;
|
||||
// this.text = '3';
|
||||
// this.columnArray.splice(0,1);
|
||||
|
||||
console.log(2, this.columnArray);
|
||||
}
|
||||
},
|
||||
setup(props) {
|
||||
|
||||
const showColumnOperator = () => {
|
||||
// arr.splice(0);
|
||||
// props.columnArray = props.columnArray.splice(0,1);
|
||||
console.log(props.columnArray);
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
showColumnOperator
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
@ -0,0 +1,158 @@
|
||||
<!--
|
||||
* @Description:
|
||||
* @version:
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-12 17:34:23
|
||||
* @LastEditors: zhuoda
|
||||
* @LastEditTime: 2021-09-01 21:03:33
|
||||
-->
|
||||
<template>
|
||||
<div class="clearfix">
|
||||
<a-upload
|
||||
:accept="props.accept"
|
||||
:customRequest="customRequest"
|
||||
:file-list="fileList"
|
||||
list-type="picture-card"
|
||||
:headers="{ 'x-access-token': useUserStore().getToken }"
|
||||
:before-upload="beforeUpload"
|
||||
@preview="handlePreview"
|
||||
@change="handleChange"
|
||||
@remove="handleRemove"
|
||||
>
|
||||
<div v-if="fileList.length < props.maxSize">
|
||||
<PlusOutlined />
|
||||
<div class="ant-upload-text">
|
||||
{{ buttonText }}
|
||||
</div>
|
||||
</div>
|
||||
</a-upload>
|
||||
<a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel">
|
||||
<img alt="example" style="width: 100%" :src="previewUrl" />
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed } from "vue";
|
||||
import { message } from "ant-design-vue";
|
||||
import { fileApi } from "/@/api/business/file/file-api";
|
||||
import { useUserStore } from "/@/store/modules/system/user";
|
||||
import { useSpinStore } from "/@/store/modules/system/spin";
|
||||
import { FILE_FOLDER_TYPE_ENUM } from "/@/constants/business/file";
|
||||
// =========== 计算属性 获取token =============
|
||||
const getToken = computed(() => {
|
||||
return "";
|
||||
});
|
||||
|
||||
// ========================
|
||||
interface UploadProps {
|
||||
value?: string;
|
||||
buttonText?: string;
|
||||
showUploadBtn?: boolean;
|
||||
defaultFileList?: any;
|
||||
multiple?: boolean;
|
||||
maxUploadSize?: number; // 最多上传文件数量
|
||||
accept?: string; // 上传的文件类型
|
||||
maxSize?: number;
|
||||
folder?: number; //文件上传类型
|
||||
fileList?: Array<FileUploadVo>;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<UploadProps>(), {
|
||||
value: undefined,
|
||||
buttonText: "点击上传附件",
|
||||
showUploadBtn: true,
|
||||
defaultFileList: [],
|
||||
multiple: false,
|
||||
maxUploadSize: 10,
|
||||
maxSize: 10,
|
||||
accept: "",
|
||||
folder: FILE_FOLDER_TYPE_ENUM.COMMON.value,
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: "update:value", value: any): void;
|
||||
(e: "change", value: any): void;
|
||||
}>();
|
||||
|
||||
// 重新修改图片展示字段
|
||||
const files = computed(() => {
|
||||
let res = [];
|
||||
if (props.fileList && props.fileList.length > 0) {
|
||||
props.fileList.forEach((element) => {
|
||||
element.url = element.fileUrl;
|
||||
res.push(element);
|
||||
});
|
||||
return res;
|
||||
}
|
||||
return res;
|
||||
});
|
||||
// ======================== 逻辑
|
||||
const previewVisible = ref<boolean>(false);
|
||||
const fileList = ref(files.value);
|
||||
const previewUrl = ref<string>("");
|
||||
|
||||
const customRequest = async (options: any) => {
|
||||
useSpinStore().show();
|
||||
try {
|
||||
console.log(options);
|
||||
const formData = new FormData();
|
||||
formData.append("file", options.file);
|
||||
let res = await fileApi.uploadFile(
|
||||
formData,
|
||||
props.folder
|
||||
);
|
||||
let file = res.data;
|
||||
file.url = file.fileUrl;
|
||||
fileList.value.push(file);
|
||||
emit("change", fileList.value);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} finally {
|
||||
useSpinStore().hide();
|
||||
}
|
||||
};
|
||||
|
||||
function handleChange(info: any) {
|
||||
let fileStatus: string = info.file.status;
|
||||
let file = info.file;
|
||||
if (fileStatus == "removed") {
|
||||
let index = fileList.value.findIndex((e) => e.fileId == file.fileId);
|
||||
if (index != -1) {
|
||||
fileList.value.splice(index, 1);
|
||||
emit("change", fileList.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleRemove(file) {
|
||||
console.log(fileList.value);
|
||||
}
|
||||
|
||||
function beforeUpload(file) {
|
||||
const isLimitSize = file.size / 1024 / 1024 < props.maxSize;
|
||||
if (!isLimitSize) {
|
||||
return message.error(`上传的文件必须小于${props.maxSize}Mb`);
|
||||
}
|
||||
return isLimitSize;
|
||||
}
|
||||
function handleCancel() {
|
||||
previewVisible.value = false;
|
||||
}
|
||||
const handlePreview = async (file: any) => {
|
||||
previewUrl.value = file.url || file.preview;
|
||||
previewVisible.value = true;
|
||||
};
|
||||
|
||||
function clear() {
|
||||
fileList.value = [];
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
clear,
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
:deep(.ant-upload-picture-card-wrapper) {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
37
admin-web/javascript-ant-design-vue/src/config/app-config.js
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-03 10:27:11
|
||||
* @LastEditTime: 2021-08-25 17:01:33
|
||||
* @LastEditors: zhuoda
|
||||
* @Description:
|
||||
* @FilePath: /smart-admin/src/config/app-config.ts
|
||||
*/
|
||||
|
||||
/**
|
||||
* 应用默认配置
|
||||
*/
|
||||
|
||||
export const appDefaultConfig = {
|
||||
// i18n 语言选择
|
||||
languageType: 'zh_CN',
|
||||
// 布局: side 或者 side-expand
|
||||
layout: 'side-expand',
|
||||
// 主题
|
||||
theme: 'dark',
|
||||
// 手机模式最大宽度 768px,如果少于768px,则手机自适应
|
||||
mobileMaxWidth: 768,
|
||||
// 侧边菜单宽度 , 默认为256px
|
||||
sideMenuWidth: 256,
|
||||
// 标签页
|
||||
multiPageTagFlag: true,
|
||||
// 标签页缓存, keep-alive, true 开启缓存; false 不开启
|
||||
multiPageTagKeepAliveFlag: true,
|
||||
// 固定头部状态栏,true:固定,false:不固定
|
||||
headerFixedFlag: true,
|
||||
// 固定侧边栏,true:固定,false:不固定
|
||||
sideBarFixedFlag: true,
|
||||
// 隐藏设置,true:隐藏,false:不隐藏
|
||||
hideSettingFlag: false,
|
||||
// 首页页面Name
|
||||
homePageName: 'Home',
|
||||
};
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-03 10:27:11
|
||||
* @LastEditTime: 2021-09-01
|
||||
* @LastEditors: zhuoda
|
||||
* @Description:
|
||||
* @FilePath: /smart-admin/src/config/project-config.ts
|
||||
*/
|
||||
import moment from 'moment';
|
||||
|
||||
/**
|
||||
* 项目默认配置
|
||||
*/
|
||||
|
||||
export const projectDefaultConfig = {
|
||||
// 项目名称
|
||||
projectName: 'SmartAdmin',
|
||||
// 版权信息
|
||||
copyright: 'Copyright ©2015-' + moment().format('YYYY') + '版权所有: 1024创新实验室 ',
|
||||
// 点击版权的跳转
|
||||
copyrightUrl: 'http://www.1024lab.net',
|
||||
// 版本: 1.0.0
|
||||
version: '2.0.0-beta',
|
||||
// build时间戳
|
||||
buildTime: moment().format('YYYY-MM-DD HH:mm:ss'),
|
||||
};
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-11
|
||||
* @LastEditTime: 2021-09-01 22:31:37
|
||||
* @LastEditors: zhuoda
|
||||
*/
|
||||
|
||||
// 商品分类
|
||||
export const GOODS_TYPE_ENUM = {
|
||||
BOOK: {
|
||||
value: 1,
|
||||
desc: '图书',
|
||||
},
|
||||
COURSE: {
|
||||
value: 2,
|
||||
desc: '课程',
|
||||
},
|
||||
};
|
||||
export default {
|
||||
GOODS_TYPE_ENUM,
|
||||
};
|
37
admin-web/javascript-ant-design-vue/src/constants/common.js
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-03
|
||||
* @LastEditTime: 2021-08-27
|
||||
* @LastEditors: zhuoda
|
||||
*/
|
||||
|
||||
export const PAGE_SIZE = 15;
|
||||
|
||||
export const PAGE_SIZE_OPTIONS = ['10', '15', '25', '35', '45', '55', '100', '150', '200', '300', '500'];
|
||||
|
||||
export const FLAG_NUMBER_ENUM = {
|
||||
TRUE: {
|
||||
value: 1,
|
||||
desc: '是',
|
||||
},
|
||||
FALSE: {
|
||||
value: 0,
|
||||
desc: '否',
|
||||
},
|
||||
};
|
||||
|
||||
export const GenderEnum = {
|
||||
UNKNOWN: {
|
||||
value: 0,
|
||||
desc: '未知',
|
||||
},
|
||||
MAN: {
|
||||
value: 1,
|
||||
desc: '男',
|
||||
},
|
||||
WOMAN: {
|
||||
value: 2,
|
||||
desc: '女',
|
||||
},
|
||||
};
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-16 15:12:42
|
||||
* @LastEditTime: 2021-08-27
|
||||
* @LastEditors: zhuoda
|
||||
* @Description:
|
||||
* @FilePath: /smart-admin/src/constants/system/employee.ts
|
||||
*/
|
||||
export const GENDER_ENUM = {
|
||||
UNKNOWN: {
|
||||
value: 0,
|
||||
desc: '未知',
|
||||
},
|
||||
MAN: {
|
||||
value: 1,
|
||||
desc: '男',
|
||||
},
|
||||
WOMAN: {
|
||||
value: 2,
|
||||
desc: '女',
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
GENDER_ENUM,
|
||||
};
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* @Author: zhuoda
|
||||
* @Date: 2021-08-09 08:58:11
|
||||
* @LastEditTime: 2021-08-18 20:13:28
|
||||
* @LastEditors: zhuoda
|
||||
* @Description:
|
||||
* @FilePath: /smart-admin/src/constants/system/local-storage-key.ts
|
||||
*/
|
||||
/**
|
||||
* key前缀
|
||||
*/
|
||||
const KEY_PREFIX = 'crm_';
|
||||
/**
|
||||
* localStorageKey集合
|
||||
*/
|
||||
export default {
|
||||
// 用户信息
|
||||
USER_INFO: `${KEY_PREFIX}user_info`,
|
||||
// 用户菜单路由
|
||||
USER_MENU: `${KEY_PREFIX}user_menu`,
|
||||
// 用户权限点
|
||||
USER_POINTS: `${KEY_PREFIX}user_points`,
|
||||
// 用户的tag列表
|
||||
USER_TAG_NAV: `${KEY_PREFIX}user_tag_nav`,
|
||||
};
|
12
admin-web/javascript-ant-design-vue/src/i18n/index.js
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
// 语言选择数组
|
||||
export const i18nList = [
|
||||
{
|
||||
text: '简体中文',
|
||||
value: 'zh_CN',
|
||||
},
|
||||
{
|
||||
text: 'English',
|
||||
value: 'en',
|
||||
},
|
||||
]
|
@ -0,0 +1,5 @@
|
||||
import settings from './account/settings'
|
||||
|
||||
export default {
|
||||
...settings
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
export default {
|
||||
'account.settings.menuMap.basic': 'Basic Settings',
|
||||
'account.settings.menuMap.security': 'Security Settings',
|
||||
'account.settings.menuMap.custom': 'Custom Settings',
|
||||
'account.settings.menuMap.binding': 'Account Binding',
|
||||
'account.settings.menuMap.notification': 'New Message Notification',
|
||||
'account.settings.basic.avatar': 'Avatar',
|
||||
'account.settings.basic.change-avatar': 'Change avatar',
|
||||
'account.settings.basic.email': 'Email',
|
||||
'account.settings.basic.email-message': 'Please input your email!',
|
||||
'account.settings.basic.nickname': 'Nickname',
|
||||
'account.settings.basic.nickname-message': 'Please input your Nickname!',
|
||||
'account.settings.basic.profile': 'Personal profile',
|
||||
'account.settings.basic.profile-message': 'Please input your personal profile!',
|
||||
'account.settings.basic.profile-placeholder': 'Brief introduction to yourself',
|
||||
'account.settings.basic.country': 'Country/Region',
|
||||
'account.settings.basic.country-message': 'Please input your country!',
|
||||
'account.settings.basic.geographic': 'Province or city',
|
||||
'account.settings.basic.geographic-message': 'Please input your geographic info!',
|
||||
'account.settings.basic.address': 'Street Address',
|
||||
'account.settings.basic.address-message': 'Please input your address!',
|
||||
'account.settings.basic.phone': 'Phone Number',
|
||||
'account.settings.basic.phone-message': 'Please input your phone!',
|
||||
'account.settings.basic.update': 'Update Information',
|
||||
'account.settings.basic.update.success': 'Update basic information successfully',
|
||||
'account.settings.security.strong': 'Strong',
|
||||
'account.settings.security.medium': 'Medium',
|
||||
'account.settings.security.weak': 'Weak',
|
||||
'account.settings.security.password': 'Account Password',
|
||||
'account.settings.security.password-description': 'Current password strength:',
|
||||
'account.settings.security.phone': 'Security Phone',
|
||||
'account.settings.security.phone-description': 'Bound phone:',
|
||||
'account.settings.security.question': 'Security Question',
|
||||
'account.settings.security.question-description':
|
||||
'The security question is not set, and the security policy can effectively protect the account security',
|
||||
'account.settings.security.email': 'Backup Email',
|
||||
'account.settings.security.email-description': 'Bound Email:',
|
||||
'account.settings.security.mfa': 'MFA Device',
|
||||
'account.settings.security.mfa-description':
|
||||
'Unbound MFA device, after binding, can be confirmed twice',
|
||||
'account.settings.security.modify': 'Modify',
|
||||
'account.settings.security.set': 'Set',
|
||||
'account.settings.security.bind': 'Bind',
|
||||
'account.settings.binding.taobao': 'Binding Taobao',
|
||||
'account.settings.binding.taobao-description': 'Currently unbound Taobao account',
|
||||
'account.settings.binding.alipay': 'Binding Alipay',
|
||||
'account.settings.binding.alipay-description': 'Currently unbound Alipay account',
|
||||
'account.settings.binding.dingding': 'Binding DingTalk',
|
||||
'account.settings.binding.dingding-description': 'Currently unbound DingTalk account',
|
||||
'account.settings.binding.bind': 'Bind',
|
||||
'account.settings.notification.password': 'Account Password',
|
||||
'account.settings.notification.password-description':
|
||||
'Messages from other users will be notified in the form of a station letter',
|
||||
'account.settings.notification.messages': 'System Messages',
|
||||
'account.settings.notification.messages-description':
|
||||
'System messages will be notified in the form of a station letter',
|
||||
'account.settings.notification.todo': 'To-do Notification',
|
||||
'account.settings.notification.todo-description':
|
||||
'The to-do list will be notified in the form of a letter from the station',
|
||||
'account.settings.settings.open': 'Open',
|
||||
'account.settings.settings.close': 'Close'
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
import analysis from './dashboard/analysis'
|
||||
|
||||
export default {
|
||||
...analysis
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
export default {
|
||||
'dashboard.analysis.test': 'Gongzhuan No.{no} shop',
|
||||
'dashboard.analysis.introduce': 'Introduce',
|
||||
'dashboard.analysis.total-sales': 'Total Sales',
|
||||
'dashboard.analysis.day-sales': 'Daily Sales',
|
||||
'dashboard.analysis.visits': 'Visits',
|
||||
'dashboard.analysis.visits-trend': 'Visits Trend',
|
||||
'dashboard.analysis.visits-ranking': 'Visits Ranking',
|
||||
'dashboard.analysis.day-visits': 'Daily Visits',
|
||||
'dashboard.analysis.week': 'WoW Change',
|
||||
'dashboard.analysis.day': 'DoD Change',
|
||||
'dashboard.analysis.payments': 'Payments',
|
||||
'dashboard.analysis.conversion-rate': 'Conversion Rate',
|
||||
'dashboard.analysis.operational-effect': 'Operational Effect',
|
||||
'dashboard.analysis.sales-trend': 'Stores Sales Trend',
|
||||
'dashboard.analysis.sales-ranking': 'Sales Ranking',
|
||||
'dashboard.analysis.all-year': 'All Year',
|
||||
'dashboard.analysis.all-month': 'All Month',
|
||||
'dashboard.analysis.all-week': 'All Week',
|
||||
'dashboard.analysis.all-day': 'All day',
|
||||
'dashboard.analysis.search-users': 'Search Users',
|
||||
'dashboard.analysis.per-capita-search': 'Per Capita Search',
|
||||
'dashboard.analysis.online-top-search': 'Online Top Search',
|
||||
'dashboard.analysis.the-proportion-of-sales': 'The Proportion Of Sales',
|
||||
'dashboard.analysis.dropdown-option-one': 'Operation one',
|
||||
'dashboard.analysis.dropdown-option-two': 'Operation two',
|
||||
'dashboard.analysis.channel.all': 'ALL',
|
||||
'dashboard.analysis.channel.online': 'Online',
|
||||
'dashboard.analysis.channel.stores': 'Stores',
|
||||
'dashboard.analysis.sales': 'Sales',
|
||||
'dashboard.analysis.traffic': 'Traffic',
|
||||
'dashboard.analysis.table.rank': 'Rank',
|
||||
'dashboard.analysis.table.search-keyword': 'Keyword',
|
||||
'dashboard.analysis.table.users': 'Users',
|
||||
'dashboard.analysis.table.weekly-range': 'Weekly Range'
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
import basicForm from './form/basicForm'
|
||||
|
||||
export default {
|
||||
...basicForm
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
export default {
|
||||
'form.basic-form.basic.title': 'Basic form',
|
||||
'form.basic-form.basic.description':
|
||||
'Form pages are used to collect or verify information to users, and basic forms are common in scenarios where there are fewer data items.',
|
||||
'form.basic-form.title.label': 'Title',
|
||||
'form.basic-form.title.placeholder': 'Give the target a name',
|
||||
'form.basic-form.title.required': 'Please enter a title',
|
||||
'form.basic-form.date.label': 'Start and end date',
|
||||
'form.basic-form.placeholder.start': 'Start date',
|
||||
'form.basic-form.placeholder.end': 'End date',
|
||||
'form.basic-form.date.required': 'Please select the start and end date',
|
||||
'form.basic-form.goal.label': 'Goal description',
|
||||
'form.basic-form.goal.placeholder': 'Please enter your work goals',
|
||||
'form.basic-form.goal.required': 'Please enter a description of the goal',
|
||||
'form.basic-form.standard.label': 'Metrics',
|
||||
'form.basic-form.standard.placeholder': 'Please enter a metric',
|
||||
'form.basic-form.standard.required': 'Please enter a metric',
|
||||
'form.basic-form.client.label': 'Client',
|
||||
'form.basic-form.label.tooltip': 'Target service object',
|
||||
'form.basic-form.client.placeholder':
|
||||
'Please describe your customer service, internal customers directly @ Name / job number',
|
||||
'form.basic-form.client.required': 'Please describe the customers you serve',
|
||||
'form.basic-form.invites.label': 'Inviting critics',
|
||||
'form.basic-form.invites.placeholder':
|
||||
'Please direct @ Name / job number, you can invite up to 5 people',
|
||||
'form.basic-form.weight.label': 'Weight',
|
||||
'form.basic-form.weight.placeholder': 'Please enter weight',
|
||||
'form.basic-form.public.label': 'Target disclosure',
|
||||
'form.basic-form.label.help': 'Customers and invitees are shared by default',
|
||||
'form.basic-form.radio.public': 'Public',
|
||||
'form.basic-form.radio.partially-public': 'Partially public',
|
||||
'form.basic-form.radio.private': 'Private',
|
||||
'form.basic-form.publicUsers.placeholder': 'Open to',
|
||||
'form.basic-form.option.A': 'Colleague A',
|
||||
'form.basic-form.option.B': 'Colleague B',
|
||||
'form.basic-form.option.C': 'Colleague C',
|
||||
'form.basic-form.email.required': 'Please enter your email!',
|
||||
'form.basic-form.email.wrong-format': 'The email address is in the wrong format!',
|
||||
'form.basic-form.userName.required': 'Please enter your userName!',
|
||||
'form.basic-form.password.required': 'Please enter your password!',
|
||||
'form.basic-form.password.twice': 'The passwords entered twice do not match!',
|
||||
'form.basic-form.strength.msg':
|
||||
"Please enter at least 6 characters and don't use passwords that are easy to guess.",
|
||||
'form.basic-form.strength.strong': 'Strength: strong',
|
||||
'form.basic-form.strength.medium': 'Strength: medium',
|
||||
'form.basic-form.strength.short': 'Strength: too short',
|
||||
'form.basic-form.confirm-password.required': 'Please confirm your password!',
|
||||
'form.basic-form.phone-number.required': 'Please enter your phone number!',
|
||||
'form.basic-form.phone-number.wrong-format': 'Malformed phone number!',
|
||||
'form.basic-form.verification-code.required': 'Please enter the verification code!',
|
||||
'form.basic-form.form.get-captcha': 'Get Captcha',
|
||||
'form.basic-form.captcha.second': 'sec',
|
||||
'form.basic-form.form.optional': ' (optional) ',
|
||||
'form.basic-form.form.submit': 'Submit',
|
||||
'form.basic-form.form.save': 'Save',
|
||||
'form.basic-form.email.placeholder': 'Email',
|
||||
'form.basic-form.password.placeholder': 'Password',
|
||||
'form.basic-form.confirm-password.placeholder': 'Confirm password',
|
||||
'form.basic-form.phone-number.placeholder': 'Phone number',
|
||||
'form.basic-form.verification-code.placeholder': 'Verification code'
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
export default {
|
||||
submit: 'Submit',
|
||||
save: 'Save',
|
||||
'submit.ok': 'Submit successfully',
|
||||
'save.ok': 'Saved successfully'
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
import antdEnUS from 'ant-design-vue/es/locale-provider/en_US'
|
||||
import momentEU from 'moment/locale/eu'
|
||||
import global from './global'
|
||||
|
||||
import menu from './menu'
|
||||
import setting from './setting'
|
||||
import user from './user'
|
||||
|
||||
import dashboard from './dashboard'
|
||||
import form from './form'
|
||||
import result from './result'
|
||||
import account from './account'
|
||||
|
||||
const components = {
|
||||
antLocale: antdEnUS,
|
||||
momentName: 'eu',
|
||||
momentLocale: momentEU
|
||||
}
|
||||
|
||||
export default {
|
||||
message: '-',
|
||||
|
||||
'layouts.usermenu.dialog.title': 'Message',
|
||||
'layouts.usermenu.dialog.content': 'Are you sure you would like to logout?',
|
||||
'layouts.userLayout.title': 'Ant Design is the most influential web design specification in Xihu district',
|
||||
...components,
|
||||
...global,
|
||||
...menu,
|
||||
...setting,
|
||||
...user,
|
||||
...dashboard,
|
||||
...form,
|
||||
...result,
|
||||
...account
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
export default {
|
||||
'menu.welcome': 'Welcome',
|
||||
'menu.home': 'Home',
|
||||
'menu.dashboard': 'Dashboard',
|
||||
'menu.dashboard.analysis': 'Analysis',
|
||||
'menu.dashboard.monitor': 'Monitor',
|
||||
'menu.dashboard.workplace': 'Workplace',
|
||||
'menu.form': 'Form',
|
||||
'menu.form.basic-form': 'Basic Form',
|
||||
'menu.form.step-form': 'Step Form',
|
||||
'menu.form.step-form.info': 'Step Form(write transfer information)',
|
||||
'menu.form.step-form.confirm': 'Step Form(confirm transfer information)',
|
||||
'menu.form.step-form.result': 'Step Form(finished)',
|
||||
'menu.form.advanced-form': 'Advanced Form',
|
||||
'menu.list': 'List',
|
||||
'menu.list.table-list': 'Search Table',
|
||||
'menu.list.basic-list': 'Basic List',
|
||||
'menu.list.card-list': 'Card List',
|
||||
'menu.list.search-list': 'Search List',
|
||||
'menu.list.search-list.articles': 'Search List(articles)',
|
||||
'menu.list.search-list.projects': 'Search List(projects)',
|
||||
'menu.list.search-list.applications': 'Search List(applications)',
|
||||
'menu.profile': 'Profile',
|
||||
'menu.profile.basic': 'Basic Profile',
|
||||
'menu.profile.advanced': 'Advanced Profile',
|
||||
'menu.result': 'Result',
|
||||
'menu.result.success': 'Success',
|
||||
'menu.result.fail': 'Fail',
|
||||
'menu.exception': 'Exception',
|
||||
'menu.exception.not-permission': '403',
|
||||
'menu.exception.not-find': '404',
|
||||
'menu.exception.server-error': '500',
|
||||
'menu.exception.trigger': 'Trigger',
|
||||
'menu.account': 'Account',
|
||||
'menu.account.center': 'Account Center',
|
||||
'menu.account.settings': 'Account Settings',
|
||||
'menu.account.trigger': 'Trigger Error',
|
||||
'menu.account.logout': 'Logout'
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
import success from './result/success'
|
||||
import fail from './result/fail'
|
||||
|
||||
export default {
|
||||
...success,
|
||||
...fail
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
export default {
|
||||
'result.fail.error.title': 'Submission Failed',
|
||||
'result.fail.error.description':
|
||||
'Please check and modify the following information before resubmitting.',
|
||||
'result.fail.error.hint-title': 'The content you submitted has the following error:',
|
||||
'result.fail.error.hint-text1': 'Your account has been frozen',
|
||||
'result.fail.error.hint-btn1': 'Thaw immediately',
|
||||
'result.fail.error.hint-text2': 'Your account is not yet eligible to apply',
|
||||
'result.fail.error.hint-btn2': 'Upgrade immediately',
|
||||
'result.fail.error.btn-text': 'Return to modify'
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
export default {
|
||||
'result.success.title': 'Submission Success',
|
||||
'result.success.description':
|
||||
'The submission results page is used to feed back the results of a series of operational tasks. If it is a simple operation, use the Message global prompt feedback. This text area can show a simple supplementary explanation. If there is a similar requirement for displaying “documents”, the following gray area can present more complicated content.',
|
||||
'result.success.operate-title': 'Project Name',
|
||||
'result.success.operate-id': 'Project ID',
|
||||
'result.success.principal': 'Principal',
|
||||
'result.success.operate-time': 'Effective time',
|
||||
'result.success.step1-title': 'Create project',
|
||||
'result.success.step1-operator': 'Qu Lili',
|
||||
'result.success.step2-title': 'Departmental preliminary review',
|
||||
'result.success.step2-operator': 'Zhou Maomao',
|
||||
'result.success.step2-extra': 'Urge',
|
||||
'result.success.step3-title': 'Financial review',
|
||||
'result.success.step4-title': 'Finish',
|
||||
'result.success.btn-return': 'Back List',
|
||||
'result.success.btn-project': 'View Project',
|
||||
'result.success.btn-print': 'Print'
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
export default {
|
||||
'app.setting.pagestyle': 'Page style setting',
|
||||
'app.setting.pagestyle.light': 'Light style',
|
||||
'app.setting.pagestyle.dark': 'Dark style',
|
||||
'app.setting.pagestyle.realdark': 'RealDark style',
|
||||
'app.setting.themecolor': 'Theme Color',
|
||||
'app.setting.navigationmode': 'Navigation Mode',
|
||||
'app.setting.content-width': 'Content Width',
|
||||
'app.setting.fixedheader': 'Fixed Header',
|
||||
'app.setting.fixedsidebar': 'Fixed Sidebar',
|
||||
'app.setting.sidemenu': 'Side Menu Layout',
|
||||
'app.setting.topmenu': 'Top Menu Layout',
|
||||
'app.setting.content-width.fixed': 'Fixed',
|
||||
'app.setting.content-width.fluid': 'Fluid',
|
||||
'app.setting.othersettings': 'Other Settings',
|
||||
'app.setting.weakmode': 'Weak Mode',
|
||||
'app.setting.copy': 'Copy Setting',
|
||||
'app.setting.loading': 'Loading theme',
|
||||
'app.setting.copyinfo': 'copy success,please replace defaultSettings in src/config/defaultSettings.js',
|
||||
'app.setting.production.hint': 'Setting panel shows in development environment only, please manually modify',
|
||||
'app.setting.themecolor.daybreak': 'Daybreak Blue',
|
||||
'app.setting.themecolor.dust': 'Dust Red',
|
||||
'app.setting.themecolor.volcano': 'Volcano',
|
||||
'app.setting.themecolor.sunset': 'Sunset Orange',
|
||||
'app.setting.themecolor.cyan': 'Cyan',
|
||||
'app.setting.themecolor.green': 'Polar Green',
|
||||
'app.setting.themecolor.geekblue': 'Geek Blue',
|
||||
'app.setting.themecolor.purple': 'Golden Purple'
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
export default {
|
||||
'user.login.userName': 'userName',
|
||||
'user.login.password': 'password',
|
||||
'user.login.username.placeholder': 'Account: admin',
|
||||
'user.login.password.placeholder': 'password: admin or ant.design',
|
||||
'user.login.message-invalid-credentials':
|
||||
'Invalid username or password(admin/ant.design)',
|
||||
'user.login.message-invalid-verification-code': 'Invalid verification code',
|
||||
'user.login.tab-login-credentials': 'Credentials',
|
||||
'user.login.tab-login-mobile': 'Mobile number',
|
||||
'user.login.mobile.placeholder': 'Mobile number',
|
||||
'user.login.mobile.verification-code.placeholder': 'Verification code',
|
||||
'user.login.remember-me': 'Remember me',
|
||||
'user.login.forgot-password': 'Forgot your password?',
|
||||
'user.login.sign-in-with': 'Sign in with',
|
||||
'user.login.signup': 'Sign up',
|
||||
'user.login.login': 'Login',
|
||||
'user.register.register': 'Register',
|
||||
'user.register.email.placeholder': 'Email',
|
||||
'user.register.password.placeholder': 'Password ',
|
||||
'user.register.password.popover-message': 'Please enter at least 6 characters. Please do not use passwords that are easy to guess. ',
|
||||
'user.register.confirm-password.placeholder': 'Confirm password',
|
||||
'user.register.get-verification-code': 'Get code',
|
||||
'user.register.sign-in': 'Already have an account?',
|
||||
'user.register-result.msg': 'Account:registered at {email}',
|
||||
'user.register-result.activation-email':
|
||||
'The activation email has been sent to your email address and is valid for 24 hours. Please log in to the email in time and click on the link in the email to activate the account.',
|
||||
'user.register-result.back-home': 'Back to home',
|
||||
'user.register-result.view-mailbox': 'View mailbox',
|
||||
'user.email.required': 'Please enter your email!',
|
||||
'user.email.wrong-format': 'The email address is in the wrong format!',
|
||||
'user.userName.required': 'Please enter account name or email address',
|
||||
'user.password.required': 'Please enter your password!',
|
||||
'user.password.twice.msg': 'The passwords entered twice do not match!',
|
||||
'user.password.strength.msg':
|
||||
'The password is not strong enough',
|
||||
'user.password.strength.strong': 'Strength: strong',
|
||||
'user.password.strength.medium': 'Strength: medium',
|
||||
'user.password.strength.low': 'Strength: low',
|
||||
'user.password.strength.short': 'Strength: too short',
|
||||
'user.confirm-password.required': 'Please confirm your password!',
|
||||
'user.phone-number.required': 'Please enter your phone number!',
|
||||
'user.phone-number.wrong-format': 'Please enter a valid phone number',
|
||||
'user.verification-code.required': 'Please enter the verification code!'
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
import settings from './account/settings'
|
||||
|
||||
export default {
|
||||
...settings
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
export default {
|
||||
'account.settings.menuMap.basic': '基本设置',
|
||||
'account.settings.menuMap.security': '安全设置',
|
||||
'account.settings.menuMap.custom': '个性化',
|
||||
'account.settings.menuMap.binding': '账号绑定',
|
||||
'account.settings.menuMap.notification': '新消息通知',
|
||||
'account.settings.basic.avatar': '头像',
|
||||
'account.settings.basic.change-avatar': '更换头像',
|
||||
'account.settings.basic.email': '邮箱',
|
||||
'account.settings.basic.email-message': '请输入您的邮箱!',
|
||||
'account.settings.basic.nickname': '昵称',
|
||||
'account.settings.basic.nickname-message': '请输入您的昵称!',
|
||||
'account.settings.basic.profile': '个人简介',
|
||||
'account.settings.basic.profile-message': '请输入个人简介!',
|
||||
'account.settings.basic.profile-placeholder': '个人简介',
|
||||
'account.settings.basic.country': '国家/地区',
|
||||
'account.settings.basic.country-message': '请输入您的国家或地区!',
|
||||
'account.settings.basic.geographic': '所在省市',
|
||||
'account.settings.basic.geographic-message': '请输入您的所在省市!',
|
||||
'account.settings.basic.address': '街道地址',
|
||||
'account.settings.basic.address-message': '请输入您的街道地址!',
|
||||
'account.settings.basic.phone': '联系电话',
|
||||
'account.settings.basic.phone-message': '请输入您的联系电话!',
|
||||
'account.settings.basic.update': '更新基本信息',
|
||||
'account.settings.basic.update.success': '更新基本信息成功',
|
||||
'account.settings.security.strong': '强',
|
||||
'account.settings.security.medium': '中',
|
||||
'account.settings.security.weak': '弱',
|
||||
'account.settings.security.password': '账户密码',
|
||||
'account.settings.security.password-description': '当前密码强度:',
|
||||
'account.settings.security.phone': '密保手机',
|
||||
'account.settings.security.phone-description': '已绑定手机:',
|
||||
'account.settings.security.question': '密保问题',
|
||||
'account.settings.security.question-description': '未设置密保问题,密保问题可有效保护账户安全',
|
||||
'account.settings.security.email': '备用邮箱',
|
||||
'account.settings.security.email-description': '已绑定邮箱:',
|
||||
'account.settings.security.mfa': 'MFA 设备',
|
||||
'account.settings.security.mfa-description': '未绑定 MFA 设备,绑定后,可以进行二次确认',
|
||||
'account.settings.security.modify': '修改',
|
||||
'account.settings.security.set': '设置',
|
||||
'account.settings.security.bind': '绑定',
|
||||
'account.settings.binding.taobao': '绑定淘宝',
|
||||
'account.settings.binding.taobao-description': '当前未绑定淘宝账号',
|
||||
'account.settings.binding.alipay': '绑定支付宝',
|
||||
'account.settings.binding.alipay-description': '当前未绑定支付宝账号',
|
||||
'account.settings.binding.dingding': '绑定钉钉',
|
||||
'account.settings.binding.dingding-description': '当前未绑定钉钉账号',
|
||||
'account.settings.binding.bind': '绑定',
|
||||
'account.settings.notification.password': '账户密码',
|
||||
'account.settings.notification.password-description': '其他用户的消息将以站内信的形式通知',
|
||||
'account.settings.notification.messages': '系统消息',
|
||||
'account.settings.notification.messages-description': '系统消息将以站内信的形式通知',
|
||||
'account.settings.notification.todo': '待办任务',
|
||||
'account.settings.notification.todo-description': '待办任务将以站内信的形式通知',
|
||||
'account.settings.settings.open': '开',
|
||||
'account.settings.settings.close': '关'
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
import analysis from './dashboard/analysis'
|
||||
|
||||
export default {
|
||||
...analysis
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
export default {
|
||||
'dashboard.analysis.test': '工专路 {no} 号店',
|
||||
'dashboard.analysis.introduce': '指标说明',
|
||||
'dashboard.analysis.total-sales': '总销售额',
|
||||
'dashboard.analysis.day-sales': '日均销售额¥',
|
||||
'dashboard.analysis.visits': '访问量',
|
||||
'dashboard.analysis.visits-trend': '访问量趋势',
|
||||
'dashboard.analysis.visits-ranking': '门店访问量排名',
|
||||
'dashboard.analysis.day-visits': '日访问量',
|
||||
'dashboard.analysis.week': '周同比',
|
||||
'dashboard.analysis.day': '日同比',
|
||||
'dashboard.analysis.payments': '支付笔数',
|
||||
'dashboard.analysis.conversion-rate': '转化率',
|
||||
'dashboard.analysis.operational-effect': '运营活动效果',
|
||||
'dashboard.analysis.sales-trend': '销售趋势',
|
||||
'dashboard.analysis.sales-ranking': '门店销售额排名',
|
||||
'dashboard.analysis.all-year': '全年',
|
||||
'dashboard.analysis.all-month': '本月',
|
||||
'dashboard.analysis.all-week': '本周',
|
||||
'dashboard.analysis.all-day': '今日',
|
||||
'dashboard.analysis.search-users': '搜索用户数',
|
||||
'dashboard.analysis.per-capita-search': '人均搜索次数',
|
||||
'dashboard.analysis.online-top-search': '线上热门搜索',
|
||||
'dashboard.analysis.the-proportion-of-sales': '销售额类别占比',
|
||||
'dashboard.analysis.dropdown-option-one': '操作一',
|
||||
'dashboard.analysis.dropdown-option-two': '操作二',
|
||||
'dashboard.analysis.channel.all': '全部渠道',
|
||||
'dashboard.analysis.channel.online': '线上',
|
||||
'dashboard.analysis.channel.stores': '门店',
|
||||
'dashboard.analysis.sales': '销售额',
|
||||
'dashboard.analysis.traffic': '客流量',
|
||||
'dashboard.analysis.table.rank': '排名',
|
||||
'dashboard.analysis.table.search-keyword': '搜索关键词',
|
||||
'dashboard.analysis.table.users': '用户数',
|
||||
'dashboard.analysis.table.weekly-range': '周涨幅'
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
import basicForm from './form/basicForm'
|
||||
|
||||
export default {
|
||||
...basicForm
|
||||
}
|