mirror of
https://gitee.com/lab1024/smart-admin.git
synced 2025-09-17 19:06:39 +08:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
f7155ac4c2
29
.gitignore
vendored
29
.gitignore
vendored
@ -1,6 +1,31 @@
|
|||||||
|
HELP.md
|
||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
!**/src/main/**
|
||||||
|
!**/src/test/**
|
||||||
|
|
||||||
|
### STS ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea
|
||||||
|
*.iws
|
||||||
*.iml
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
**/target/
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
build/
|
||||||
|
|
||||||
**/node_modules/
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
|
32
README.md
32
README.md
@ -25,32 +25,32 @@ gitee: [https://gitee.com/lab1024/smart-admin](https://gitee.com/lab1024/smart-
|
|||||||
#### 演示图
|
#### 演示图
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="http://img.zhuoluodada.cn/cut/1.1.0/11.png"/></td>
|
<td><img src="https://images.gitee.com/uploads/images/2020/1208/180453_252f5e9f_5469596.png"/></td>
|
||||||
<td><img src="http://img.zhuoluodada.cn/cut/1.1.0/12.png"/></td>
|
<td><img src="https://images.gitee.com/uploads/images/2020/1208/180630_ee5b4f46_5469596.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="http://img.zhuoluodada.cn/cut/1.1.0/21.png"/></td>
|
<td><img src="https://images.gitee.com/uploads/images/2020/1208/180737_9363e283_5469596.png"/></td>
|
||||||
<td><img src="http://img.zhuoluodada.cn/cut/1.1.0/22.png"/></td>
|
<td><img src="https://images.gitee.com/uploads/images/2020/1208/180802_aefb78f4_5469596.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="http://img.zhuoluodada.cn/cut/1.1.0/31.png"/></td>
|
<td><img src="https://images.gitee.com/uploads/images/2020/1208/180821_30fc7aaf_5469596.png")"/></td>
|
||||||
<td><img src="http://img.zhuoluodada.cn/cut/1.1.0/32.png"/></td>
|
<td><img src="https://images.gitee.com/uploads/images/2020/1208/180844_01ebd7d2_5469596.png")"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="http://img.zhuoluodada.cn/cut/1.1.0/41.png"/></td>
|
<td><img src="https://images.gitee.com/uploads/images/2020/1208/180902_02c8d838_5469596.png"/></td>
|
||||||
<td><img src="http://img.zhuoluodada.cn/cut/1.1.0/42.png"/></td>
|
<td><img src="https://images.gitee.com/uploads/images/2020/1208/180918_ff1f7ff5_5469596.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="http://img.zhuoluodada.cn/cut/1.1.0/51.png"/></td>
|
<td><img src="https://images.gitee.com/uploads/images/2020/1208/180938_86b39645_5469596.png"/></td>
|
||||||
<td><img src="http://img.zhuoluodada.cn/cut/1.1.0/52.png"/></td>
|
<td><img src="https://images.gitee.com/uploads/images/2020/1208/180956_69e25a9c_5469596.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="http://img.zhuoluodada.cn/cut/1.1.0/61.png"/></td>
|
<td><img src="https://images.gitee.com/uploads/images/2020/1208/181013_791d92f0_5469596.png"/></td>
|
||||||
<td><img src="http://img.zhuoluodada.cn/cut/1.1.0/62.png"/></td>
|
<td><img src="https://images.gitee.com/uploads/images/2020/1208/181032_9f0dbbee_5469596.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="http://img.zhuoluodada.cn/cut/1.1.0/71.png"/></td>
|
<td><img src="https://images.gitee.com/uploads/images/2020/1208/181049_099d0169_5469596.png"/></td>
|
||||||
<td><img src="http://img.zhuoluodada.cn/cut/1.1.0/72.png"/></td>
|
<td><img src="https://images.gitee.com/uploads/images/2020/1208/181104_914c457a_5469596.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ SmartAdmin微信群(**加我微信拉你入群!**)
|
|||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="http://img.zhuoluodada.cn/wechat/zhuoda-wechat.jpg"/></td>
|
<td><img src="https://images.gitee.com/uploads/images/2020/1208/181125_2ab89aa9_5469596.jpeg"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
@ -121,7 +121,7 @@ SmartAdmin微信群(**加我微信拉你入群!**)
|
|||||||
>*佛祖保佑捐赠这些人写程序永无bug,工资翻倍,迎娶白富美,走上人生巅峰!*
|
>*佛祖保佑捐赠这些人写程序永无bug,工资翻倍,迎娶白富美,走上人生巅峰!*
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="http://img.zhuoluodada.cn/wechat/zhuoda-wechat-money-v1.jpg"/></td>
|
<td><img src="https://images.gitee.com/uploads/images/2020/1208/181143_b6804a87_5469596.jpeg"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
2
smart-admin-h5/.browserslistrc
Normal file
2
smart-admin-h5/.browserslistrc
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
> 1%
|
||||||
|
last 2 versions
|
15
smart-admin-h5/.editorconfig
Normal file
15
smart-admin-h5/.editorconfig
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
# 字符
|
||||||
|
charset = utf-8
|
||||||
|
# 空格
|
||||||
|
indent_style = space
|
||||||
|
# 2个空格缩进
|
||||||
|
indent_size = 2
|
||||||
|
# 换行符
|
||||||
|
end_of_line = lf
|
||||||
|
# 文件的最后插入一个空行
|
||||||
|
insert_final_newline = true
|
||||||
|
# 删除行尾的空格
|
||||||
|
trim_trailing_whitespace = true
|
4
smart-admin-h5/.env.development
Normal file
4
smart-admin-h5/.env.development
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
NODE_ENV = development
|
||||||
|
VUE_APP_ENV = dev
|
||||||
|
VUE_APP_URL = http://127.0.0.1:10086/smart-admin-api/
|
||||||
|
|
3
smart-admin-h5/.env.local
Normal file
3
smart-admin-h5/.env.local
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
NODE_ENV = development
|
||||||
|
VUE_APP_ENV = local
|
||||||
|
VUE_APP_URL=http://127.0.0.1:10086/smart-admin-api/
|
3
smart-admin-h5/.env.pre
Normal file
3
smart-admin-h5/.env.pre
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
NODE_ENV = production
|
||||||
|
VUE_APP_ENV = pre
|
||||||
|
VUE_APP_URL = http://smartadmin.1024lab.net/api/
|
3
smart-admin-h5/.env.prod
Normal file
3
smart-admin-h5/.env.prod
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
NODE_ENV = production
|
||||||
|
VUE_APP_ENV = prod
|
||||||
|
VUE_APP_URL = http://smartadmin.1024lab.net/api/
|
3
smart-admin-h5/.env.sit
Normal file
3
smart-admin-h5/.env.sit
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
NODE_ENV = production
|
||||||
|
VUE_APP_ENV = sit
|
||||||
|
VUE_APP_URL=http://127.0.0.1:10086/smart-admin-api/
|
7
smart-admin-h5/.eslintignore
Normal file
7
smart-admin-h5/.eslintignore
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
# 忽略项目中某些文件的提交代码规范
|
||||||
|
|
||||||
|
build/*.js
|
||||||
|
src/assets
|
||||||
|
public
|
||||||
|
dist
|
232
smart-admin-h5/.eslintrc.js
Normal file
232
smart-admin-h5/.eslintrc.js
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
env: {
|
||||||
|
node: true
|
||||||
|
},
|
||||||
|
extends: [
|
||||||
|
'plugin:vue/essential',
|
||||||
|
'eslint:recommended'
|
||||||
|
],
|
||||||
|
parserOptions: {
|
||||||
|
parser: 'babel-eslint'
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
// 具体请看 https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/max-attributes-per-line.md
|
||||||
|
'vue/max-attributes-per-line': [
|
||||||
|
2,
|
||||||
|
{
|
||||||
|
singleline: 10,
|
||||||
|
multiline: {
|
||||||
|
max: 1,
|
||||||
|
allowFirstLine: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 在单行元素的内容前后需要换行符
|
||||||
|
'vue/singleline-html-element-content-newline': 'off',
|
||||||
|
// 在多行元素的内容之前和之后需要换行符
|
||||||
|
'vue/multiline-html-element-content-newline': 'off',
|
||||||
|
// JS/JSX中的组件名应该 大写驼峰 命名法
|
||||||
|
'vue/name-property-casing': ['error', 'PascalCase'],
|
||||||
|
// 给v-for设置键值,与key结合使用,可以高效的更新虚拟DOM
|
||||||
|
"vue/require-v-for-key": 1,
|
||||||
|
'vue/no-v-html': 'off',
|
||||||
|
// 在对象中强制使用getter/setter
|
||||||
|
'accessor-pairs': 2,
|
||||||
|
// 在箭头函数之前/之后需要空格
|
||||||
|
'arrow-spacing': [
|
||||||
|
2,
|
||||||
|
{
|
||||||
|
before: true,
|
||||||
|
after: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 在打开块之后和关闭块之前,禁止或强制执行块内部的空格
|
||||||
|
'block-spacing': [2, 'always'],
|
||||||
|
// 需要大括号样式
|
||||||
|
'brace-style': [
|
||||||
|
2,
|
||||||
|
'1tbs',
|
||||||
|
{
|
||||||
|
allowSingleLine: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 需要驼峰命名
|
||||||
|
camelcase: [
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
properties: 'always'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 要求或禁止使用尾随逗号;最后一个属性是不需要逗号
|
||||||
|
'comma-dangle': [2, 'never'],
|
||||||
|
// 强制逗号旁边的间距: 左右一个空格
|
||||||
|
'comma-spacing': [
|
||||||
|
2,
|
||||||
|
{
|
||||||
|
before: false,
|
||||||
|
after: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 逗号风格
|
||||||
|
'comma-style': [2, 'last'],
|
||||||
|
// 构建方法中使用super方法
|
||||||
|
'constructor-super': 2,
|
||||||
|
curly: [2, 'multi-line'],
|
||||||
|
// 在dot之前和之后强制换行
|
||||||
|
'dot-location': [2, 'property'],
|
||||||
|
// 在文件末尾要求或禁止换行
|
||||||
|
'eol-last': 2,
|
||||||
|
// 是否使用全等
|
||||||
|
eqeqeq: ['error', 'always', { null: 'ignore' }],
|
||||||
|
// 在生成器函数中强制执行*周围的间距
|
||||||
|
'generator-star-spacing': [2, {
|
||||||
|
'before': true,
|
||||||
|
'after': true
|
||||||
|
}],
|
||||||
|
// 强制执行回调错误处理
|
||||||
|
'handle-callback-err': [1, '^(err|error)$'],
|
||||||
|
// 强制执行一致的缩进
|
||||||
|
'indent': [2, 2, {
|
||||||
|
'SwitchCase': 1
|
||||||
|
}],
|
||||||
|
// 强制在JSX文件中一致使用单引号
|
||||||
|
'jsx-quotes': [2, 'prefer-single'],
|
||||||
|
// 在对象属性中强制键和值之间的一致间距
|
||||||
|
'key-spacing': [2, {
|
||||||
|
'beforeColon': false,
|
||||||
|
'afterColon': true
|
||||||
|
}],
|
||||||
|
// 关键字前后强制执行一致的间距
|
||||||
|
'keyword-spacing': [2, {
|
||||||
|
'before': true,
|
||||||
|
'after': true
|
||||||
|
}],
|
||||||
|
// 要求构造函数名称以大写字母开头
|
||||||
|
'new-cap': [2, {
|
||||||
|
'newIsCap': true,
|
||||||
|
'capIsNew': false
|
||||||
|
}],
|
||||||
|
'new-parens': 2, // 调用不带参数的函数时需要括号
|
||||||
|
'no-array-constructor': 2, // 禁止阵列构建器
|
||||||
|
'no-caller': 2, // 禁止使用来电者/被叫者
|
||||||
|
'no-console': 'off', // 不允许使用控制台
|
||||||
|
'no-class-assign': 2, // 禁止修改类声明的变量
|
||||||
|
'no-cond-assign': 2, // 在条件语句中禁止赋值运算符
|
||||||
|
'no-const-assign': 2, // 禁止修改使用const声明的变量
|
||||||
|
'no-control-regex': 0, // 禁止正则表达式中的控制字符
|
||||||
|
'no-delete-var': 2, // 禁止删除变量
|
||||||
|
'no-dupe-args': 2, // 在函数定义中禁止重复参数
|
||||||
|
'no-dupe-class-members': 2, // 禁止在类成员中重复名称
|
||||||
|
'no-dupe-keys': 2, // 禁止对象重复声明属性
|
||||||
|
'no-duplicate-case': 2, // 规则禁止重复案例标签
|
||||||
|
'no-empty-character-class': 2, // 禁止在正则表达式中使用空字符类
|
||||||
|
'no-empty-pattern': 2, // 不允许空的解构模式
|
||||||
|
'no-eval': 2, // 禁止使用eval()
|
||||||
|
'no-ex-assign': 2, // 禁止在catch子句中重新分配异常
|
||||||
|
'no-extend-native': 2, // 禁止扩展原生对象
|
||||||
|
'no-extra-bind': 2, // 禁止不必要的功能绑定
|
||||||
|
'no-extra-boolean-cast': 2, // 禁止不必要的布尔类型转换
|
||||||
|
'no-extra-parens': [2, 'functions'], // 禁止不必要的括号
|
||||||
|
'no-fallthrough': 2, // 禁止太多陈述描述
|
||||||
|
'no-floating-decimal': 2, // 禁止浮动小数
|
||||||
|
'no-func-assign': 2, // 禁止重新分配函数声明
|
||||||
|
'no-implied-eval': 2,
|
||||||
|
'no-inner-declarations': [2, 'functions'], // 禁止嵌套块中的变量或函数声明
|
||||||
|
'no-invalid-regexp': 2, // 禁止在RegExp中使用无效的正则表达式字符串
|
||||||
|
'no-irregular-whitespace': 2, // 不允许不规则的空白
|
||||||
|
'no-iterator': 2, // 禁止迭代器
|
||||||
|
'no-label-var': 2, // 禁止变量名称的标签
|
||||||
|
'no-labels': [2, {
|
||||||
|
'allowLoop': false,
|
||||||
|
'allowSwitch': false
|
||||||
|
}],
|
||||||
|
'no-lone-blocks': 2, // 禁止不必要的嵌套块
|
||||||
|
'no-mixed-spaces-and-tabs': 2, // 禁止使用混合空格和制表符进行缩进
|
||||||
|
'no-multi-spaces': 2, // 禁止多个空格
|
||||||
|
'no-multi-str': 2, // 禁止多行字符串
|
||||||
|
'no-multiple-empty-lines': [2, { // 禁止多个空行
|
||||||
|
'max': 1
|
||||||
|
}],
|
||||||
|
'no-native-reassign': 2,
|
||||||
|
'no-negated-in-lhs': 2,
|
||||||
|
'no-new-object': 2,
|
||||||
|
'no-new-require': 2,
|
||||||
|
'no-new-symbol': 2,
|
||||||
|
'no-new-wrappers': 2,
|
||||||
|
'no-obj-calls': 2,
|
||||||
|
'no-octal': 2,
|
||||||
|
'no-octal-escape': 2,
|
||||||
|
'no-path-concat': 2,
|
||||||
|
'no-proto': 2,
|
||||||
|
'no-redeclare': 2,
|
||||||
|
'no-regex-spaces': 2,
|
||||||
|
'no-return-assign': [2, 'except-parens'],
|
||||||
|
'no-self-assign': 2,
|
||||||
|
'no-self-compare': 2,
|
||||||
|
'no-sequences': 2,
|
||||||
|
'no-shadow-restricted-names': 2,
|
||||||
|
'no-spaced-func': 2,
|
||||||
|
'no-sparse-arrays': 2,
|
||||||
|
'no-this-before-super': 2,
|
||||||
|
'no-throw-literal': 2,
|
||||||
|
'no-trailing-spaces': 2,
|
||||||
|
'no-undef': 0,
|
||||||
|
'no-undef-init': 2,
|
||||||
|
'no-unexpected-multiline': 2,
|
||||||
|
'no-unmodified-loop-condition': 2, // 禁止未修改的循环条件
|
||||||
|
'no-unneeded-ternary': [2, { // 当存在更简单的替代方案时,不允许三元运算符
|
||||||
|
'defaultAssignment': false
|
||||||
|
}],
|
||||||
|
'no-unreachable': 2, // 返回,抛出,继续和中断语句后禁止无法访问的代码
|
||||||
|
'no-unsafe-finally': 2, // 禁止finally块中的控制流语句
|
||||||
|
'no-unused-vars': [2, { // 禁止使用未声明的变量
|
||||||
|
'vars': 'all',
|
||||||
|
'args': 'none'
|
||||||
|
}],
|
||||||
|
'no-useless-call': 2, // 禁止不必要的call()和apply()方法
|
||||||
|
'no-useless-computed-key': 2, // 禁止在对象上使用不必要的计算属性键
|
||||||
|
'no-useless-constructor': 2, // 禁止不必要的构造方法
|
||||||
|
'no-useless-escape': 0, // 禁止不必要的转义用法
|
||||||
|
'no-whitespace-before-property': 2, // 在属性之前禁止空格
|
||||||
|
'no-with': 2,
|
||||||
|
'one-var': [2, {
|
||||||
|
'initialized': 'never'
|
||||||
|
}],
|
||||||
|
'operator-linebreak': [2, 'after', { // 为维护强制执行一致的换行方式
|
||||||
|
'overrides': {
|
||||||
|
'?': 'before',
|
||||||
|
':': 'before'
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
'padded-blocks': [2, 'never'], // 在块内要求或禁止填充
|
||||||
|
'quotes': [2, 'single', {
|
||||||
|
'avoidEscape': true,
|
||||||
|
'allowTemplateLiterals': true
|
||||||
|
}],
|
||||||
|
semi: ["error", "always"],
|
||||||
|
'space-before-blocks': [2, 'always'], // 不要存在多余的块空间
|
||||||
|
'space-before-function-paren': [2, 'never'],
|
||||||
|
'space-in-parens': [2, 'never'],
|
||||||
|
'space-infix-ops': 2,
|
||||||
|
'space-unary-ops': [2, {
|
||||||
|
'words': true,
|
||||||
|
'nonwords': false
|
||||||
|
}],
|
||||||
|
'spaced-comment': [2, 'always', {
|
||||||
|
'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
|
||||||
|
}],
|
||||||
|
'template-curly-spacing': [2, 'never'],
|
||||||
|
'use-isnan': 2,
|
||||||
|
'valid-typeof': 2,
|
||||||
|
'wrap-iife': [2, 'any'],
|
||||||
|
'yield-star-spacing': [2, 'both'],
|
||||||
|
'yoda': [2, 'never'],
|
||||||
|
'prefer-const': 1,
|
||||||
|
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
|
||||||
|
'object-curly-spacing': [2, 'always', {
|
||||||
|
objectsInObjects: false
|
||||||
|
}],
|
||||||
|
'array-bracket-spacing': [2, 'never']
|
||||||
|
}
|
||||||
|
}
|
22
smart-admin-h5/.gitignore
vendored
Normal file
22
smart-admin-h5/.gitignore
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
node_modules
|
||||||
|
/dist
|
||||||
|
|
||||||
|
# Log files
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.DS_Store
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
|
||||||
|
package-lock.json
|
||||||
|
yarn.lock
|
||||||
|
|
||||||
|
build/env.js
|
12
smart-admin-h5/.postcssrc.js
Normal file
12
smart-admin-h5/.postcssrc.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// 详情请看 https://github.com/michael-ciniawsky/postcss-load-config
|
||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
autoprefixer: {
|
||||||
|
overrideBrowserslist: ['Android 4.1', 'iOS 7.1', 'Chrome > 31', 'ff > 31', 'ie >= 8']
|
||||||
|
},
|
||||||
|
'postcss-pxtorem': {
|
||||||
|
rootValue: 37.5,
|
||||||
|
propList: ['*'],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
smart-admin-h5/.prettierrc.js
Normal file
31
smart-admin-h5/.prettierrc.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
module.exports = {
|
||||||
|
// 缩进字节数
|
||||||
|
tabWidth: 2,
|
||||||
|
// 使用单引号代替双引号
|
||||||
|
singleQuote: true,
|
||||||
|
// 在对象或数组最后一个元素后面是否加逗号(在ES5中加尾逗号)
|
||||||
|
trailingComma: 'none',
|
||||||
|
// 句尾添加分号
|
||||||
|
semi: true,
|
||||||
|
// 默认值。因为使用了一些折行敏感型的渲染器(如GitHub comment)而按照markdown文本样式进行折行
|
||||||
|
proseWrap: 'always',
|
||||||
|
// (x) => {} 箭头函数参数只有一个时是否要有小括号。avoid:省略括号
|
||||||
|
arrowParens: 'avoid',
|
||||||
|
// 在对象,数组括号与文字之间加空格 "{ foo: bar }"
|
||||||
|
bracketSpacing: true,
|
||||||
|
// 在jsx中把'>' 是否单独放一行
|
||||||
|
jsxBracketSameLine: false,
|
||||||
|
// 缩进不使用tab,使用空格
|
||||||
|
useTabs: false,
|
||||||
|
// 不让prettier使用eslint的代码格式进行校验
|
||||||
|
eslintIntegration: true,
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: '.prettierrc',
|
||||||
|
options: {
|
||||||
|
parser: 'json'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
endOfLine: 'auto'
|
||||||
|
}
|
7
smart-admin-h5/.sentryclirc
Normal file
7
smart-admin-h5/.sentryclirc
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
[defaults]
|
||||||
|
url = https://sentry.1024lab.net/
|
||||||
|
org = 1024lab
|
||||||
|
project = smart-admin-h5
|
||||||
|
|
||||||
|
[auth]
|
||||||
|
token = 8bab45b9152d44b19d4e0a762a93dd34a1318ee8317f46a0a007c48da0e9888e
|
36
smart-admin-h5/README.en.md
Normal file
36
smart-admin-h5/README.en.md
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# ren-min-yi-xue-manage-h5
|
||||||
|
|
||||||
|
#### 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/)
|
39
smart-admin-h5/README.md
Normal file
39
smart-admin-h5/README.md
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# ren-min-yi-xue-manage-h5
|
||||||
|
|
||||||
|
#### 介绍
|
||||||
|
{**以下是 Gitee 平台说明,您可以替换此简介**
|
||||||
|
Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台
|
||||||
|
无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
|
||||||
|
|
||||||
|
#### 软件架构
|
||||||
|
软件架构说明
|
||||||
|
|
||||||
|
|
||||||
|
#### 安装教程
|
||||||
|
|
||||||
|
1. xxxx
|
||||||
|
2. xxxx
|
||||||
|
3. xxxx
|
||||||
|
|
||||||
|
#### 使用说明
|
||||||
|
|
||||||
|
1. xxxx
|
||||||
|
2. xxxx
|
||||||
|
3. xxxx
|
||||||
|
|
||||||
|
#### 参与贡献
|
||||||
|
|
||||||
|
1. Fork 本仓库
|
||||||
|
2. 新建 Feat_xxx 分支
|
||||||
|
3. 提交代码
|
||||||
|
4. 新建 Pull Request
|
||||||
|
|
||||||
|
|
||||||
|
#### 特技
|
||||||
|
|
||||||
|
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
|
||||||
|
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
|
||||||
|
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
|
||||||
|
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
|
||||||
|
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
|
||||||
|
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
16
smart-admin-h5/babel.config.js
Normal file
16
smart-admin-h5/babel.config.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
module.exports = {
|
||||||
|
presets: [['@vue/cli-plugin-babel/preset', {useBuiltIns: 'usage', corejs: 3}]],
|
||||||
|
plugins:[
|
||||||
|
// vant-ui 按需引入,详情:https://github.com/ElementUI/babel-plugin-component
|
||||||
|
// [
|
||||||
|
// 'import',
|
||||||
|
// {
|
||||||
|
// libraryName: 'vant',
|
||||||
|
// libraryDirectory: 'es',
|
||||||
|
// style: true
|
||||||
|
// },
|
||||||
|
// 'vant'
|
||||||
|
// ]
|
||||||
|
]
|
||||||
|
};
|
60
smart-admin-h5/package.json
Normal file
60
smart-admin-h5/package.json
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"name": "smart-admin-h5",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "基于Smart-H5的SmartAdmin的H5端",
|
||||||
|
"author": "zhuoluodada@qq.com",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"local": "vue-cli-service serve --open --mode local",
|
||||||
|
"dev": "vue-cli-service serve --open",
|
||||||
|
"build": "vue-cli-service build",
|
||||||
|
"build:sit": "vue-cli-service build --mode sit",
|
||||||
|
"build:pre": "vue-cli-service build --mode pre",
|
||||||
|
"build:prod": "vue-cli-service build --mode prod",
|
||||||
|
"stage": "vue-cli-service build --mode staging",
|
||||||
|
"lint": "vue-cli-service lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@sentry/browser": "^5.13.2",
|
||||||
|
"@sentry/integrations": "^5.13.2",
|
||||||
|
"axios": "^0.19.2",
|
||||||
|
"core-js": "^3.6.5",
|
||||||
|
"fastclick": "^1.0.6",
|
||||||
|
"js-cookie": "^2.2.1",
|
||||||
|
"lib-flexible": "^0.3.2",
|
||||||
|
"lodash": "^4.17.20",
|
||||||
|
"moment": "^2.29.0",
|
||||||
|
"nprogress": "^0.2.0",
|
||||||
|
"regenerator-runtime": "^0.13.5",
|
||||||
|
"vant": "^2.10.2",
|
||||||
|
"vue": "^2.6.11",
|
||||||
|
"vue-enum": "^1.0.5",
|
||||||
|
"vue-loading-overlay": "^3.4.2",
|
||||||
|
"vue-router": "^3.2.0",
|
||||||
|
"vuex": "^3.4.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@sentry/webpack-plugin": "^1.11.1",
|
||||||
|
"@vue/cli-plugin-babel": "~4.5.0",
|
||||||
|
"@vue/cli-plugin-eslint": "~4.5.0",
|
||||||
|
"@vue/cli-plugin-router": "~4.5.0",
|
||||||
|
"@vue/cli-plugin-vuex": "~4.5.0",
|
||||||
|
"@vue/cli-service": "~4.5.0",
|
||||||
|
"babel-eslint": "^10.1.0",
|
||||||
|
"babel-plugin-import": "^1.13.0",
|
||||||
|
"babel-plugin-transform-remove-console": "^6.9.4",
|
||||||
|
"compression-webpack-plugin": "^3.1.0",
|
||||||
|
"eslint": "^6.7.2",
|
||||||
|
"eslint-plugin-vue": "^6.2.2",
|
||||||
|
"less": "^3.11.2",
|
||||||
|
"less-loader": "^6.1.0",
|
||||||
|
"node-sass": "^4.14.1",
|
||||||
|
"postcss-pxtorem": "^5.1.1",
|
||||||
|
"sass-loader": "^8.0.2",
|
||||||
|
"script-ext-html-webpack-plugin": "^2.1.4",
|
||||||
|
"uglifyjs-webpack-plugin": "^2.2.0",
|
||||||
|
"vconsole": "^3.3.4",
|
||||||
|
"vue-template-compiler": "^2.6.11",
|
||||||
|
"webpack-bundle-analyzer": "^3.8.0"
|
||||||
|
}
|
||||||
|
}
|
BIN
smart-admin-h5/public/favicon.ico
Normal file
BIN
smart-admin-h5/public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
47
smart-admin-h5/public/index.html
Normal file
47
smart-admin-h5/public/index.html
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html
|
||||||
|
env="<%= VUE_APP_ENV %>"
|
||||||
|
version="<%= require('../package.json').version %>"
|
||||||
|
updated="<%= require('moment')().format('YYYY-MM-DD HH:mm:ss') %>"
|
||||||
|
>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport"
|
||||||
|
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover">
|
||||||
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||||
|
|
||||||
|
<!--- cdn begin --->
|
||||||
|
<% if (process.env.NODE_ENV === 'production') { %>
|
||||||
|
<% for(var css of htmlWebpackPlugin.options.cdn.css) { %>
|
||||||
|
<link href="<%=css%>" rel="preload" as="style" />
|
||||||
|
<link rel="stylesheet" href="<%=css%>" as="style" />
|
||||||
|
<% } %> <% for(var js of htmlWebpackPlugin.options.cdn.js) { %>
|
||||||
|
<link href="<%=js%>" rel="preload" as="script" />
|
||||||
|
<script src="<%=js%>"></script>
|
||||||
|
<% } %> <% } %>
|
||||||
|
<!--- cdn end --->
|
||||||
|
|
||||||
|
<!--- vconsole begin --->
|
||||||
|
<% if (process.env.NODE_ENV === 'development') { %>
|
||||||
|
<script src="https://cdn.bootcss.com/vConsole/3.3.4/vconsole.min.js"></script>
|
||||||
|
<% } %>
|
||||||
|
<!--- vconsole end --->
|
||||||
|
|
||||||
|
<script type="text/javascript" src="https://3gimg.qq.com/lightmap/components/geolocation/geolocation.min.js"></script>
|
||||||
|
|
||||||
|
|
||||||
|
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!--- 无脚本提示 --->
|
||||||
|
<noscript>
|
||||||
|
<strong>
|
||||||
|
很抱歉,<%= htmlWebpackPlugin.options.title %> 在没有启用JavaScript的情况下无法正常工作,请联系技术人员,稍后重试!
|
||||||
|
</strong>
|
||||||
|
</noscript>
|
||||||
|
|
||||||
|
<div id="app"></div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
16
smart-admin-h5/src/App.vue
Normal file
16
smart-admin-h5/src/App.vue
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<template>
|
||||||
|
<div id="app">
|
||||||
|
<router-view />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'App'
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="less">
|
||||||
|
#nprogress .bar {
|
||||||
|
background: #1989fa !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
22
smart-admin-h5/src/api/crm-school.js
Normal file
22
smart-admin-h5/src/api/crm-school.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { getAxios, postAxios } from '@/lib/http';
|
||||||
|
|
||||||
|
export const crmSchoolApi = {
|
||||||
|
|
||||||
|
// 分校列表 - 分校 by yandanyang
|
||||||
|
querySchoolList: (data) => {
|
||||||
|
return postAxios('/admin/crm/school/list', data);
|
||||||
|
},
|
||||||
|
// 分校跟进详列表 - 分校 by yandanyang
|
||||||
|
querySchoolTrackList: data => {
|
||||||
|
return postAxios('/admin/crm/school/track/list', data);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 分校跟进 - 分校 by yandanyang
|
||||||
|
addSchoolTrack: data => {
|
||||||
|
return postAxios('/admin/crm/school/track/add', data);
|
||||||
|
},
|
||||||
|
// 分校跟进 - 分校 by yandanyang
|
||||||
|
getSchoolTrackDetail: schoolTrackId => {
|
||||||
|
return getAxios(`/admin/crm/school/track/detail/${schoolTrackId}`);
|
||||||
|
}
|
||||||
|
};
|
43
smart-admin-h5/src/api/employee.js
Normal file
43
smart-admin-h5/src/api/employee.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { postAxios, getAxios } from '@/lib/http';
|
||||||
|
export const employeeApi = {
|
||||||
|
// 员工管理查询
|
||||||
|
getEmployeeList: (data) => {
|
||||||
|
return postAxios('/employee/query', data);
|
||||||
|
},
|
||||||
|
// 添加员工
|
||||||
|
addEmployee: (data) => {
|
||||||
|
return postAxios('/employee/add', data);
|
||||||
|
},
|
||||||
|
// 更新员工信息
|
||||||
|
updateEmployee: (data) => {
|
||||||
|
return postAxios('/employee/update', data);
|
||||||
|
},
|
||||||
|
// 禁用启用单个员工
|
||||||
|
updateStatus: (employeeId, status) => {
|
||||||
|
return getAxios('/employee/updateStatus/' + employeeId + '/' + status);
|
||||||
|
},
|
||||||
|
// 批量禁用
|
||||||
|
updateStatusBatch: (data) => {
|
||||||
|
return postAxios('/employee/batchUpdateStatus', data);
|
||||||
|
},
|
||||||
|
// 单个员工角色授权
|
||||||
|
updateRoles: (data) => {
|
||||||
|
return postAxios('/employee/updateRoles', data);
|
||||||
|
},
|
||||||
|
// 修改密码
|
||||||
|
updatePwd: (data) => {
|
||||||
|
return postAxios('/employee/updatePwd', data);
|
||||||
|
},
|
||||||
|
// 重置密码
|
||||||
|
resetPassword: (employeeId) => {
|
||||||
|
return getAxios('/employee/resetPasswd/' + employeeId);
|
||||||
|
},
|
||||||
|
// 通过部门id获取当前部门的人员&没有部门的人
|
||||||
|
getListEmployeeByDeptId: (departmentId) => {
|
||||||
|
return getAxios('/employee/listEmployeeByDeptId/' + departmentId);
|
||||||
|
},
|
||||||
|
// 删除员工
|
||||||
|
deleteEmployee: (employeeId) => {
|
||||||
|
return postAxios('/employee/delete/' + employeeId);
|
||||||
|
}
|
||||||
|
};
|
14
smart-admin-h5/src/api/file.js
Normal file
14
smart-admin-h5/src/api/file.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { postAxios, getAxios } from '@/lib/http';
|
||||||
|
import config from '@/config';
|
||||||
|
import Cookies from '@/lib/cookie';
|
||||||
|
const baseUrl = config.baseUrl.apiUrl;
|
||||||
|
|
||||||
|
export const fileApi = {
|
||||||
|
// 文件上传
|
||||||
|
fileUpload: (folder, data) => {
|
||||||
|
const url = baseUrl + '/common/file/upload/' + folder + '?x-access-token=' + Cookies.getToken();
|
||||||
|
return postAxios(url, data, {
|
||||||
|
headers: { 'Content-Type': 'multipart/form-data' }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
13
smart-admin-h5/src/api/login.js
Normal file
13
smart-admin-h5/src/api/login.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { getAxios, postAxios } from '@/lib/http';
|
||||||
|
|
||||||
|
export const loginApi = {
|
||||||
|
getVerificationCode: () => {
|
||||||
|
return getAxios('/verificationCode');
|
||||||
|
},
|
||||||
|
login: (data) => {
|
||||||
|
return postAxios('/login', data);
|
||||||
|
},
|
||||||
|
logout: (token) => {
|
||||||
|
return getAxios(`/logout?x-access-token=${token}`);
|
||||||
|
}
|
||||||
|
};
|
31
smart-admin-h5/src/api/system-config.js
Normal file
31
smart-admin-h5/src/api/system-config.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// 系统参数API
|
||||||
|
import {
|
||||||
|
postAxios,
|
||||||
|
getAxios
|
||||||
|
} from '@/lib/http';
|
||||||
|
export const systemConfigApi = {
|
||||||
|
// 查询系统参数列表
|
||||||
|
getSystemConfigList: (data) => {
|
||||||
|
return postAxios('/admin/systemConfig/getListPage', data);
|
||||||
|
},
|
||||||
|
// 添加系统参数
|
||||||
|
addSystemConfig: (data) => {
|
||||||
|
return postAxios('/admin/systemConfig/add', data);
|
||||||
|
},
|
||||||
|
// 更新单条系统参数
|
||||||
|
updateSystemConfig: (data) => {
|
||||||
|
return postAxios('/admin/systemConfig/update', data);
|
||||||
|
},
|
||||||
|
// 通过key获取对应的信息
|
||||||
|
getConfigListByKey: (key) => {
|
||||||
|
return getAxios(`/admin/systemConfig/selectByKey?configKey=${key}`);
|
||||||
|
},
|
||||||
|
// 根据分组查询所有系统配置
|
||||||
|
getListByGroup: (group) => {
|
||||||
|
return getAxios(`/admin/systemConfig/getListByGroup?group=${group}`);
|
||||||
|
},
|
||||||
|
// 获取系统版本信息
|
||||||
|
getCodeVersion: () => {
|
||||||
|
return getAxios('/admin/codeVersion');
|
||||||
|
}
|
||||||
|
};
|
13
smart-admin-h5/src/assets/css/index.scss
Normal file
13
smart-admin-h5/src/assets/css/index.scss
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
@import './variables.scss';
|
||||||
|
@import './mixin.scss';
|
||||||
|
|
||||||
|
html,
|
||||||
|
body .app {
|
||||||
|
color: #333333;
|
||||||
|
font-family: Arial, Helvetica, 'STHeiti STXihei', 'Microsoft YaHei', Tohoma, sans-serif;
|
||||||
|
background-color: $background-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-container {
|
||||||
|
padding-bottom: 50px;
|
||||||
|
}
|
36
smart-admin-h5/src/assets/css/mixin.scss
Normal file
36
smart-admin-h5/src/assets/css/mixin.scss
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// mixin
|
||||||
|
// 清除浮动
|
||||||
|
@mixin clearfix {
|
||||||
|
&:after {
|
||||||
|
content: "";
|
||||||
|
display: table;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 多行隐藏
|
||||||
|
@mixin textoverflow($clamp:1) {
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
-o-text-overflow: ellipsis;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: $clamp;
|
||||||
|
/*! autoprefixer: ignore next */
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
//flex box
|
||||||
|
@mixin flexbox($jc:space-between, $ai:center, $fd:row, $fw:nowrap) {
|
||||||
|
display: flex;
|
||||||
|
display: -webkit-flex;
|
||||||
|
flex: 1;
|
||||||
|
justify-content: $jc;
|
||||||
|
-webkit-justify-content: $jc;
|
||||||
|
align-items: $ai;
|
||||||
|
-webkit-align-items: $ai;
|
||||||
|
flex-direction: $fd;
|
||||||
|
-webkit-flex-direction: $fd;
|
||||||
|
flex-wrap: $fw;
|
||||||
|
-webkit-flex-wrap: $fw;
|
||||||
|
}
|
3
smart-admin-h5/src/assets/css/variables.scss
Normal file
3
smart-admin-h5/src/assets/css/variables.scss
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
// variables
|
||||||
|
$background-color: #f8f8f8;
|
BIN
smart-admin-h5/src/assets/logo.png
Normal file
BIN
smart-admin-h5/src/assets/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.7 KiB |
54
smart-admin-h5/src/components/TabBar.vue
Normal file
54
smart-admin-h5/src/components/TabBar.vue
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<van-tabbar fixed route v-model="active" @change="handleChange">
|
||||||
|
<van-tabbar-item v-for="(item, index) in data" :to="item.to" :icon="item.icon" :key="index">
|
||||||
|
{{ item.title }}
|
||||||
|
</van-tabbar-item>
|
||||||
|
</van-tabbar>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'TabBar',
|
||||||
|
props: {
|
||||||
|
defaultActive: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
active: this.defaultActive
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleChange(value) {
|
||||||
|
this.$emit('change', value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||||
|
<style scoped>
|
||||||
|
h3 {
|
||||||
|
margin: 40px 0 0;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: #42b983;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,120 @@
|
|||||||
|
/**
|
||||||
|
* @description:department-employee-selector
|
||||||
|
* @author: zhuoda
|
||||||
|
*/
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
<div style="padding: 20px">
|
||||||
|
<template v-if="isRadio">
|
||||||
|
<van-radio-group v-model="radioSelectEmployeeId">
|
||||||
|
<van-radio
|
||||||
|
v-for="item in employeeList"
|
||||||
|
:key="item.id"
|
||||||
|
:name="item.id"
|
||||||
|
style="margin-top: 5px"
|
||||||
|
@click="clickRadio"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
item.actualName
|
||||||
|
}}
|
||||||
|
</van-radio>
|
||||||
|
</van-radio-group>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-if="!isRadio">
|
||||||
|
<van-checkbox-group ref="checkboxGroup" :max="max" v-model="selectEmployeeList">
|
||||||
|
<van-checkbox
|
||||||
|
:key="item.id"
|
||||||
|
:name="item.id"
|
||||||
|
v-model="item._checked"
|
||||||
|
v-for="item in employeeList"
|
||||||
|
style="margin-top: 5px">
|
||||||
|
{{
|
||||||
|
item.actualName
|
||||||
|
}}
|
||||||
|
</van-checkbox>
|
||||||
|
</van-checkbox-group>
|
||||||
|
</template>
|
||||||
|
<br>
|
||||||
|
<van-button v-if="!isRadio" type="primary" size="small" @click="checkAll" style="margin:0 10px">全选</van-button>
|
||||||
|
<van-button v-if="!isRadio" type="info" size="small" @click="toggleAll">反选</van-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { systemConfigApi } from '@/api/system-config';
|
||||||
|
import { employeeApi } from 'api/employee';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'DepartmentEmployeeSelector',
|
||||||
|
props: {
|
||||||
|
// 最大数
|
||||||
|
max: Number,
|
||||||
|
isRadio: Boolean
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
selectEmployeeList: [],
|
||||||
|
employeeList: [],
|
||||||
|
radioSelectEmployeeId: null,
|
||||||
|
radioSelectEmployeeName: null
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.loadEmployeeList();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
updateRadioSelectEmployeeId(employeeId) {
|
||||||
|
this.radioSelectEmployeeId = employeeId;
|
||||||
|
},
|
||||||
|
clickRadio(e, val) {
|
||||||
|
this.radioSelectEmployeeName = e.target.innerText;
|
||||||
|
},
|
||||||
|
getSelected() {
|
||||||
|
if (this.isRadio) {
|
||||||
|
return [{
|
||||||
|
id: this.radioSelectEmployeeId,
|
||||||
|
actualName: this.radioSelectEmployeeName
|
||||||
|
}];
|
||||||
|
} else {
|
||||||
|
const result = [];
|
||||||
|
for (const employee of this.employeeList) {
|
||||||
|
if (this.selectEmployeeList.indexOf(employee.id) > -1) {
|
||||||
|
result.push(Object.assign({}, employee));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async loadEmployeeList() {
|
||||||
|
this.$smart.loading();
|
||||||
|
try {
|
||||||
|
const departmentIdResult = await systemConfigApi.getConfigListByKey('crm_school_share_department_id');
|
||||||
|
const employeeListResult = await employeeApi.getListEmployeeByDeptId(departmentIdResult.data.configValue);
|
||||||
|
this.employeeList = employeeListResult.data.filter(e => e.isDelete === 0 && e.isDisabled === 0).map(e => {
|
||||||
|
e._checked = false;
|
||||||
|
return e;
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
this.$smartSentry.captureException(e);
|
||||||
|
} finally {
|
||||||
|
this.$smart.loadingClear();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
checkAll() {
|
||||||
|
this.$refs.checkboxGroup.toggleAll(true);
|
||||||
|
},
|
||||||
|
toggleAll() {
|
||||||
|
this.$refs.checkboxGroup.toggleAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -0,0 +1,61 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<van-field
|
||||||
|
v-model="result"
|
||||||
|
v-bind="$attrs"
|
||||||
|
readonly
|
||||||
|
is-link
|
||||||
|
@click="show = !show"
|
||||||
|
/>
|
||||||
|
<van-popup v-model="show" position="bottom">
|
||||||
|
<van-picker
|
||||||
|
value-key="desc"
|
||||||
|
:columns="columns"
|
||||||
|
show-toolbar
|
||||||
|
:title="$attrs.label"
|
||||||
|
@cancel="show = !show"
|
||||||
|
@confirm="onConfirm"
|
||||||
|
/>
|
||||||
|
</van-popup>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'SmartEnumSelectPicker',
|
||||||
|
model: {
|
||||||
|
prop: 'selectValue'
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
enumName: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
selectValue: {
|
||||||
|
type: String
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
show: false,
|
||||||
|
result: this.selectValue,
|
||||||
|
columns: this.$enum.getValueDescList(this.enumName)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onConfirm(value) {
|
||||||
|
this.result = value.desc;
|
||||||
|
this.show = !this.show;
|
||||||
|
this.$emit('change', value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
selectValue: function(newVal) {
|
||||||
|
this.result = newVal;
|
||||||
|
},
|
||||||
|
result(newVal) {
|
||||||
|
this.$emit('input', newVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style></style>
|
@ -0,0 +1,59 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<van-field
|
||||||
|
v-model="result"
|
||||||
|
v-bind="$attrs"
|
||||||
|
readonly
|
||||||
|
is-link
|
||||||
|
@click="show = !show"
|
||||||
|
/>
|
||||||
|
<van-popup v-model="show" position="bottom">
|
||||||
|
<van-picker
|
||||||
|
value-key="value"
|
||||||
|
:columns="columns"
|
||||||
|
show-toolbar
|
||||||
|
:title="$attrs.label"
|
||||||
|
@cancel="show = !show"
|
||||||
|
@confirm="onConfirm"
|
||||||
|
/>
|
||||||
|
</van-popup>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
model: {
|
||||||
|
prop: 'selectValue'
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
columns: {
|
||||||
|
type: Array
|
||||||
|
},
|
||||||
|
selectValue: {
|
||||||
|
type: String
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
show: false,
|
||||||
|
result: this.selectValue
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onConfirm(value) {
|
||||||
|
this.result = value;
|
||||||
|
this.show = !this.show;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
selectValue: function(newVal) {
|
||||||
|
this.result = newVal;
|
||||||
|
},
|
||||||
|
result(newVal) {
|
||||||
|
this.$emit('input', newVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style></style>
|
24
smart-admin-h5/src/components/van-bar/BackNavBar.vue
Normal file
24
smart-admin-h5/src/components/van-bar/BackNavBar.vue
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<template>
|
||||||
|
|
||||||
|
<van-nav-bar :title="title" left-text="返回" left-arrow @click-left="onClickLeft" />
|
||||||
|
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'BackNavBar',
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onClickLeft() {
|
||||||
|
this.$router.go(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
27
smart-admin-h5/src/components/van-bar/RouterNavBar.vue
Normal file
27
smart-admin-h5/src/components/van-bar/RouterNavBar.vue
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<template>
|
||||||
|
|
||||||
|
<van-nav-bar :title="title" left-text="返回" left-arrow @click-left="onClickLeft" />
|
||||||
|
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'RouterNavBar',
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
path: {
|
||||||
|
type: String
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onClickLeft() {
|
||||||
|
this.$router.push(this.path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
44
smart-admin-h5/src/config/index.js
Normal file
44
smart-admin-h5/src/config/index.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
console.log('project api url : ', process.env.VUE_APP_URL);
|
||||||
|
|
||||||
|
const isProductionEnv = ['production'].includes(process.env.NODE_ENV);
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// 配置显示在浏览器标签的title
|
||||||
|
title: 'Smart-Admin-H5',
|
||||||
|
// token在Cookie中存储的天数,默认7天
|
||||||
|
cookieExpires: 7,
|
||||||
|
/**
|
||||||
|
* @description api请求基础路径
|
||||||
|
*/
|
||||||
|
baseUrl: {
|
||||||
|
apiUrl: process.env.VUE_APP_URL,
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 打包后静态资源地址;如果是走cdn的话,可以配置如下:
|
||||||
|
* publicPath: isProd ? 'https://cdn.1024lab.net/static/smart-h5/' : '/'
|
||||||
|
*/
|
||||||
|
publicPath: isProductionEnv ? '/smart-admin-h5/' : '/',
|
||||||
|
|
||||||
|
// ==================== cdn 相关 begin ====================
|
||||||
|
cdn: {
|
||||||
|
cdnResource: {
|
||||||
|
css: [],
|
||||||
|
js: [
|
||||||
|
'https://cdn.bootcss.com/vue/2.6.11/vue.min.js',
|
||||||
|
'https://cdn.bootcss.com/vue-router/3.2.0/vue-router.min.js',
|
||||||
|
'https://cdn.bootcdn.net/ajax/libs/vuex/3.5.1/vuex.min.js',
|
||||||
|
'https://cdn.bootcss.com/axios/0.19.2/axios.min.js',
|
||||||
|
'https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.20/lodash.min.js'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// 指定资源加载cdn
|
||||||
|
externals: {
|
||||||
|
vue: 'Vue',
|
||||||
|
'vue-router': 'VueRouter',
|
||||||
|
vuex: 'Vuex',
|
||||||
|
axios: 'axios',
|
||||||
|
lodash: '_'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ==================== cdn 相关 end ====================
|
||||||
|
};
|
4047
smart-admin-h5/src/constants/area.js
Normal file
4047
smart-admin-h5/src/constants/area.js
Normal file
File diff suppressed because it is too large
Load Diff
92
smart-admin-h5/src/constants/file.js
Normal file
92
smart-admin-h5/src/constants/file.js
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
export const COMMON_FILE_FOLDER_TYPE_ENUM = {
|
||||||
|
DISPLAY_PIC: {
|
||||||
|
value: 1,
|
||||||
|
desc: '轮播展示图'
|
||||||
|
},
|
||||||
|
RESOURCE_LECTURER: {
|
||||||
|
value: 2,
|
||||||
|
desc: '资源-讲师图片'
|
||||||
|
},
|
||||||
|
RESOURCE_FILE: {
|
||||||
|
value: 3,
|
||||||
|
desc: '资源-文件资源'
|
||||||
|
},
|
||||||
|
USER_AVATAR: {
|
||||||
|
value: 4,
|
||||||
|
desc: '用户头像'
|
||||||
|
},
|
||||||
|
STOCK_BASIC: {
|
||||||
|
value: 5,
|
||||||
|
desc: '货物基本信息图片'
|
||||||
|
},
|
||||||
|
PUBLICATION_QR_CODE: {
|
||||||
|
value: 6,
|
||||||
|
desc: '出版物二维码图片'
|
||||||
|
},
|
||||||
|
RESOURCE_PAGE_QR_CODE: {
|
||||||
|
value: 7,
|
||||||
|
desc: '资源页面链接二维码图片'
|
||||||
|
},
|
||||||
|
FINANCE_RECEIVE_QR_CODE: {
|
||||||
|
value: 8,
|
||||||
|
desc: '财务收款二维码'
|
||||||
|
},
|
||||||
|
FINANCE_WX_PAY_CERT: {
|
||||||
|
value: 9,
|
||||||
|
desc: '财务-微信支付证书'
|
||||||
|
},
|
||||||
|
GOODS: {
|
||||||
|
value: 10,
|
||||||
|
desc: '商品图片-公用文件夹'
|
||||||
|
},
|
||||||
|
EXCEL_EXPORT: {
|
||||||
|
value: 11,
|
||||||
|
desc: 'excel导出-私有文件夹'
|
||||||
|
},
|
||||||
|
FINANCE_WAIT_PAYMENT_PAYMENT_PROOF: {
|
||||||
|
value: 12,
|
||||||
|
desc: '财务待支付支付凭证'
|
||||||
|
},
|
||||||
|
FEEDBACK: {
|
||||||
|
value: 99,
|
||||||
|
desc: '用户反馈图片'
|
||||||
|
},
|
||||||
|
EDITOR: {
|
||||||
|
value: 100,
|
||||||
|
desc: '文本编辑器'
|
||||||
|
},
|
||||||
|
EDITOR_IMG: {
|
||||||
|
value: 100,
|
||||||
|
desc: '文本编辑器'
|
||||||
|
},
|
||||||
|
INTERNAL_INFORMATION: {
|
||||||
|
value: 14,
|
||||||
|
desc: '内部资料'
|
||||||
|
},
|
||||||
|
CRM_USER: {
|
||||||
|
value: 111,
|
||||||
|
desc: 'CRM学员跟进附件'
|
||||||
|
},
|
||||||
|
CRM_SCHOOL: {
|
||||||
|
value: 112,
|
||||||
|
desc: 'CRM分校跟进附件'
|
||||||
|
},
|
||||||
|
// = =======erp 相关 begin============
|
||||||
|
ERP_STOCK_IMG: {
|
||||||
|
value: 201,
|
||||||
|
desc: '货物图片'
|
||||||
|
},
|
||||||
|
ERP_CONTACT_COMPANY_RECEIVE_IMAGE: {
|
||||||
|
value: 210,
|
||||||
|
desc: '往来单位收款二维码'
|
||||||
|
},
|
||||||
|
ERP_CONTACT_COMPANY_ATTACHMENT: {
|
||||||
|
value: 211,
|
||||||
|
desc: '往来单位附件'
|
||||||
|
}
|
||||||
|
// = =======erp 相关 end ============
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
COMMON_FILE_FOLDER_TYPE_ENUM
|
||||||
|
};
|
5
smart-admin-h5/src/constants/index.js
Normal file
5
smart-admin-h5/src/constants/index.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import file from './file';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
...file,
|
||||||
|
};
|
298
smart-admin-h5/src/filters/filter.js
Normal file
298
smart-admin-h5/src/filters/filter.js
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
import Vue from 'vue';
|
||||||
|
|
||||||
|
function ellipsis(value, length) {
|
||||||
|
if (!value) return '';
|
||||||
|
if (value.length > length) {
|
||||||
|
return value.slice(0, length) + '...';
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 去除空格 type 1-所有空格 2-前后空格 3-前空格 4-后空格
|
||||||
|
*/
|
||||||
|
function trim(value, trim) {
|
||||||
|
switch (trim) {
|
||||||
|
case 1:
|
||||||
|
return value.replace(/\s+/g, '');
|
||||||
|
case 2:
|
||||||
|
return value.replace(/(^\s*)|(\s*$)/g, '');
|
||||||
|
case 3:
|
||||||
|
return value.replace(/(^\s*)/g, '');
|
||||||
|
case 4:
|
||||||
|
return value.replace(/(\s*$)/g, '');
|
||||||
|
default:
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任意格式日期处理
|
||||||
|
使用格式:
|
||||||
|
{{ '2018-09-14 01:05' | formatDate(yyyy-MM-dd hh:mm:ss) }}
|
||||||
|
{{ '2018-09-14 01:05' | formatDate(yyyy-MM-dd) }}
|
||||||
|
{{ '2018-09-14 01:05' | formatDate(MM/dd) }} 等
|
||||||
|
|
||||||
|
* @param value
|
||||||
|
* @param fmt
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
function formatDate(value, fmt) {
|
||||||
|
var date = new Date(value);
|
||||||
|
var o = {
|
||||||
|
'M+': date.getMonth() + 1, // 月份
|
||||||
|
'd+': date.getDate(), // 日
|
||||||
|
'h+': date.getHours(), // 小时
|
||||||
|
'm+': date.getMinutes(), // 分
|
||||||
|
's+': date.getSeconds(), // 秒
|
||||||
|
'w+': date.getDay(), // 星期
|
||||||
|
'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
|
||||||
|
'S': date.getMilliseconds() // 毫秒
|
||||||
|
};
|
||||||
|
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
|
||||||
|
for (var k in o) {
|
||||||
|
if (k === 'w+') {
|
||||||
|
if (o[k] === 0) {
|
||||||
|
fmt = fmt.replace('w', '周日');
|
||||||
|
} else if (o[k] === 1) {
|
||||||
|
fmt = fmt.replace('w', '周一');
|
||||||
|
} else if (o[k] === 2) {
|
||||||
|
fmt = fmt.replace('w', '周二');
|
||||||
|
} else if (o[k] === 3) {
|
||||||
|
fmt = fmt.replace('w', '周三');
|
||||||
|
} else if (o[k] === 4) {
|
||||||
|
fmt = fmt.replace('w', '周四');
|
||||||
|
} else if (o[k] === 5) {
|
||||||
|
fmt = fmt.replace('w', '周五');
|
||||||
|
} else if (o[k] === 6) {
|
||||||
|
fmt = fmt.replace('w', '周六');
|
||||||
|
}
|
||||||
|
} else if (new RegExp('(' + k + ')').test(fmt)) {
|
||||||
|
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字母大小写切换
|
||||||
|
type
|
||||||
|
1:首字母大写
|
||||||
|
2:首页母小写
|
||||||
|
3:大小写转换
|
||||||
|
4:全部大写
|
||||||
|
5:全部小写
|
||||||
|
* @param str
|
||||||
|
* @param type
|
||||||
|
* @returns {string|*}
|
||||||
|
*/
|
||||||
|
function changeCase(str, type) {
|
||||||
|
function ToggleCase(str) {
|
||||||
|
var itemText = '';
|
||||||
|
str.split('').forEach(
|
||||||
|
function(item) {
|
||||||
|
if (/^([a-z]+)/.test(item)) {
|
||||||
|
itemText += item.toUpperCase();
|
||||||
|
} else if (/^([A-Z]+)/.test(item)) {
|
||||||
|
itemText += item.toLowerCase();
|
||||||
|
} else {
|
||||||
|
itemText += item;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return itemText;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 1:
|
||||||
|
return str.replace(/\b\w+\b/g, function(word) {
|
||||||
|
return word.substring(0, 1).toUpperCase() + word.substring(1).toLowerCase();
|
||||||
|
});
|
||||||
|
case 2:
|
||||||
|
return str.replace(/\b\w+\b/g, function(word) {
|
||||||
|
return word.substring(0, 1).toLowerCase() + word.substring(1).toUpperCase();
|
||||||
|
});
|
||||||
|
case 3:
|
||||||
|
return ToggleCase(str);
|
||||||
|
case 4:
|
||||||
|
return str.toUpperCase();
|
||||||
|
case 5:
|
||||||
|
return str.toLowerCase();
|
||||||
|
default:
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符串循环复制,count->次数
|
||||||
|
*/
|
||||||
|
function repeatStr(str, count) {
|
||||||
|
var text = '';
|
||||||
|
for (var i = 0; i < count; i++) {
|
||||||
|
text += str;
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符串替换
|
||||||
|
*/
|
||||||
|
function replaceAll(str, AFindText, ARepText) {
|
||||||
|
const raRegExp = new RegExp(AFindText, 'g');
|
||||||
|
return str.replace(raRegExp, ARepText);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 字符替换*,隐藏手机号或者身份证号等
|
||||||
|
replaceStr(字符串,字符格式, 替换方式,替换的字符(默认*))
|
||||||
|
ecDo.replaceStr('18819322663',[3,5,3],0)
|
||||||
|
result:188*****663
|
||||||
|
ecDo.replaceStr('asdasdasdaa',[3,5,3],1)
|
||||||
|
result:***asdas***
|
||||||
|
ecDo.replaceStr('1asd88465asdwqe3',[5],0)
|
||||||
|
result:*****8465asdwqe3
|
||||||
|
ecDo.replaceStr('1asd88465asdwqe3',[5],1,'+')
|
||||||
|
result:"1asd88465as+++++"
|
||||||
|
*
|
||||||
|
* @param str
|
||||||
|
* @param regArr
|
||||||
|
* @param type
|
||||||
|
* @param ARepText
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
function replaceStr(str, regArr, type, ARepText) {
|
||||||
|
var regtext = '';
|
||||||
|
var Reg = null;
|
||||||
|
var replaceText = ARepText || '*';
|
||||||
|
// repeatStr是在上面定义过的(字符串循环复制),大家注意哦
|
||||||
|
if (regArr.length === 3 && type === 0) {
|
||||||
|
regtext = '(\\w{' + regArr[0] + '})\\w{' + regArr[1] + '}(\\w{' + regArr[2] + '})';
|
||||||
|
Reg = new RegExp(regtext);
|
||||||
|
var replaceCount = this.repeatStr(replaceText, regArr[1]);
|
||||||
|
return str.replace(Reg, '$1' + replaceCount + '$2');
|
||||||
|
} else if (regArr.length === 3 && type === 1) {
|
||||||
|
regtext = '\\w{' + regArr[0] + '}(\\w{' + regArr[1] + '})\\w{' + regArr[2] + '}';
|
||||||
|
Reg = new RegExp(regtext);
|
||||||
|
var replaceCount1 = this.repeatStr(replaceText, regArr[0]);
|
||||||
|
var replaceCount2 = this.repeatStr(replaceText, regArr[2]);
|
||||||
|
return str.replace(Reg, replaceCount1 + '$1' + replaceCount2);
|
||||||
|
} else if (regArr.length === 1 && type === 0) {
|
||||||
|
regtext = '(^\\w{' + regArr[0] + '})';
|
||||||
|
Reg = new RegExp(regtext);
|
||||||
|
var replaceCount = this.repeatStr(replaceText, regArr[0]);
|
||||||
|
return str.replace(Reg, replaceCount);
|
||||||
|
} else if (regArr.length === 1 && type === 1) {
|
||||||
|
regtext = '(\\w{' + regArr[0] + '}$)';
|
||||||
|
Reg = new RegExp(regtext);
|
||||||
|
var replaceCount = this.repeatStr(replaceText, regArr[0]);
|
||||||
|
return str.replace(Reg, replaceCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化处理字符串
|
||||||
|
ecDo.formatText('1234asda567asd890')
|
||||||
|
result:"12,34a,sda,567,asd,890"
|
||||||
|
ecDo.formatText('1234asda567asd890',4,' ')
|
||||||
|
result:"1 234a sda5 67as d890"
|
||||||
|
ecDo.formatText('1234asda567asd890',4,'-')
|
||||||
|
result:"1-234a-sda5-67as-d890"
|
||||||
|
|
||||||
|
* @param str
|
||||||
|
* @param size
|
||||||
|
* @param delimiter
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
function formatText(str, size, delimiter) {
|
||||||
|
var _size = size || 3;
|
||||||
|
var _delimiter = delimiter || ',';
|
||||||
|
var regText = '\\B(?=(\\w{' + _size + '})+(?!\\w))';
|
||||||
|
var reg = new RegExp(regText, 'g');
|
||||||
|
return str.replace(reg, _delimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 现金额大写转换函数
|
||||||
|
ecDo.upDigit(168752632)
|
||||||
|
result:"人民币壹亿陆仟捌佰柒拾伍万贰仟陆佰叁拾贰元整"
|
||||||
|
ecDo.upDigit(1682)
|
||||||
|
result:"人民币壹仟陆佰捌拾贰元整"
|
||||||
|
ecDo.upDigit(-1693)
|
||||||
|
result:"欠人民币壹仟陆佰玖拾叁元整"
|
||||||
|
* @param n
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function upDigit(n) {
|
||||||
|
var fraction = ['角', '分', '厘'];
|
||||||
|
var digit = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
|
||||||
|
var unit = [
|
||||||
|
['元', '万', '亿'],
|
||||||
|
['', '拾', '佰', '仟']
|
||||||
|
];
|
||||||
|
var head = n < 0 ? '欠人民币' : '人民币';
|
||||||
|
n = Math.abs(n);
|
||||||
|
var s = '';
|
||||||
|
for (var i = 0; i < fraction.length; i++) {
|
||||||
|
s += (digit[Math.floor(n * 10 * Math.pow(10, i)) % 10] + fraction[i]).replace(/零./, '');
|
||||||
|
}
|
||||||
|
s = s || '整';
|
||||||
|
n = Math.floor(n);
|
||||||
|
for (var i = 0; i < unit[0].length && n > 0; i++) {
|
||||||
|
var p = '';
|
||||||
|
for (var j = 0; j < unit[1].length && n > 0; j++) {
|
||||||
|
p = digit[n % 10] + unit[1][j] + p;
|
||||||
|
n = Math.floor(n / 10);
|
||||||
|
}
|
||||||
|
s = p.replace(/(零.)*零$/, '').replace(/^$/, '零') + unit[0][i] + s;
|
||||||
|
// s = p + unit[0][i] + s;
|
||||||
|
}
|
||||||
|
return head + s.replace(/(零.)*零元/, '元').replace(/(零.)+/g, '零').replace(/^整$/, '零元整');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保留2位小数
|
||||||
|
function toFixed(val, acc) {
|
||||||
|
let num = parseFloat(val);
|
||||||
|
if (isNaN(num)) {
|
||||||
|
num = 0;
|
||||||
|
}
|
||||||
|
let accuracy = parseInt(acc);
|
||||||
|
if (isNaN(accuracy) || accuracy < 0 || accuracy > 10) {
|
||||||
|
accuracy = 2;
|
||||||
|
}
|
||||||
|
return num.toFixed(accuracy);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转百分比
|
||||||
|
function toPercent(val, acc) {
|
||||||
|
let num = parseFloat(val);
|
||||||
|
if (isNaN(num)) {
|
||||||
|
num = 0;
|
||||||
|
}
|
||||||
|
let accuracy = parseInt(acc);
|
||||||
|
if (isNaN(accuracy) || accuracy < 0 || accuracy > 10) {
|
||||||
|
accuracy = 2;
|
||||||
|
}
|
||||||
|
return (num * 100).toFixed(accuracy) + '%';
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------ enum begin ------------
|
||||||
|
function getEnumDescByValue(value, enumName) {
|
||||||
|
return Vue.prototype.$enum.getDescByValue(enumName, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------ enum end ------------
|
||||||
|
|
||||||
|
export {
|
||||||
|
trim,
|
||||||
|
changeCase,
|
||||||
|
repeatStr,
|
||||||
|
replaceAll,
|
||||||
|
replaceStr,
|
||||||
|
formatText,
|
||||||
|
upDigit,
|
||||||
|
toFixed,
|
||||||
|
formatDate,
|
||||||
|
toPercent,
|
||||||
|
getEnumDescByValue,
|
||||||
|
ellipsis
|
||||||
|
};
|
5
smart-admin-h5/src/filters/index.js
Normal file
5
smart-admin-h5/src/filters/index.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
|
||||||
|
import * as filter from './filter'
|
||||||
|
|
||||||
|
Object.keys(filter).forEach(key => Vue.filter(key, filter[key]))
|
21
smart-admin-h5/src/lib/cookie.js
Normal file
21
smart-admin-h5/src/lib/cookie.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import Cookies from 'js-cookie';
|
||||||
|
import config from '@/config';
|
||||||
|
const { cookieExpires } = config;
|
||||||
|
export const TOKEN_KEY = 'token';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setToken: token => {
|
||||||
|
Cookies.set(TOKEN_KEY, token, {
|
||||||
|
// token在Cookie中存储的天数,默认1天
|
||||||
|
expires: cookieExpires || 7
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getToken: () => {
|
||||||
|
const token = Cookies.get(TOKEN_KEY);
|
||||||
|
if (token) return token;
|
||||||
|
else return null;
|
||||||
|
},
|
||||||
|
clearToken: () => {
|
||||||
|
Cookies.remove(TOKEN_KEY);
|
||||||
|
}
|
||||||
|
};
|
65
smart-admin-h5/src/lib/http.js
Normal file
65
smart-admin-h5/src/lib/http.js
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import Axios from 'axios';
|
||||||
|
import config from '@/config';
|
||||||
|
import cookie from '@/lib/cookie';
|
||||||
|
import { Toast } from 'vant';
|
||||||
|
|
||||||
|
export const baseUrl = config.baseUrl.apiUrl;
|
||||||
|
|
||||||
|
const axios = Axios.create({
|
||||||
|
baseURL: baseUrl,
|
||||||
|
timeout: 30000,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json; charset=utf-8'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加请求拦截器
|
||||||
|
axios.interceptors.request.use(
|
||||||
|
function(config) {
|
||||||
|
const token = cookie.getToken();
|
||||||
|
if (token) {
|
||||||
|
config.headers['x-access-token'] = token;
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
function(error) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// 添加响应拦截器
|
||||||
|
axios.interceptors.response.use(
|
||||||
|
res => {
|
||||||
|
const { data } = res;
|
||||||
|
if (data && data.code && data.code !== 1) {
|
||||||
|
if (data.code === 1001) {
|
||||||
|
cookie.clearToken();
|
||||||
|
localStorage.clear();
|
||||||
|
window.location.href = window.location.pathname + '#/login';
|
||||||
|
Toast.fail('未登录,或登录失效,请登录');
|
||||||
|
return;
|
||||||
|
} else if (data.code === 502) {
|
||||||
|
window.location.href = window.location.pathname + '#/500';
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
Toast.fail(data.msg);
|
||||||
|
return Promise.reject(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Promise.resolve(data);
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
Toast.fail('服务内部错误');
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export const postAxios = (url, data, config) => {
|
||||||
|
return axios.post(url, data, config);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getAxios = (url, data) => {
|
||||||
|
return axios.get(url, {
|
||||||
|
params: data
|
||||||
|
});
|
||||||
|
};
|
8
smart-admin-h5/src/lib/local.js
Normal file
8
smart-admin-h5/src/lib/local.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export const localSave = (key, value) => {
|
||||||
|
localStorage.setItem(key, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const localRead = key => {
|
||||||
|
return localStorage.getItem(key) || '';
|
||||||
|
};
|
||||||
|
|
276
smart-admin-h5/src/lib/menu-func.js
Normal file
276
smart-admin-h5/src/lib/menu-func.js
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
import { forEach, hasOneOf, objEqual } from '@/lib/util';
|
||||||
|
import config from '@/config';
|
||||||
|
import { localRead, localSave } from '@/lib/local';
|
||||||
|
const { title, useI18n } = config;
|
||||||
|
export const hasChild = item => {
|
||||||
|
return item.children && item.children.length !== 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过权限过滤菜单
|
||||||
|
* @param {Object} map 权限对象
|
||||||
|
* @param {Array} menuList 菜单列表
|
||||||
|
* @returns {Array}
|
||||||
|
*/
|
||||||
|
export const getShowMenu = (map = {}, menuList, access = false) => {
|
||||||
|
// 判断是否为超级管理员
|
||||||
|
if (access) {
|
||||||
|
return menuList;
|
||||||
|
}
|
||||||
|
// 返回的菜单列表
|
||||||
|
let result = [];
|
||||||
|
for (let menuItem of menuList) {
|
||||||
|
let routerObj = JSON.parse(JSON.stringify(menuItem));
|
||||||
|
if (
|
||||||
|
map.hasOwnProperty(menuItem.name) &&
|
||||||
|
(menuItem.name !== 'home' && menuItem.name !== '_home')
|
||||||
|
) {
|
||||||
|
// 判断该菜单权限下是否为数组,若为数组,则为功能点权限否则为子菜单
|
||||||
|
if (getType(map[routerObj.name]) === 'array') {
|
||||||
|
let funcPrivilege = localRead('funcPrivilegeInfo')
|
||||||
|
? JSON.parse(localRead('funcPrivilegeInfo'))
|
||||||
|
: {};
|
||||||
|
localSave(
|
||||||
|
'funcPrivilegeInfo',
|
||||||
|
JSON.stringify({
|
||||||
|
...funcPrivilege,
|
||||||
|
[routerObj.name]: map[routerObj.name]
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} else if (
|
||||||
|
getType(map[routerObj.name]) !== 'array' &&
|
||||||
|
!routerObj.children
|
||||||
|
) {
|
||||||
|
// 判断是否为二级菜单,若是则需要多枚举一层赋值
|
||||||
|
let funcPrivilege = localRead('funcPrivilegeInfo')
|
||||||
|
? JSON.parse(localRead('funcPrivilegeInfo'))
|
||||||
|
: {};
|
||||||
|
localSave(
|
||||||
|
'funcPrivilegeInfo',
|
||||||
|
JSON.stringify({
|
||||||
|
...funcPrivilege,
|
||||||
|
[routerObj.name]: map[routerObj.name][routerObj.name]
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} else if (
|
||||||
|
getType(map[routerObj.name]) !== 'array' &&
|
||||||
|
routerObj.children
|
||||||
|
) {
|
||||||
|
// 循环子菜单权限
|
||||||
|
routerObj.children = getShowMenu(
|
||||||
|
map[routerObj.name],
|
||||||
|
routerObj.children
|
||||||
|
);
|
||||||
|
}
|
||||||
|
result.push(routerObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
// 获取数据类型
|
||||||
|
export const getType = obj => {
|
||||||
|
return {}.toString
|
||||||
|
.call(obj)
|
||||||
|
.match(/\s([a-zA-Z]+)/)[1]
|
||||||
|
.toLowerCase();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 本地存储和获取标签导航列表
|
||||||
|
*/
|
||||||
|
export const setTagNavListInLocalStorage = list => {
|
||||||
|
localStorage.tagNaveList = JSON.stringify(list);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* @returns {Array} 其中的每个元素只包含路由原信息中的name, path, meta三项
|
||||||
|
*/
|
||||||
|
export const getTagNavListFromLocalStorage = () => {
|
||||||
|
const list = localStorage.tagNaveList;
|
||||||
|
return list ? JSON.parse(list) : [];
|
||||||
|
};
|
||||||
|
export const getBreadCrumbList = (route, homeRoute) => {
|
||||||
|
let homeItem = {
|
||||||
|
...homeRoute,
|
||||||
|
icon: homeRoute.meta.icon
|
||||||
|
};
|
||||||
|
let routeMatched = route.matched;
|
||||||
|
if (routeMatched.some(item => item.name === homeRoute.name)) {
|
||||||
|
return [homeItem];
|
||||||
|
}
|
||||||
|
let res = routeMatched
|
||||||
|
.filter(item => {
|
||||||
|
return item.meta === undefined || !item.meta.hideInBread;
|
||||||
|
})
|
||||||
|
.map(item => {
|
||||||
|
let meta = {
|
||||||
|
...item.meta
|
||||||
|
};
|
||||||
|
if (meta.title && typeof meta.title === 'function') {
|
||||||
|
meta.__titleIsFunction__ = true;
|
||||||
|
meta.title = meta.title(route);
|
||||||
|
}
|
||||||
|
let obj = {
|
||||||
|
icon: (item.meta && item.meta.icon) || '',
|
||||||
|
name: item.name,
|
||||||
|
meta: meta
|
||||||
|
};
|
||||||
|
return obj;
|
||||||
|
});
|
||||||
|
res = res.filter(item => {
|
||||||
|
return !item.meta.hideInMenu;
|
||||||
|
});
|
||||||
|
return [...res];
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* @param {Array} routers 路由列表数组
|
||||||
|
* @description 用于找到路由列表中name为home的对象
|
||||||
|
*/
|
||||||
|
export const getHomeRoute = (routers, homeName = 'Home') => {
|
||||||
|
let i = -1;
|
||||||
|
let len = routers.length;
|
||||||
|
let homeRoute = {};
|
||||||
|
while (++i < len) {
|
||||||
|
let item = routers[i];
|
||||||
|
if (item.children && item.children.length) {
|
||||||
|
let res = getHomeRoute(item.children, homeName);
|
||||||
|
if (res.name) return res;
|
||||||
|
} else {
|
||||||
|
if (item.name === homeName) homeRoute = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return homeRoute;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* @param {Array} list 标签列表
|
||||||
|
* @param {String} name 当前关闭的标签的name
|
||||||
|
*/
|
||||||
|
export const getNextRoute = (list, route) => {
|
||||||
|
let res = {};
|
||||||
|
if (list.length === 2) {
|
||||||
|
res = getHomeRoute(list);
|
||||||
|
} else {
|
||||||
|
const index = list.findIndex(item => routeEqual(item, route));
|
||||||
|
if (index === list.length - 1) res = list[list.length - 2];
|
||||||
|
else res = list[index + 1];
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断打开的标签列表里是否已存在这个新添加的路由对象
|
||||||
|
*/
|
||||||
|
export const routeHasExist = (tagNavList, routeItem) => {
|
||||||
|
let len = tagNavList.length;
|
||||||
|
let res = false;
|
||||||
|
doCustomTimes(len, index => {
|
||||||
|
if (routeEqual(tagNavList[index], routeItem)) res = true;
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* @param {*} list 现有标签导航列表
|
||||||
|
* @param {*} newRoute 新添加的路由原信息对象
|
||||||
|
* @description 如果该newRoute已经存在则不再添加
|
||||||
|
*/
|
||||||
|
export const getNewTagList = (list, newRoute) => {
|
||||||
|
const { name, path, meta, query } = newRoute;
|
||||||
|
let newList = [...list];
|
||||||
|
let index = newList.findIndex(item => item.name === name);
|
||||||
|
if (index >= 0) {
|
||||||
|
newList[index] = { name, path, meta, query };
|
||||||
|
} else newList.push({ name, path, meta, query });
|
||||||
|
return newList;
|
||||||
|
};
|
||||||
|
export const routeEqual = (route1, route2) => {
|
||||||
|
return route1.name === route2.name;
|
||||||
|
};
|
||||||
|
export const getRouteTitleHandled = route => {
|
||||||
|
let router = {
|
||||||
|
...route
|
||||||
|
};
|
||||||
|
let meta = {
|
||||||
|
...route.meta
|
||||||
|
};
|
||||||
|
let title = '';
|
||||||
|
if (meta.title) {
|
||||||
|
if (typeof meta.title === 'function') {
|
||||||
|
meta.__titleIsFunction__ = true;
|
||||||
|
title = meta.title(router);
|
||||||
|
} else title = meta.title;
|
||||||
|
}
|
||||||
|
meta.title = title;
|
||||||
|
router.meta = meta;
|
||||||
|
return router;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* @param {Number} times 回调函数需要执行的次数
|
||||||
|
* @param {Function} callback 回调函数
|
||||||
|
*/
|
||||||
|
export const doCustomTimes = (times, callback) => {
|
||||||
|
let i = -1;
|
||||||
|
while (++i < times) {
|
||||||
|
callback(i);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export const showTitle = (item, vm) => {
|
||||||
|
let { title, __titleIsFunction__ } = item.meta;
|
||||||
|
if (!title) return;
|
||||||
|
if (useI18n) {
|
||||||
|
if (title.includes('{{') && title.includes('}}') && useI18n) {
|
||||||
|
title = title.replace(/({{[\s\S]+?}})/, (m, str) =>
|
||||||
|
str.replace(/{{([\s\S]*)}}/, (m, _) => vm.$t(_.trim()))
|
||||||
|
);
|
||||||
|
} else if (__titleIsFunction__) title = item.meta.title;
|
||||||
|
else title = vm.$t(item.name);
|
||||||
|
} else title = (item.meta && item.meta.title) || item.name;
|
||||||
|
return title;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* @description 根据当前跳转的路由设置显示在浏览器标签的title
|
||||||
|
* @param {Object} routeItem 路由对象
|
||||||
|
* @param {Object} vm Vue实例
|
||||||
|
*/
|
||||||
|
export const setTitle = (routeItem, vm) => {
|
||||||
|
const handledRoute = getRouteTitleHandled(routeItem);
|
||||||
|
const pageTitle = showTitle(handledRoute, vm);
|
||||||
|
const resTitle = pageTitle ? `${pageTitle} - ${title}` : title;
|
||||||
|
window.document.title = resTitle;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const findNodeUpper = (ele, tag) => {
|
||||||
|
if (ele.parentNode) {
|
||||||
|
if (ele.parentNode.tagName === tag.toUpperCase()) {
|
||||||
|
return ele.parentNode;
|
||||||
|
} else {
|
||||||
|
return findNodeUpper(ele.parentNode, tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const findNodeUpperByClasses = (ele, classes) => {
|
||||||
|
let parentNode = ele.parentNode;
|
||||||
|
if (parentNode) {
|
||||||
|
let classList = parentNode.classList;
|
||||||
|
if (
|
||||||
|
classList &&
|
||||||
|
classes.every(className => classList.contains(className))
|
||||||
|
) {
|
||||||
|
return parentNode;
|
||||||
|
} else {
|
||||||
|
return findNodeUpperByClasses(parentNode, classes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const findNodeDownward = (ele, tag) => {
|
||||||
|
const tagName = tag.toUpperCase();
|
||||||
|
if (ele.childNodes.length) {
|
||||||
|
let i = -1;
|
||||||
|
let len = ele.childNodes.length;
|
||||||
|
while (++i < len) {
|
||||||
|
let child = ele.childNodes[i];
|
||||||
|
if (child.tagName === tagName) return child;
|
||||||
|
else return findNodeDownward(child, tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
133
smart-admin-h5/src/lib/printPlugs.js
Normal file
133
smart-admin-h5/src/lib/printPlugs.js
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
// 打印类属性、方法定义
|
||||||
|
/* eslint-disable */
|
||||||
|
//第二个参数表明是否要关闭当前窗口
|
||||||
|
const Print = function(dom, close, options) {
|
||||||
|
if (!(this instanceof Print)) return new Print(dom, close, options);
|
||||||
|
|
||||||
|
this.options = this.extend(
|
||||||
|
{
|
||||||
|
noPrint: '.no-print'
|
||||||
|
},
|
||||||
|
options
|
||||||
|
);
|
||||||
|
|
||||||
|
if (typeof dom === 'string') {
|
||||||
|
this.dom = document.querySelector(dom);
|
||||||
|
} else {
|
||||||
|
this.dom = dom;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.init(close);
|
||||||
|
};
|
||||||
|
Print.prototype = {
|
||||||
|
init: function(close) {
|
||||||
|
var content = this.getStyle() + this.getHtml();
|
||||||
|
this.writeIframe(content, close);
|
||||||
|
},
|
||||||
|
extend: function(obj, obj2) {
|
||||||
|
for (var k in obj2) {
|
||||||
|
obj[k] = obj2[k];
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
},
|
||||||
|
|
||||||
|
getStyle: function() {
|
||||||
|
var str = '',
|
||||||
|
styles = document.querySelectorAll('style,link');
|
||||||
|
for (var i = 0; i < styles.length; i++) {
|
||||||
|
str += styles[i].outerHTML;
|
||||||
|
}
|
||||||
|
str +=
|
||||||
|
'<style>body, html{height: auto; overflow: auto !important;}' +
|
||||||
|
(this.options.noPrint ? this.options.noPrint : '.no-print') +
|
||||||
|
'{display:none;}</style>';
|
||||||
|
|
||||||
|
return str;
|
||||||
|
},
|
||||||
|
|
||||||
|
getHtml: function() {
|
||||||
|
var inputs = document.querySelectorAll('input');
|
||||||
|
var textareas = document.querySelectorAll('textarea');
|
||||||
|
var selects = document.querySelectorAll('select');
|
||||||
|
|
||||||
|
for (var k in inputs) {
|
||||||
|
if (inputs[k].type == 'checkbox' || inputs[k].type == 'radio') {
|
||||||
|
if (inputs[k].checked == true) {
|
||||||
|
inputs[k].setAttribute('checked', 'checked');
|
||||||
|
} else {
|
||||||
|
inputs[k].removeAttribute('checked');
|
||||||
|
}
|
||||||
|
} else if (inputs[k].type == 'text') {
|
||||||
|
inputs[k].setAttribute('value', inputs[k].value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var k2 in textareas) {
|
||||||
|
if (textareas[k2].type == 'textarea') {
|
||||||
|
textareas[k2].innerHTML = textareas[k2].value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var k3 in selects) {
|
||||||
|
if (selects[k3].type == 'select-one') {
|
||||||
|
var child = selects[k3].children;
|
||||||
|
for (var i in child) {
|
||||||
|
if (child[i].tagName == 'OPTION') {
|
||||||
|
if (child[i].selected == true) {
|
||||||
|
child[i].setAttribute('selected', 'selected');
|
||||||
|
} else {
|
||||||
|
child[i].removeAttribute('selected');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.dom.outerHTML;
|
||||||
|
},
|
||||||
|
|
||||||
|
writeIframe: function(content, close) {
|
||||||
|
var w,
|
||||||
|
doc,
|
||||||
|
iframe = document.createElement('iframe'),
|
||||||
|
f = document.body.appendChild(iframe);
|
||||||
|
iframe.id = 'myIframe';
|
||||||
|
iframe.style = 'position:absolute;';
|
||||||
|
|
||||||
|
w = f.contentWindow || f.contentDocument;
|
||||||
|
doc = f.contentDocument || f.contentWindow.document;
|
||||||
|
doc.open();
|
||||||
|
doc.write(content);
|
||||||
|
doc.close();
|
||||||
|
this.toPrint(w, close);
|
||||||
|
setTimeout(function() {
|
||||||
|
document.body.removeChild(iframe);
|
||||||
|
}, 500);
|
||||||
|
},
|
||||||
|
|
||||||
|
toPrint: function(frameWindow, close) {
|
||||||
|
try {
|
||||||
|
setTimeout(function() {
|
||||||
|
frameWindow.focus();
|
||||||
|
try {
|
||||||
|
if (!frameWindow.document.execCommand('print', false, null)) {
|
||||||
|
frameWindow.print();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
frameWindow.print();
|
||||||
|
}
|
||||||
|
frameWindow.close();
|
||||||
|
if (close) {
|
||||||
|
window.close();
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
} catch (err) {
|
||||||
|
console.log('err', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const MyPlugin = {};
|
||||||
|
MyPlugin.install = function(Vue, options) {
|
||||||
|
// 4. 添加实例方法
|
||||||
|
Vue.prototype.$print = Print;
|
||||||
|
};
|
||||||
|
export default MyPlugin;
|
10
smart-admin-h5/src/lib/render-dom.js
Normal file
10
smart-admin-h5/src/lib/render-dom.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
export default {
|
||||||
|
name: 'RenderDom',
|
||||||
|
functional: true,
|
||||||
|
props: {
|
||||||
|
render: Function
|
||||||
|
},
|
||||||
|
render: (h, ctx) => {
|
||||||
|
return ctx.props.render(h);
|
||||||
|
}
|
||||||
|
};
|
18
smart-admin-h5/src/lib/smart-sentry.js
Normal file
18
smart-admin-h5/src/lib/smart-sentry.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* @Description:
|
||||||
|
* @Author: zhuoda
|
||||||
|
*/
|
||||||
|
// smart sentry
|
||||||
|
import * as Sentry from '@sentry/browser';
|
||||||
|
export default {
|
||||||
|
/**
|
||||||
|
* sentry 主动上报
|
||||||
|
* @param {error} error 错误信息
|
||||||
|
*/
|
||||||
|
captureException: (error) => {
|
||||||
|
if (error.config && error.data && error && error.headers && error.request && error.status) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Sentry.captureException(error);
|
||||||
|
}
|
||||||
|
};
|
84
smart-admin-h5/src/lib/table-action.js
Normal file
84
smart-admin-h5/src/lib/table-action.js
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
// 处理table操作按钮
|
||||||
|
const tableAction = (h, array) => {
|
||||||
|
let btnArray = [];
|
||||||
|
let btnMore = [];
|
||||||
|
array.map((item, index) => {
|
||||||
|
if (index < 2) {
|
||||||
|
let btn = h(
|
||||||
|
'a',
|
||||||
|
{
|
||||||
|
props: {
|
||||||
|
type: !index ? 'primary' : 'info',
|
||||||
|
size: 'small',
|
||||||
|
to: item.to ? item.to : '',
|
||||||
|
target: item.target ? item.target : '_self',
|
||||||
|
ghost: true
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
marginLeft: '5px'
|
||||||
|
},
|
||||||
|
directives: item.directives,
|
||||||
|
on: {
|
||||||
|
click: item.action
|
||||||
|
}
|
||||||
|
},
|
||||||
|
item.title
|
||||||
|
);
|
||||||
|
btnArray.push(btn);
|
||||||
|
} else {
|
||||||
|
btnMore.push(
|
||||||
|
h(
|
||||||
|
'DropdownItem',
|
||||||
|
{
|
||||||
|
nativeOn: {
|
||||||
|
click: item.action
|
||||||
|
}
|
||||||
|
},
|
||||||
|
item.title
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let dropdown = h(
|
||||||
|
'Dropdown',
|
||||||
|
{
|
||||||
|
props: {
|
||||||
|
transfer: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[
|
||||||
|
h(
|
||||||
|
'a',
|
||||||
|
{
|
||||||
|
props: {
|
||||||
|
type: 'default',
|
||||||
|
size: 'small'
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
marginLeft: '5px'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[
|
||||||
|
h('span', '更多'),
|
||||||
|
h('Icon', {
|
||||||
|
props: {
|
||||||
|
type: 'ios-arrow-down'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
),
|
||||||
|
h(
|
||||||
|
'DropdownMenu',
|
||||||
|
{
|
||||||
|
slot: 'list'
|
||||||
|
},
|
||||||
|
btnMore
|
||||||
|
)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
if (array.length > 2) {
|
||||||
|
btnArray.push(dropdown);
|
||||||
|
}
|
||||||
|
return btnArray;
|
||||||
|
};
|
||||||
|
export default tableAction;
|
515
smart-admin-h5/src/lib/util.js
Normal file
515
smart-admin-h5/src/lib/util.js
Normal file
@ -0,0 +1,515 @@
|
|||||||
|
import moment from 'moment';
|
||||||
|
/**
|
||||||
|
* @param {String} url
|
||||||
|
* @description 从URL中解析参数
|
||||||
|
*/
|
||||||
|
export const getParams = url => {
|
||||||
|
const keyValueArr = url.split('?')[1].split('&');
|
||||||
|
let paramObj = {};
|
||||||
|
keyValueArr.forEach(item => {
|
||||||
|
const keyValue = item.split('=');
|
||||||
|
paramObj[keyValue[0]] = keyValue[1];
|
||||||
|
});
|
||||||
|
return paramObj;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Any} obj
|
||||||
|
* @description 获取数据类型
|
||||||
|
*/
|
||||||
|
export const getType = obj => {
|
||||||
|
return {}.toString
|
||||||
|
.call(obj)
|
||||||
|
.match(/\s([a-zA-Z]+)/)[1]
|
||||||
|
.toLowerCase();
|
||||||
|
};
|
||||||
|
// 日期格式
|
||||||
|
export const dateFormat = {
|
||||||
|
YMD: 'YMD',
|
||||||
|
YMDHM: 'YMDHM',
|
||||||
|
YMDHMS: 'YMDHMS'
|
||||||
|
};
|
||||||
|
export const forEach = (arr, fn) => {
|
||||||
|
if (!arr.length || !fn) return;
|
||||||
|
let i = -1;
|
||||||
|
let len = arr.length;
|
||||||
|
while (++i < len) {
|
||||||
|
let item = arr[i];
|
||||||
|
fn(item, i, arr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Array} arr1
|
||||||
|
* @param {Array} arr2
|
||||||
|
* @description 得到两个数组的交集, 两个数组的元素为数值或字符串
|
||||||
|
*/
|
||||||
|
export const getIntersection = (arr1, arr2) => {
|
||||||
|
let len = Math.min(arr1.length, arr2.length);
|
||||||
|
let i = -1;
|
||||||
|
let res = [];
|
||||||
|
while (++i < len) {
|
||||||
|
const item = arr2[i];
|
||||||
|
if (arr1.indexOf(item) > -1) res.push(item);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Array} arr1
|
||||||
|
* @param {Array} arr2
|
||||||
|
* @description 得到两个数组的并集, 两个数组的元素为数值或字符串
|
||||||
|
*/
|
||||||
|
export const getUnion = (arr1, arr2) => {
|
||||||
|
return Array.from(new Set([...arr1, ...arr2]));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Array} target 目标数组
|
||||||
|
* @param {Array} arr 需要查询的数组
|
||||||
|
* @description 判断要查询的数组是否至少有一个元素包含在目标数组中
|
||||||
|
*/
|
||||||
|
export const hasOneOf = (targetarr, arr) => {
|
||||||
|
return targetarr.some(_ => arr.indexOf(_) > -1);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {String|Number} value 要验证的字符串或数值
|
||||||
|
* @param {*} validList 用来验证的列表
|
||||||
|
*/
|
||||||
|
export function oneOf (value, validList) {
|
||||||
|
for (let i = 0; i < validList.length; i++) {
|
||||||
|
if (value === validList[i]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} timeStamp 判断时间戳格式是否是毫秒
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
|
const isMillisecond = timeStamp => {
|
||||||
|
const timeStr = String(timeStamp);
|
||||||
|
return timeStr.length > 10;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} timeStamp 传入的时间戳
|
||||||
|
* @param {Number} currentTime 当前时间时间戳
|
||||||
|
* @returns {Boolean} 传入的时间戳是否早于当前时间戳
|
||||||
|
*/
|
||||||
|
const isEarly = (timeStamp, currentTime) => {
|
||||||
|
return timeStamp < currentTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} num 数值
|
||||||
|
* @returns {String} 处理后的字符串
|
||||||
|
* @description 如果传入的数值小于10,即位数只有1位,则在前面补充0
|
||||||
|
*/
|
||||||
|
const getHandledValue = num => {
|
||||||
|
return num < 10 ? '0' + num : num;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} timeStamp 传入的时间戳
|
||||||
|
* @param {Number} startType 要返回的时间字符串的格式类型,传入'year'则返回年开头的完整时间
|
||||||
|
*/
|
||||||
|
const getDate = (timeStamp, startType) => {
|
||||||
|
const d = new Date(timeStamp * 1000);
|
||||||
|
const year = d.getFullYear();
|
||||||
|
const month = getHandledValue(d.getMonth() + 1);
|
||||||
|
const date = getHandledValue(d.getDate());
|
||||||
|
const hours = getHandledValue(d.getHours());
|
||||||
|
const minutes = getHandledValue(d.getMinutes());
|
||||||
|
const second = getHandledValue(d.getSeconds());
|
||||||
|
let resStr = '';
|
||||||
|
if (startType === 'year') {
|
||||||
|
resStr =
|
||||||
|
year +
|
||||||
|
'-' +
|
||||||
|
month +
|
||||||
|
'-' +
|
||||||
|
date +
|
||||||
|
' ' +
|
||||||
|
hours +
|
||||||
|
':' +
|
||||||
|
minutes +
|
||||||
|
':' +
|
||||||
|
second;
|
||||||
|
}
|
||||||
|
else resStr = month + '-' + date + ' ' + hours + ':' + minutes;
|
||||||
|
return resStr;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {String|Number} timeStamp 时间戳
|
||||||
|
* @returns {String} 相对时间字符串
|
||||||
|
*/
|
||||||
|
export const getRelativeTime = timeStamp => {
|
||||||
|
// 判断当前传入的时间戳是秒格式还是毫秒
|
||||||
|
const IS_MILLISECOND = isMillisecond(timeStamp);
|
||||||
|
// 如果是毫秒格式则转为秒格式
|
||||||
|
if (IS_MILLISECOND) Math.floor((timeStamp /= 1000));
|
||||||
|
// 传入的时间戳可以是数值或字符串类型,这里统一转为数值类型
|
||||||
|
timeStamp = Number(timeStamp);
|
||||||
|
// 获取当前时间时间戳
|
||||||
|
const currentTime = Math.floor(Date.parse(new Date()) / 1000);
|
||||||
|
// 判断传入时间戳是否早于当前时间戳
|
||||||
|
const IS_EARLY = isEarly(timeStamp, currentTime);
|
||||||
|
// 获取两个时间戳差值
|
||||||
|
let diff = currentTime - timeStamp;
|
||||||
|
// 如果IS_EARLY为false则差值取反
|
||||||
|
if (!IS_EARLY) diff = -diff;
|
||||||
|
let resStr = '';
|
||||||
|
const dirStr = IS_EARLY ? '前' : '后';
|
||||||
|
// 少于等于59秒
|
||||||
|
if (diff <= 59) resStr = diff + '秒' + dirStr;
|
||||||
|
// 多于59秒,少于等于59分钟59秒
|
||||||
|
else if (diff > 59 && diff <= 3599) { resStr = Math.floor(diff / 60) + '分钟' + dirStr; }
|
||||||
|
// 多于59分钟59秒,少于等于23小时59分钟59秒
|
||||||
|
else if (diff > 3599 && diff <= 86399) { resStr = Math.floor(diff / 3600) + '小时' + dirStr; }
|
||||||
|
// 多于23小时59分钟59秒,少于等于29天59分钟59秒
|
||||||
|
else if (diff > 86399 && diff <= 2623859) { resStr = Math.floor(diff / 86400) + '天' + dirStr; }
|
||||||
|
// 多于29天59分钟59秒,少于364天23小时59分钟59秒,且传入的时间戳早于当前
|
||||||
|
else if (diff > 2623859 && diff <= 31567859 && IS_EARLY) { resStr = getDate(timeStamp); }
|
||||||
|
else resStr = getDate(timeStamp, 'year');
|
||||||
|
return resStr;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {String} 当前浏览器名称
|
||||||
|
*/
|
||||||
|
export const getExplorer = () => {
|
||||||
|
const ua = window.navigator.userAgent;
|
||||||
|
const isExplorer = exp => {
|
||||||
|
return ua.indexOf(exp) > -1;
|
||||||
|
};
|
||||||
|
if (isExplorer('MSIE')) return 'IE';
|
||||||
|
else if (isExplorer('Firefox')) return 'Firefox';
|
||||||
|
else if (isExplorer('Chrome')) return 'Chrome';
|
||||||
|
else if (isExplorer('Opera')) return 'Opera';
|
||||||
|
else if (isExplorer('Safari')) return 'Safari';
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 绑定事件 on(element, event, handler)
|
||||||
|
*/
|
||||||
|
export const on = (function () {
|
||||||
|
if (document.addEventListener) {
|
||||||
|
return function (element, event, handler) {
|
||||||
|
if (element && event && handler) {
|
||||||
|
element.addEventListener(event, handler, false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return function (element, event, handler) {
|
||||||
|
if (element && event && handler) {
|
||||||
|
element.attachEvent('on' + event, handler);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 解绑事件 off(element, event, handler)
|
||||||
|
*/
|
||||||
|
export const off = (function () {
|
||||||
|
if (document.removeEventListener) {
|
||||||
|
return function (element, event, handler) {
|
||||||
|
if (element && event) {
|
||||||
|
element.removeEventListener(event, handler, false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return function (element, event, handler) {
|
||||||
|
if (element && event) {
|
||||||
|
element.detachEvent('on' + event, handler);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断一个对象是否存在key,如果传入第二个参数key,则是判断这个obj对象是否存在key这个属性
|
||||||
|
* 如果没有传入key这个参数,则判断obj对象是否有键值对
|
||||||
|
*/
|
||||||
|
export const hasKey = (obj, key) => {
|
||||||
|
if (key) return key in obj;
|
||||||
|
else {
|
||||||
|
let keysArr = Object.keys(obj);
|
||||||
|
return keysArr.length;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {*} obj1 对象
|
||||||
|
* @param {*} obj2 对象
|
||||||
|
* @description 判断两个对象是否相等,这两个对象的值只能是数字或字符串
|
||||||
|
*/
|
||||||
|
export const objEqual = (obj1, obj2) => {
|
||||||
|
const keysArr1 = Object.keys(obj1);
|
||||||
|
const keysArr2 = Object.keys(obj2);
|
||||||
|
if (keysArr1.length !== keysArr2.length) return false;
|
||||||
|
else if (keysArr1.length === 0 && keysArr2.length === 0) return true;
|
||||||
|
/* eslint-disable-next-line */ else { return !keysArr1.some(key => obj1[key] != obj2[key]); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// 相关工具类
|
||||||
|
export const utils = {
|
||||||
|
/**
|
||||||
|
* @description table实现反选
|
||||||
|
* @param {Object} vm Vue实例
|
||||||
|
* @param {Array} tableSelectDate 选中的数据
|
||||||
|
* @param {Array} allData 所有数据
|
||||||
|
* @param {Array} key 数据中的唯一值
|
||||||
|
*/
|
||||||
|
reverseSelect (vm, tableSelectDate, allData, key) {
|
||||||
|
let copyMess = JSON.parse(JSON.stringify(tableSelectDate));
|
||||||
|
// 流程:先全部选中->再部分选中
|
||||||
|
vm.handleSelectAll(false);
|
||||||
|
// 选中的idList
|
||||||
|
let idList = copyMess.map(item => item[key]);
|
||||||
|
console.log(idList);
|
||||||
|
for (let item of allData) {
|
||||||
|
if (idList.every(id => id !== item.id)) {
|
||||||
|
vm.$set(item, '_checked', true);
|
||||||
|
tableSelectDate.push(item);
|
||||||
|
} else {
|
||||||
|
vm.$set(item, '_checked', false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 校验字符串是否相同 合同使用
|
||||||
|
contrastString (originStr, changeStr) {
|
||||||
|
let origin = originStr
|
||||||
|
.replace(/\s*/g, '')
|
||||||
|
.replace(/"/g, '\'')
|
||||||
|
.replace(/ /g, '')
|
||||||
|
.replace(/disabled=\/'\/'/g, 'disabled');
|
||||||
|
let change = changeStr
|
||||||
|
.replace(/\s*/g, '')
|
||||||
|
.replace(/"/g, '\'')
|
||||||
|
.replace(/ /g, '')
|
||||||
|
.replace(/disabled=\/'\/'/g, 'disabled');
|
||||||
|
return origin === change;
|
||||||
|
},
|
||||||
|
// 获取当前日期getDateStr(0)、前几天getDateStr(-10)、后几天getDateStr(20)
|
||||||
|
getDateStr (AddDayCount, format) {
|
||||||
|
let date = new Date();
|
||||||
|
// 获取AddDayCount天后的日期
|
||||||
|
date.setDate(date.getDate() + AddDayCount);
|
||||||
|
return this.getDate(date, format);
|
||||||
|
},
|
||||||
|
getDate (date, format) {
|
||||||
|
let year = date.getFullYear();
|
||||||
|
// day获取当前几号,不足10补0
|
||||||
|
let day = date.getDate() > 9 ? date.getDate() : '0' + date.getDate();
|
||||||
|
// month获取当前月份的日期,不足10补0
|
||||||
|
let month =
|
||||||
|
date.getMonth() + 1 > 9
|
||||||
|
? date.getMonth() + 1
|
||||||
|
: '0' + (date.getMonth() + 1);
|
||||||
|
// h获取当前小时,不足10补0
|
||||||
|
let h = date.getHours() > 9 ? date.getHours() : '0' + date.getHours();
|
||||||
|
// s获取当前分钟,不足10补0
|
||||||
|
let m = date.getMinutes() > 9 ? date.getMinutes() : '0' + date.getMinutes();
|
||||||
|
// s获取当前秒数,不足10补0
|
||||||
|
let s = date.getSeconds() > 9 ? date.getSeconds() : '0' + date.getSeconds();
|
||||||
|
let resultDate = '';
|
||||||
|
if (format === dateFormat.YMD) {
|
||||||
|
resultDate = year + '-' + month + '-' + day;
|
||||||
|
}
|
||||||
|
if (format === dateFormat.YMDHM) {
|
||||||
|
resultDate = year + '-' + month + '-' + day + ' ' + h + ':' + m;
|
||||||
|
}
|
||||||
|
if (format === dateFormat.YMDHMS) {
|
||||||
|
resultDate = year + '-' + month + '-' + day + ' ' + h + ':' + m + ':' + s;
|
||||||
|
}
|
||||||
|
return resultDate;
|
||||||
|
},
|
||||||
|
// 获取周一和周日日期,返回两种格式时间
|
||||||
|
getDateWeek () {
|
||||||
|
let now = new Date();
|
||||||
|
let nowTime = now.getTime();
|
||||||
|
let day = now.getDay();
|
||||||
|
let oneDayLong = 1000 * 60 * 60 * 24;
|
||||||
|
let MondayTime = nowTime - (day - 1) * oneDayLong;
|
||||||
|
let SundayTime = nowTime + (7 - day) * oneDayLong;
|
||||||
|
let monday = new Date(MondayTime);
|
||||||
|
let sunday = new Date(SundayTime);
|
||||||
|
return {
|
||||||
|
// first: this.getDateAll(monday),
|
||||||
|
// last: this.getDateAll(sunday),
|
||||||
|
firstDate: monday,
|
||||||
|
lastDate: sunday
|
||||||
|
};
|
||||||
|
},
|
||||||
|
// 获取月初与月末日期,返回两种时间格式
|
||||||
|
getDateMonth () {
|
||||||
|
let dateFirter = new Date();
|
||||||
|
let dateLast = new Date();
|
||||||
|
dateFirter.setDate(1);
|
||||||
|
|
||||||
|
let currentMonth = dateLast.getMonth();
|
||||||
|
let nextMonth = ++currentMonth;
|
||||||
|
let nextMonthFirstDay = new Date(dateLast.getFullYear(), nextMonth, 1);
|
||||||
|
let oneDay = 1000 * 60 * 60 * 24;
|
||||||
|
dateLast = new Date(nextMonthFirstDay - oneDay);
|
||||||
|
|
||||||
|
return {
|
||||||
|
// first: this.getDateAll(dateFirter),
|
||||||
|
// last: this.getDateAll(dateLast),
|
||||||
|
firstDate: dateFirter,
|
||||||
|
lastDate: dateLast
|
||||||
|
};
|
||||||
|
},
|
||||||
|
// 计算天数
|
||||||
|
getDayBetweenDate (date) {
|
||||||
|
date = this.getDate(new Date(date), 'YMD');
|
||||||
|
let startTime = Date.parse(new Date(date)); // IE支持“yyyy/MM/dd”格式
|
||||||
|
let endTime = Date.parse(this.getDate(new Date(), 'YMD'));
|
||||||
|
let day = parseInt((endTime - startTime) / (1000 * 60 * 60 * 24));
|
||||||
|
return day;
|
||||||
|
},
|
||||||
|
getDateIntervalYear (firstDate, secondDate) {
|
||||||
|
if (!firstDate || !secondDate) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
let first = new Date(firstDate);
|
||||||
|
let second = new Date(secondDate);
|
||||||
|
let firstYear = first.getFullYear();
|
||||||
|
let secondYear = second.getFullYear();
|
||||||
|
let intervalYear = secondYear - firstYear;
|
||||||
|
return intervalYear < 0 ? 0 : intervalYear;
|
||||||
|
},
|
||||||
|
getDateIntervalYearFixed2 (firstDate, secondDate) {
|
||||||
|
if (!firstDate || !secondDate) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// 格式化时间
|
||||||
|
let startDate = new Date(this.getDate(new Date(firstDate), 'YMD'));
|
||||||
|
let endDate = new Date(this.getDate(new Date(secondDate), 'YMD'));
|
||||||
|
// 得到毫秒值
|
||||||
|
let startTime = Date.parse(startDate);
|
||||||
|
let endTime = Date.parse(endDate);
|
||||||
|
// 得到差了多少天
|
||||||
|
let day = parseInt((endTime - startTime) / (1000 * 60 * 60 * 24));
|
||||||
|
if (day <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// 得到差的多少年 保留两位小数
|
||||||
|
let resultYear = parseFloat((day / (30 * 12)).toFixed(2));
|
||||||
|
return resultYear;
|
||||||
|
},
|
||||||
|
// 数字转化为中文大写
|
||||||
|
// 代码如下所示:
|
||||||
|
convertCurrency (money) {
|
||||||
|
// 汉字的数字
|
||||||
|
let cnNums = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
|
||||||
|
// 基本单位
|
||||||
|
let cnIntRadice = ['', '拾', '佰', '仟'];
|
||||||
|
// 对应整数部分扩展单位
|
||||||
|
let cnIntUnits = ['', '万', '亿', '兆'];
|
||||||
|
// 对应小数部分单位
|
||||||
|
let cnDecUnits = ['角', '分', '毫', '厘'];
|
||||||
|
// 整数金额时后面跟的字符
|
||||||
|
let cnInteger = '整';
|
||||||
|
// 整型完以后的单位
|
||||||
|
let cnIntLast = '元';
|
||||||
|
// 最大处理的数字
|
||||||
|
let maxNum = 999999999999999.9999;
|
||||||
|
// 金额整数部分
|
||||||
|
let integerNum;
|
||||||
|
// 金额小数部分
|
||||||
|
let decimalNum;
|
||||||
|
// 输出的中文金额字符串
|
||||||
|
let chineseStr = '';
|
||||||
|
// 分离金额后用的数组,预定义
|
||||||
|
let parts;
|
||||||
|
if (money === '') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
money = parseFloat(money);
|
||||||
|
if (money >= maxNum) {
|
||||||
|
// 超出最大处理数字
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
if (money === 0) {
|
||||||
|
chineseStr = cnNums[0] + cnIntLast + cnInteger;
|
||||||
|
return chineseStr;
|
||||||
|
}
|
||||||
|
// 转换为字符串
|
||||||
|
money = money.toString();
|
||||||
|
if (money.indexOf('.') === -1) {
|
||||||
|
integerNum = money;
|
||||||
|
decimalNum = '';
|
||||||
|
} else {
|
||||||
|
parts = money.split('.');
|
||||||
|
integerNum = parts[0];
|
||||||
|
decimalNum = parts[1].substr(0, 4);
|
||||||
|
}
|
||||||
|
// 获取整型部分转换
|
||||||
|
if (parseInt(integerNum, 10) > 0) {
|
||||||
|
let zeroCount = 0;
|
||||||
|
let IntLen = integerNum.length;
|
||||||
|
for (let i = 0; i < IntLen; i++) {
|
||||||
|
let n = integerNum.substr(i, 1);
|
||||||
|
let p = IntLen - i - 1;
|
||||||
|
let q = p / 4;
|
||||||
|
let m = p % 4;
|
||||||
|
if (n === '0') {
|
||||||
|
zeroCount++;
|
||||||
|
} else {
|
||||||
|
if (zeroCount > 0) {
|
||||||
|
chineseStr += cnNums[0];
|
||||||
|
}
|
||||||
|
// 归零
|
||||||
|
zeroCount = 0;
|
||||||
|
chineseStr += cnNums[parseInt(n)] + cnIntRadice[m];
|
||||||
|
}
|
||||||
|
if (m === 0 && zeroCount < 4) {
|
||||||
|
chineseStr += cnIntUnits[q];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chineseStr += cnIntLast;
|
||||||
|
}
|
||||||
|
// 小数部分
|
||||||
|
if (decimalNum !== '') {
|
||||||
|
let decLen = decimalNum.length;
|
||||||
|
for (let i = 0; i < decLen; i++) {
|
||||||
|
let n = decimalNum.substr(i, 1);
|
||||||
|
if (n !== '0') {
|
||||||
|
chineseStr += cnNums[Number(n)] + cnDecUnits[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chineseStr === '') {
|
||||||
|
chineseStr += cnNums[0] + cnIntLast + cnInteger;
|
||||||
|
} else if (decimalNum === '') {
|
||||||
|
chineseStr += cnInteger;
|
||||||
|
}
|
||||||
|
return chineseStr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export const dateTimeRangeConvert = (timerange) => {
|
||||||
|
// timerange
|
||||||
|
let arr = [];
|
||||||
|
if (timerange[0] === '') {
|
||||||
|
arr.push(null);
|
||||||
|
} else {
|
||||||
|
arr.push(moment(timerange[0]).format("YYYY-MM-DD 00:00:00"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timerange[1] === '') {
|
||||||
|
arr.push(null);
|
||||||
|
} else {
|
||||||
|
arr.push(moment(timerange[1]).format("YYYY-MM-DD 23:59:59"));
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
49
smart-admin-h5/src/lib/watermark.js
Normal file
49
smart-admin-h5/src/lib/watermark.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
const watermark = {};
|
||||||
|
|
||||||
|
const setWatermark = (str) => {
|
||||||
|
const id = '1.23452384164.123412415';
|
||||||
|
|
||||||
|
if (document.getElementById(id) !== null) {
|
||||||
|
document.body.removeChild(document.getElementById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
const can = document.createElement('canvas');
|
||||||
|
can.width = 150;
|
||||||
|
can.height = 120;
|
||||||
|
|
||||||
|
const cans = can.getContext('2d');
|
||||||
|
cans.rotate(-20 * Math.PI / 180);
|
||||||
|
cans.font = '15px Vedana';
|
||||||
|
cans.fillStyle = 'rgba(0, 0, 0, 0.15)';
|
||||||
|
cans.textAlign = 'left';
|
||||||
|
cans.textBaseline = 'Middle';
|
||||||
|
cans.fillText(str, can.width / 20, can.height);
|
||||||
|
|
||||||
|
const div = document.createElement('div');
|
||||||
|
div.id = id;
|
||||||
|
div.style.pointerEvents = 'none';
|
||||||
|
div.style.top = '3px';
|
||||||
|
div.style.left = '0px';
|
||||||
|
div.style.position = 'fixed';
|
||||||
|
div.style.zIndex = '100000';
|
||||||
|
div.style.width = document.documentElement.clientWidth + 'px';
|
||||||
|
div.style.height = document.documentElement.clientHeight + 'px';
|
||||||
|
div.style.background = 'url(' + can.toDataURL('image/png') + ') left top repeat';
|
||||||
|
document.body.appendChild(div);
|
||||||
|
return id;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 该方法只允许调用一次
|
||||||
|
watermark.set = (str) => {
|
||||||
|
let id = setWatermark(str);
|
||||||
|
setInterval(() => {
|
||||||
|
if (document.getElementById(id) === null) {
|
||||||
|
id = setWatermark(str);
|
||||||
|
}
|
||||||
|
}, 2000);
|
||||||
|
window.onresize = () => {
|
||||||
|
setWatermark(str);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default watermark;
|
62
smart-admin-h5/src/main.js
Normal file
62
smart-admin-h5/src/main.js
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// vue 三大核心
|
||||||
|
import Vue from 'vue';
|
||||||
|
import router from '@/router';
|
||||||
|
import store from '@/store';
|
||||||
|
|
||||||
|
// 更好的兼容性
|
||||||
|
import 'core-js/stable';
|
||||||
|
import 'regenerator-runtime/runtime';
|
||||||
|
// 移动端适配
|
||||||
|
import 'lib-flexible/flexible.js';
|
||||||
|
import 'vant/lib/index.css';
|
||||||
|
// 引入首个组件
|
||||||
|
import App from './App.vue';
|
||||||
|
// 引入自定义主题样式
|
||||||
|
import './themes/index.less';
|
||||||
|
// 引入过滤器
|
||||||
|
import './filters';
|
||||||
|
// 引入配置信息
|
||||||
|
import config from '@/config';
|
||||||
|
// 引入自定义smart 插件
|
||||||
|
import SmartPlugin from './plugins/smart';
|
||||||
|
// Import component
|
||||||
|
import Loading from 'vue-loading-overlay';
|
||||||
|
// Import stylesheet
|
||||||
|
import 'vue-loading-overlay/dist/vue-loading.css';
|
||||||
|
|
||||||
|
import Vant from 'vant';
|
||||||
|
import 'vant/lib/index.css';
|
||||||
|
|
||||||
|
// sentry错误预警
|
||||||
|
import SmartSentry from './plugins/smart-sentry';
|
||||||
|
|
||||||
|
import Enum from 'vue-enum';
|
||||||
|
|
||||||
|
import enumInfo from '@/constants';
|
||||||
|
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
Vue.use(Vant);
|
||||||
|
|
||||||
|
Vue.use(Loading);
|
||||||
|
|
||||||
|
Vue.use(SmartPlugin);
|
||||||
|
|
||||||
|
Vue.use(SmartSentry);
|
||||||
|
|
||||||
|
Vue.prototype.$config = config;
|
||||||
|
|
||||||
|
Vue.config.productionTip = false;
|
||||||
|
|
||||||
|
Vue.use(Enum, {
|
||||||
|
enumInfo
|
||||||
|
});
|
||||||
|
|
||||||
|
window._ = _;
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el: '#app',
|
||||||
|
router,
|
||||||
|
store,
|
||||||
|
render: h => h(App)
|
||||||
|
});
|
17
smart-admin-h5/src/plugins/smart-sentry.js
Normal file
17
smart-admin-h5/src/plugins/smart-sentry.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import * as Sentry from '@sentry/browser';
|
||||||
|
|
||||||
|
const SmartSentry = {};
|
||||||
|
|
||||||
|
SmartSentry.install = function(Vue, options) {
|
||||||
|
Vue.prototype.$smartSentry = {
|
||||||
|
captureException: (error) => {
|
||||||
|
console.error(error);
|
||||||
|
if (error.config && error.data && error && error.headers && error.request && error.status) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Sentry.captureException(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SmartSentry;
|
24
smart-admin-h5/src/plugins/smart.js
Normal file
24
smart-admin-h5/src/plugins/smart.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
let loader = null;
|
||||||
|
|
||||||
|
const SmartPlugin = {};
|
||||||
|
|
||||||
|
SmartPlugin.install = function(Vue, options) {
|
||||||
|
Vue.prototype.$smart = {
|
||||||
|
loading: (message) => {
|
||||||
|
if (loader) {
|
||||||
|
loader.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
loader = Vue.$loading.show({
|
||||||
|
// Optional parameters
|
||||||
|
lockScroll: true,
|
||||||
|
color: '#1989fa'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
loadingClear: () => {
|
||||||
|
loader.hide();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SmartPlugin;
|
8
smart-admin-h5/src/plugins/vant.js
Normal file
8
smart-admin-h5/src/plugins/vant.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// 按需全局引入 vant组件
|
||||||
|
import Vue from 'vue';
|
||||||
|
import { Button, List, Cell, Tabbar, TabbarItem } from 'vant';
|
||||||
|
|
||||||
|
Vue.use(Button);
|
||||||
|
Vue.use(Cell);
|
||||||
|
Vue.use(List);
|
||||||
|
Vue.use(Tabbar).use(TabbarItem);
|
131
smart-admin-h5/src/router/index.js
Normal file
131
smart-admin-h5/src/router/index.js
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
import Vue from 'vue';
|
||||||
|
import Router from 'vue-router';
|
||||||
|
import { routers } from './routers';
|
||||||
|
import cookie from '@/lib/cookie';
|
||||||
|
import { ROUTER_PERMISSION_TYPE } from './router-const';
|
||||||
|
import NProgress from 'nprogress';
|
||||||
|
import 'nprogress/nprogress.css';
|
||||||
|
|
||||||
|
const projectConfig = require('@/config/index.js');
|
||||||
|
|
||||||
|
Vue.use(Router);
|
||||||
|
|
||||||
|
const router = new Router({
|
||||||
|
routes: routers
|
||||||
|
});
|
||||||
|
|
||||||
|
// 解决路由跳转相同的地址报错
|
||||||
|
const originalPush = Router.prototype.push;
|
||||||
|
Router.prototype.push = function(location) {
|
||||||
|
try {
|
||||||
|
return originalPush.call(this, location).catch(err => err);
|
||||||
|
} catch (error) {
|
||||||
|
// TODO zhuoda sentry
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const LOGIN_PAGE_NAME = 'Login';
|
||||||
|
|
||||||
|
router.beforeEach((to, from, next) => {
|
||||||
|
// 加载进度条
|
||||||
|
NProgress.start();
|
||||||
|
|
||||||
|
// 权限
|
||||||
|
const permissionType = to.meta.permissionType;
|
||||||
|
// 不需要验证,直接放行
|
||||||
|
if (permissionType === ROUTER_PERMISSION_TYPE.NO_VALID.value) {
|
||||||
|
next();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const token = cookie.getToken();
|
||||||
|
// 需要登录
|
||||||
|
if (permissionType === ROUTER_PERMISSION_TYPE.NEED_LOGIN.value) {
|
||||||
|
if (token) {
|
||||||
|
next();
|
||||||
|
} else {
|
||||||
|
next({
|
||||||
|
name: LOGIN_PAGE_NAME
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 需要登录,且验证权限
|
||||||
|
if (permissionType === ROUTER_PERMISSION_TYPE.VALIDATE_PERMISSION.value) {
|
||||||
|
if (!token) {
|
||||||
|
// TODO 验证权限
|
||||||
|
next({
|
||||||
|
name: LOGIN_PAGE_NAME
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
next({
|
||||||
|
name: 'Error404'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
router.afterEach(to => {
|
||||||
|
NProgress.done();
|
||||||
|
window.scrollTo(0, 0);
|
||||||
|
if (to.meta.title) {
|
||||||
|
console.log(to.meta);
|
||||||
|
document.title = to.meta.title + ' ' + projectConfig.title;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const tempCheckObj = {
|
||||||
|
checkRouterNameMap: new Map(),
|
||||||
|
checkRouterPathMap: new Map()
|
||||||
|
};
|
||||||
|
|
||||||
|
function recursionCheckRouter(routerArray) {
|
||||||
|
for (const routerItem of routerArray) {
|
||||||
|
if (!routerItem.name) {
|
||||||
|
console.error('没有配置router name', routerItem);
|
||||||
|
} else {
|
||||||
|
const existNameRouter = tempCheckObj.checkRouterNameMap.get(
|
||||||
|
routerItem.name
|
||||||
|
);
|
||||||
|
if (typeof existNameRouter !== 'undefined') {
|
||||||
|
console.error('存在相同的router name', routerItem, existNameRouter);
|
||||||
|
} else {
|
||||||
|
tempCheckObj.checkRouterNameMap.set(routerItem.name, routerItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!routerItem.path) {
|
||||||
|
console.error('没有配置router path', routerItem);
|
||||||
|
} else {
|
||||||
|
// path必须以 / 开头
|
||||||
|
if (routerItem.path !== '*' && routerItem.path.indexOf('/') !== 0) {
|
||||||
|
console.error('path 没有以/开头 ', routerItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
const existPathRouter = tempCheckObj.checkRouterPathMap.get(
|
||||||
|
routerItem.path
|
||||||
|
);
|
||||||
|
if (typeof existPathRouter !== 'undefined') {
|
||||||
|
console.error('存在相同的router path', routerItem, existPathRouter);
|
||||||
|
} else {
|
||||||
|
tempCheckObj.checkRouterPathMap.set(routerItem.path, routerItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (routerItem.children) {
|
||||||
|
recursionCheckRouter(routerItem.children);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是开发环境,需要检测router的规范性
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
recursionCheckRouter(routers);
|
||||||
|
delete tempCheckObj.checkRouterNameMap;
|
||||||
|
delete tempCheckObj.checkRouterPathMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default router;
|
15
smart-admin-h5/src/router/other/develop.js
Normal file
15
smart-admin-h5/src/router/other/develop.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { ROUTER_PERMISSION_TYPE } from '@/router/router-const';
|
||||||
|
|
||||||
|
export const develop = [
|
||||||
|
{
|
||||||
|
path: '/develop/config',
|
||||||
|
name: 'DevelopConfig',
|
||||||
|
meta: {
|
||||||
|
title: '开发专用配置',
|
||||||
|
permissionType: ROUTER_PERMISSION_TYPE.NEED_LOGIN.value
|
||||||
|
},
|
||||||
|
component: () =>
|
||||||
|
import('@/views/develop/config')
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
37
smart-admin-h5/src/router/other/error.js
Normal file
37
smart-admin-h5/src/router/other/error.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// 错误页
|
||||||
|
import { ROUTER_PERMISSION_TYPE } from '@/router/router-const';
|
||||||
|
|
||||||
|
export const error = [
|
||||||
|
{
|
||||||
|
path: '/404',
|
||||||
|
name: 'Error404',
|
||||||
|
meta: {
|
||||||
|
hideInMenu: true,
|
||||||
|
access: true,
|
||||||
|
permissionType: ROUTER_PERMISSION_TYPE.NO_VALID.value
|
||||||
|
},
|
||||||
|
component: () => import('@/views/error/404.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/500',
|
||||||
|
name: 'Error500',
|
||||||
|
meta: {
|
||||||
|
hideInMenu: true,
|
||||||
|
access: true,
|
||||||
|
noValidatePrivilege: true,
|
||||||
|
permissionType: ROUTER_PERMISSION_TYPE.NO_VALID.value
|
||||||
|
},
|
||||||
|
component: () => import('@/views/error/404.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '*',
|
||||||
|
name: 'http://localhost:8080/#employee/role-employee-manage',
|
||||||
|
meta: {
|
||||||
|
hideInMenu: true,
|
||||||
|
access: true,
|
||||||
|
noValidatePrivilege: true,
|
||||||
|
permissionType: ROUTER_PERMISSION_TYPE.NO_VALID.value
|
||||||
|
},
|
||||||
|
component: () => import('@/views/error/404.vue')
|
||||||
|
}
|
||||||
|
];
|
25
smart-admin-h5/src/router/other/index.js
Normal file
25
smart-admin-h5/src/router/other/index.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* 其他路由
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { user } from './user';
|
||||||
|
import { ROUTER_PERMISSION_TYPE } from '@/router/router-const';
|
||||||
|
import { develop } from '@/router/other/develop';
|
||||||
|
import { school } from '@/router/other/school';
|
||||||
|
import { contactCompany } from '@/router/other/erp/contact-company';
|
||||||
|
|
||||||
|
export const otherRouter = [
|
||||||
|
{
|
||||||
|
path: '/other-main',
|
||||||
|
meta: {
|
||||||
|
keepAlive: true,
|
||||||
|
permissionType: ROUTER_PERMISSION_TYPE.NO_VALID.value
|
||||||
|
},
|
||||||
|
component: () => import('views/main/other-main'),
|
||||||
|
children: [
|
||||||
|
...user,
|
||||||
|
...develop,
|
||||||
|
...school,
|
||||||
|
...contactCompany
|
||||||
|
]
|
||||||
|
}];
|
41
smart-admin-h5/src/router/other/school.js
Normal file
41
smart-admin-h5/src/router/other/school.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { ROUTER_PERMISSION_TYPE } from '@/router/router-const';
|
||||||
|
|
||||||
|
export const school = [
|
||||||
|
{
|
||||||
|
path: '/school/detail',
|
||||||
|
name: 'SchoolDetail',
|
||||||
|
meta: {
|
||||||
|
title: '学校详情',
|
||||||
|
permissionType: ROUTER_PERMISSION_TYPE.NEED_LOGIN.value
|
||||||
|
},
|
||||||
|
component: () => import('@/views/crm/school/school-detail')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/school/track/add',
|
||||||
|
name: 'SchoolTrackAdd',
|
||||||
|
meta: {
|
||||||
|
title: '学校拜访记录添加',
|
||||||
|
permissionType: ROUTER_PERMISSION_TYPE.NEED_LOGIN.value
|
||||||
|
},
|
||||||
|
component: () => import('@/views/crm/school/add-track')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/school/track/detail',
|
||||||
|
name: 'SchoolTrackDetail',
|
||||||
|
meta: {
|
||||||
|
title: '学校拜访记录详情',
|
||||||
|
permissionType: ROUTER_PERMISSION_TYPE.NEED_LOGIN.value
|
||||||
|
},
|
||||||
|
component: () => import('@/views/crm/school/track-detail')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/school/update',
|
||||||
|
name: 'SchoolUpdate',
|
||||||
|
meta: {
|
||||||
|
title: '更新学校',
|
||||||
|
permissionType: ROUTER_PERMISSION_TYPE.NEED_LOGIN.value
|
||||||
|
},
|
||||||
|
component: () => import('@/views/crm/school/update-school')
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
15
smart-admin-h5/src/router/other/user.js
Normal file
15
smart-admin-h5/src/router/other/user.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { ROUTER_PERMISSION_TYPE } from '@/router/router-const';
|
||||||
|
|
||||||
|
export const user = [
|
||||||
|
{
|
||||||
|
path: '/user/change-password',
|
||||||
|
name: 'UserChangePassword',
|
||||||
|
meta: {
|
||||||
|
title: '修改密码',
|
||||||
|
permissionType: ROUTER_PERMISSION_TYPE.NEED_LOGIN.value
|
||||||
|
},
|
||||||
|
component: () =>
|
||||||
|
import('@/views/mine/change-password')
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
23
smart-admin-h5/src/router/router-const.js
Normal file
23
smart-admin-h5/src/router/router-const.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* 权限类型
|
||||||
|
*/
|
||||||
|
export const ROUTER_PERMISSION_TYPE = {
|
||||||
|
/**
|
||||||
|
* 不 验 证
|
||||||
|
*/
|
||||||
|
NO_VALID: {
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 需要登录
|
||||||
|
*/
|
||||||
|
NEED_LOGIN: {
|
||||||
|
value: 2
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 需要验证权限
|
||||||
|
*/
|
||||||
|
VALIDATE_PERMISSION: {
|
||||||
|
value: 3
|
||||||
|
}
|
||||||
|
};
|
24
smart-admin-h5/src/router/routers.js
Normal file
24
smart-admin-h5/src/router/routers.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { tabbarRouter } from './tabbar';
|
||||||
|
import { otherRouter } from '@/router/other';
|
||||||
|
import { error } from './other/error';
|
||||||
|
import { ROUTER_PERMISSION_TYPE } from '@/router/router-const';
|
||||||
|
|
||||||
|
// 登录模块
|
||||||
|
export const login = {
|
||||||
|
path: '/login',
|
||||||
|
name: 'Login',
|
||||||
|
meta: {
|
||||||
|
title: '登录',
|
||||||
|
keepAlive: false,
|
||||||
|
permissionType: ROUTER_PERMISSION_TYPE.NO_VALID.value
|
||||||
|
},
|
||||||
|
component: () => import('@/views/login/login.vue')
|
||||||
|
};
|
||||||
|
|
||||||
|
// 全部路由
|
||||||
|
export const routers = [
|
||||||
|
login,
|
||||||
|
...tabbarRouter,
|
||||||
|
...otherRouter,
|
||||||
|
...error
|
||||||
|
];
|
49
smart-admin-h5/src/router/tabbar/index.js
Normal file
49
smart-admin-h5/src/router/tabbar/index.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { ROUTER_PERMISSION_TYPE } from '../router-const';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主要用于 tabbar 的路由
|
||||||
|
*/
|
||||||
|
export const tabbarRouter = [
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
redirect: '/contact-company',
|
||||||
|
meta: {
|
||||||
|
title: '首页',
|
||||||
|
keepAlive: true,
|
||||||
|
permissionType: ROUTER_PERMISSION_TYPE.NEED_LOGIN.value
|
||||||
|
},
|
||||||
|
component: () => import('views/main/tabbar-main'),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/home',
|
||||||
|
name: 'Home',
|
||||||
|
meta: {
|
||||||
|
title: '首页',
|
||||||
|
keepAlive: true,
|
||||||
|
permissionType: ROUTER_PERMISSION_TYPE.NEED_LOGIN.value
|
||||||
|
},
|
||||||
|
component: () => import('@/views/home/index')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/business',
|
||||||
|
name: 'Business',
|
||||||
|
meta: {
|
||||||
|
title: '业务中心',
|
||||||
|
keepAlive: false,
|
||||||
|
permissionType: ROUTER_PERMISSION_TYPE.NEED_LOGIN.value
|
||||||
|
},
|
||||||
|
component: () => import('@/views/business/index')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/mine',
|
||||||
|
name: 'Mine',
|
||||||
|
meta: {
|
||||||
|
title: '关于我',
|
||||||
|
keepAlive: false,
|
||||||
|
permissionType: ROUTER_PERMISSION_TYPE.NEED_LOGIN.value
|
||||||
|
},
|
||||||
|
component: () => import('@/views/mine/index')
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
21
smart-admin-h5/src/store/index.js
Normal file
21
smart-admin-h5/src/store/index.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import Vue from 'vue';
|
||||||
|
import Vuex from 'vuex';
|
||||||
|
|
||||||
|
import user from './module/user';
|
||||||
|
|
||||||
|
Vue.use(Vuex);
|
||||||
|
|
||||||
|
export default new Vuex.Store({
|
||||||
|
state: {
|
||||||
|
//
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
//
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
//
|
||||||
|
},
|
||||||
|
modules: {
|
||||||
|
user
|
||||||
|
}
|
||||||
|
});
|
41
smart-admin-h5/src/store/module/user.js
Normal file
41
smart-admin-h5/src/store/module/user.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import cookie from '@/lib/cookie.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
namespaced: true,
|
||||||
|
state: {
|
||||||
|
token: cookie.getToken(),
|
||||||
|
// session 信息
|
||||||
|
sessionInfo: {},
|
||||||
|
// 是否获取了session
|
||||||
|
isHaveGotSessionInfo: false,
|
||||||
|
// 权限集合
|
||||||
|
privilegeKeySet: new Set()
|
||||||
|
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
clearSession() {
|
||||||
|
state.token = null;
|
||||||
|
state.sessionInfo = null;
|
||||||
|
state.privilegeKeySet = new Set();
|
||||||
|
},
|
||||||
|
updateSession(state, userLoginInfo) {
|
||||||
|
state.isHaveGotSessionInfo = true;
|
||||||
|
state.sessionInfo = userLoginInfo;
|
||||||
|
if (userLoginInfo.privilegeList) {
|
||||||
|
state.privilegeKeySet = new Set(userLoginInfo.privilegeList.map(e => e.key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getters: {
|
||||||
|
// 用户菜单权限
|
||||||
|
privilegeKeySet: state => state.privilegeKeySet,
|
||||||
|
isSuperMan: state => state.sessionInfo.isSuperMan,
|
||||||
|
actualName: state => state.sessionInfo.actualName,
|
||||||
|
loginUserId: state => state.sessionInfo.id
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
// 登录
|
||||||
|
handleLogin({ commit }, params) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
6
smart-admin-h5/src/themes/index.less
Normal file
6
smart-admin-h5/src/themes/index.less
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
@text-color: #323233;
|
||||||
|
@border-color: #ebedf0;
|
||||||
|
@active-color: #f2f3f5;
|
||||||
|
@background-color: #f7f8fa;
|
||||||
|
@background-color-light: #fafafa;
|
97
smart-admin-h5/src/views/bpm/index.vue
Normal file
97
smart-admin-h5/src/views/bpm/index.vue
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
<!-- home -->
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<van-nav-bar title="审批中心">
|
||||||
|
<template #right>
|
||||||
|
<van-icon name="search" size="18" style="margin-right: 20px" />
|
||||||
|
<van-icon name="filter-o" size="18" />
|
||||||
|
</template>
|
||||||
|
</van-nav-bar>
|
||||||
|
|
||||||
|
<van-tabs v-model="bpmStatusActive" sticky>
|
||||||
|
<van-tab title="标签 1">
|
||||||
|
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
|
||||||
|
<van-list
|
||||||
|
v-model="loading"
|
||||||
|
:finished="finished"
|
||||||
|
finished-text="没有更多了"
|
||||||
|
@load="onLoad"
|
||||||
|
>
|
||||||
|
|
||||||
|
<van-cell title="单元格" value="内容" size="large" label="描述信息" />
|
||||||
|
<van-cell title="单元格" value="内容" size="large" label="描述信息" />
|
||||||
|
<van-cell title="单元格" value="内容" size="large" label="描述信息" />
|
||||||
|
<van-cell title="单元格" value="内容" size="large" label="描述信息" />
|
||||||
|
|
||||||
|
</van-list>
|
||||||
|
</van-pull-refresh>
|
||||||
|
</van-tab>
|
||||||
|
<van-tab title="标签 2">内容 2</van-tab>
|
||||||
|
<van-tab title="标签 3">内容 3</van-tab>
|
||||||
|
<van-tab title="标签 4">内容 4</van-tab>
|
||||||
|
</van-tabs>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
list: ['asdasd', 'asdasd', 'asdasd'],
|
||||||
|
bpmStatusActive: 0,
|
||||||
|
finished: true,
|
||||||
|
refreshing: true,
|
||||||
|
loading: true
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
onRefresh() {
|
||||||
|
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
this.finished = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.index-container {
|
||||||
|
.warpper {
|
||||||
|
padding: 12px;
|
||||||
|
background: #fff;
|
||||||
|
|
||||||
|
.demo-home__title {
|
||||||
|
margin: 0 0 6px;
|
||||||
|
font-size: 32px;
|
||||||
|
|
||||||
|
.demo-home__title img,
|
||||||
|
.demo-home__title span {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
margin-left: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-home__desc {
|
||||||
|
margin: 0 0 20px;
|
||||||
|
color: rgba(69, 90, 100, 0.6);
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
66
smart-admin-h5/src/views/business/index.vue
Normal file
66
smart-admin-h5/src/views/business/index.vue
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<!-- home -->
|
||||||
|
<template>
|
||||||
|
<div class="index-container">
|
||||||
|
<div class="warpper">
|
||||||
|
<h2 class="demo-home__desc">
|
||||||
|
业务
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Cell } from 'vant';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
[Cell.name]: Cell
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
list: []
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.index-container {
|
||||||
|
.warpper {
|
||||||
|
padding: 12px;
|
||||||
|
background: #fff;
|
||||||
|
|
||||||
|
.demo-home__title {
|
||||||
|
margin: 0 0 6px;
|
||||||
|
font-size: 32px;
|
||||||
|
|
||||||
|
.demo-home__title img,
|
||||||
|
.demo-home__title span {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
margin-left: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-home__desc {
|
||||||
|
margin: 0 0 20px;
|
||||||
|
color: rgba(69, 90, 100, 0.6);
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
46
smart-admin-h5/src/views/develop/config.vue
Normal file
46
smart-admin-h5/src/views/develop/config.vue
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<!-- home -->
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<router-nav-bar path="/mine" title="开发专用配置" left-text="返回" left-arrow />
|
||||||
|
|
||||||
|
<van-cell center title="VConsole">
|
||||||
|
<van-switch v-model="vconsoleFlag" @change="switchVConsole" />
|
||||||
|
</van-cell>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import RouterNavBar from 'components/van-bar/RouterNavBar';
|
||||||
|
const VCONSOLE_ID = '__vconsole';
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
RouterNavBar
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
vconsole: null,
|
||||||
|
vconsoleFlag: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.checkVConsoleExist();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 检测vconsole是否存在
|
||||||
|
checkVConsoleExist() {
|
||||||
|
const vconsoleElement = document.getElementById(VCONSOLE_ID);
|
||||||
|
this.vconsoleFlag = !!vconsoleElement;
|
||||||
|
},
|
||||||
|
// 提交表单
|
||||||
|
switchVConsole(flag) {
|
||||||
|
if (flag) {
|
||||||
|
this.vconsole = new VConsole();
|
||||||
|
} else {
|
||||||
|
delete this.vconsole;
|
||||||
|
document.getElementById(VCONSOLE_ID).remove();
|
||||||
|
this.vconsole = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
23
smart-admin-h5/src/views/error/404.vue
Normal file
23
smart-admin-h5/src/views/error/404.vue
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<!-- home -->
|
||||||
|
<template>
|
||||||
|
<div class="index-container">
|
||||||
|
<h1>404!</h1>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
list: []
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {}
|
||||||
|
};
|
||||||
|
</script>
|
68
smart-admin-h5/src/views/home/index.vue
Normal file
68
smart-admin-h5/src/views/home/index.vue
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<!-- home -->
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div style="background-color: #1989fa;height: ">
|
||||||
|
<h4>
|
||||||
|
<center>首页</center>
|
||||||
|
</h4>
|
||||||
|
<van-row gutter="20">
|
||||||
|
<van-col span="12">span: 8</van-col>
|
||||||
|
<van-col span="12">span: 8</van-col>
|
||||||
|
</van-row>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
list: []
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.index-container {
|
||||||
|
.warpper {
|
||||||
|
padding: 12px;
|
||||||
|
background: #fff;
|
||||||
|
|
||||||
|
.demo-home__title {
|
||||||
|
margin: 0 0 6px;
|
||||||
|
font-size: 32px;
|
||||||
|
|
||||||
|
.demo-home__title img,
|
||||||
|
.demo-home__title span {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
margin-left: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-home__desc {
|
||||||
|
margin: 0 0 20px;
|
||||||
|
color: rgba(69, 90, 100, 0.6);
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
80
smart-admin-h5/src/views/login/login.vue
Normal file
80
smart-admin-h5/src/views/login/login.vue
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
<!-- home -->
|
||||||
|
<template>
|
||||||
|
<div style="padding: 0.4rem">
|
||||||
|
<h1 align="center">Smart-Admin-H5</h1>
|
||||||
|
<van-form @submit="onSubmit">
|
||||||
|
<van-field
|
||||||
|
v-model="formData.loginName"
|
||||||
|
name="用户名"
|
||||||
|
label="用户名"
|
||||||
|
placeholder="用户名"
|
||||||
|
:rules="[{ required: true, message: '请填写用户名' }]"
|
||||||
|
/>
|
||||||
|
<van-field
|
||||||
|
v-model="formData.loginPwd"
|
||||||
|
type="password"
|
||||||
|
name="密码"
|
||||||
|
label="密码"
|
||||||
|
placeholder="密码"
|
||||||
|
:rules="[{ required: true, message: '请填写密码' }]"
|
||||||
|
/>
|
||||||
|
<div style="margin: 16px;">
|
||||||
|
<van-button block type="info" native-type="submit">
|
||||||
|
登录
|
||||||
|
</van-button>
|
||||||
|
</div>
|
||||||
|
</van-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { loginApi } from '@/api/login';
|
||||||
|
import cookie from '@/lib/cookie';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
formData: {
|
||||||
|
loginName: '',
|
||||||
|
loginPwd: ''
|
||||||
|
},
|
||||||
|
codeUrl: ''
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 获取验证码
|
||||||
|
async getVerificationCode() {
|
||||||
|
try {
|
||||||
|
const res = await loginApi.getVerificationCode();
|
||||||
|
const data = res.data;
|
||||||
|
this.formData.codeUuid = data.uuid;
|
||||||
|
this.codeUrl = data.code;
|
||||||
|
this.formData.code = '';
|
||||||
|
console.log(this.codeUrl);
|
||||||
|
} catch (e) {
|
||||||
|
this.$smartSentry.captureException(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 提交表单
|
||||||
|
async onSubmit() {
|
||||||
|
this.$smart.loading();
|
||||||
|
try {
|
||||||
|
const res = await loginApi.login(this.formData);
|
||||||
|
const loginInfo = res.data;
|
||||||
|
this.$store.commit('user/updateSession', loginInfo);
|
||||||
|
cookie.setToken(loginInfo.xaccessToken);
|
||||||
|
this.$toast.success('登录成功');
|
||||||
|
this.$router.replace('/bpm');
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
this.$smartSentry.captureException(e);
|
||||||
|
await this.getVerificationCode();
|
||||||
|
} finally {
|
||||||
|
this.$smart.loadingClear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
25
smart-admin-h5/src/views/main/main-mixin.js
Normal file
25
smart-admin-h5/src/views/main/main-mixin.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import cookie from '@/lib/cookie';
|
||||||
|
import { userApi } from 'api/user';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 此 mixin为登录以后的页面用的,因为所有的有效路由(排除登录、注册、404,500 这个几个特殊页面)都会走 other-main 或者 tabber-main两个父级组件。
|
||||||
|
* 所以对于一些session的信息获取只能放到这个两个main组件上,故此mixin只用于两个main组件,起到全局的作用
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
created: function() {
|
||||||
|
const token = cookie.getToken();
|
||||||
|
// 如果登录过,获取token
|
||||||
|
if (token && !this.$store.state.user.isHaveGotSessionInfo) {
|
||||||
|
(async() => {
|
||||||
|
try {
|
||||||
|
console.debug(' request session info ');
|
||||||
|
const res = await userApi.getSession();
|
||||||
|
const loginInfo = res.data;
|
||||||
|
this.$store.commit('user/updateSession', loginInfo);
|
||||||
|
} catch (e) {
|
||||||
|
this.$smartSentry.captureException(e);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
31
smart-admin-h5/src/views/main/other-main.vue
Normal file
31
smart-admin-h5/src/views/main/other-main.vue
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<!---------------- 頁面内容 begin ---------------->
|
||||||
|
<div class="main-content">
|
||||||
|
<keep-alive>
|
||||||
|
<router-view v-if="$route.meta.keepAlive" />
|
||||||
|
</keep-alive>
|
||||||
|
<router-view v-if="!$route.meta.keepAlive" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
import mainMixin from './main-mixin';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'OtherMain',
|
||||||
|
mixins: [mainMixin],
|
||||||
|
data() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
},
|
||||||
|
computed: {},
|
||||||
|
methods: {}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="less" scoped>
|
||||||
|
</style>
|
96
smart-admin-h5/src/views/main/tabbar-main.vue
Normal file
96
smart-admin-h5/src/views/main/tabbar-main.vue
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<!---------------- 頁面内容 begin ---------------->
|
||||||
|
<div class="main-content">
|
||||||
|
<keep-alive>
|
||||||
|
<router-view v-if="$route.meta.keepAlive" />
|
||||||
|
</keep-alive>
|
||||||
|
<router-view v-if="!$route.meta.keepAlive" />
|
||||||
|
</div>
|
||||||
|
<!---------------- 頁面内容 end ---------------->
|
||||||
|
|
||||||
|
<!---------------- 底部 tabbar begin ---------------->
|
||||||
|
<div class="main-footer">
|
||||||
|
<van-tabbar
|
||||||
|
fixed
|
||||||
|
route
|
||||||
|
v-model="active"
|
||||||
|
>
|
||||||
|
<van-tabbar-item
|
||||||
|
v-for="(item, index) in tabbar"
|
||||||
|
:to="item.to"
|
||||||
|
:icon="item.icon"
|
||||||
|
:name="item.name"
|
||||||
|
:key="index">
|
||||||
|
{{ item.title }}
|
||||||
|
</van-tabbar-item>
|
||||||
|
</van-tabbar>
|
||||||
|
</div>
|
||||||
|
<!---------------- 底部 tabbar end ---------------->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
import mainMixin from 'views/main/main-mixin';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'TabbarMain',
|
||||||
|
mixins: [mainMixin],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
active: 'ContactCompany',
|
||||||
|
tabbar: [
|
||||||
|
// {
|
||||||
|
// name: 'Home',
|
||||||
|
// title: '首页',
|
||||||
|
// icon: 'wap-home-o',
|
||||||
|
// to: '/home'
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: 'Business',
|
||||||
|
// title: '业务中心',
|
||||||
|
// icon: 'apps-o',
|
||||||
|
// to: '/business'
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
name: 'ContactCompany',
|
||||||
|
title: '往来机构',
|
||||||
|
icon: 'user-o',
|
||||||
|
badge: 0,
|
||||||
|
to: '/contact-company'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Mine',
|
||||||
|
title: '我的',
|
||||||
|
icon: 'user-o',
|
||||||
|
to: '/mine'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
// 通过路由跳转绑定Tabbar的选中
|
||||||
|
this.updateTabbarSelected(this.$route.name);
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
// 监听路由变化,保证路由跳转Tabbar选中正常
|
||||||
|
$route: {
|
||||||
|
handler(val, oldval) {
|
||||||
|
// this.updateTabbarSelected(val.name)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deep: true
|
||||||
|
},
|
||||||
|
computed: {},
|
||||||
|
methods: {
|
||||||
|
updateTabbarSelected(item) {
|
||||||
|
console.log(item, 12222);
|
||||||
|
this.active = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="less" scoped>
|
||||||
|
</style>
|
96
smart-admin-h5/src/views/mine/change-password.vue
Normal file
96
smart-admin-h5/src/views/mine/change-password.vue
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
<!-- home -->
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<router-nav-bar path="/mine" title="修改密码" left-text="返回" left-arrow />
|
||||||
|
|
||||||
|
<van-form @submit="onSubmit">
|
||||||
|
<van-field
|
||||||
|
v-model="formData.loginName"
|
||||||
|
name="旧密码"
|
||||||
|
label="旧密码"
|
||||||
|
placeholder="旧密码"
|
||||||
|
:rules="[{ required: true, message: '请填写旧密码' }]"
|
||||||
|
/>
|
||||||
|
<van-field
|
||||||
|
v-model="formData.loginPwd"
|
||||||
|
type="password"
|
||||||
|
name="新密码"
|
||||||
|
label="新密码"
|
||||||
|
placeholder="新密码"
|
||||||
|
:rules="[{ required: true, message: '请填写新密码' }]"
|
||||||
|
/>
|
||||||
|
<van-field
|
||||||
|
style="width: 60%;float:left"
|
||||||
|
v-model="formData.code"
|
||||||
|
name="新密码"
|
||||||
|
label="新密码"
|
||||||
|
placeholder="新密码"
|
||||||
|
:rules="[{ required: true, message: '请填写新密码' }]"
|
||||||
|
/>
|
||||||
|
<div style="margin: 16px;">
|
||||||
|
<van-button block type="info" native-type="submit" size="small">
|
||||||
|
提交
|
||||||
|
</van-button>
|
||||||
|
</div>
|
||||||
|
</van-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { loginApi } from '@/api/login';
|
||||||
|
import cookie from '@/lib/cookie';
|
||||||
|
import RouterNavBar from 'components/van-bar/RouterNavBar';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
RouterNavBar
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
formData: {
|
||||||
|
loginName: '',
|
||||||
|
loginPwd: '',
|
||||||
|
code: '',
|
||||||
|
codeUuid: ''
|
||||||
|
},
|
||||||
|
codeUrl: ''
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getVerificationCode();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 获取验证码
|
||||||
|
async getVerificationCode() {
|
||||||
|
try {
|
||||||
|
const res = await loginApi.getVerificationCode();
|
||||||
|
const data = res.data;
|
||||||
|
this.formData.codeUuid = data.uuid;
|
||||||
|
this.codeUrl = data.code;
|
||||||
|
this.formData.code = '';
|
||||||
|
console.log(this.codeUrl);
|
||||||
|
} catch (e) {
|
||||||
|
this.$smartSentry.captureException(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 提交表单
|
||||||
|
async onSubmit() {
|
||||||
|
this.$smart.loading();
|
||||||
|
try {
|
||||||
|
const res = await loginApi.login(this.formData);
|
||||||
|
const loginInfo = res.data;
|
||||||
|
this.$store.commit('user/updateSession', loginInfo);
|
||||||
|
cookie.setToken(loginInfo.xaccessToken);
|
||||||
|
this.$toast.success('登录成功');
|
||||||
|
this.$router.replace('/home');
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
this.$smartSentry.captureException(e);
|
||||||
|
await this.getVerificationCode();
|
||||||
|
} finally {
|
||||||
|
this.$smart.loadingClear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
73
smart-admin-h5/src/views/mine/index.vue
Normal file
73
smart-admin-h5/src/views/mine/index.vue
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<!-- home -->
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<van-nav-bar title="个人中心"/>
|
||||||
|
|
||||||
|
<van-grid :column-num="1">
|
||||||
|
<van-grid-item icon="home-o" :text="actualName"/>
|
||||||
|
</van-grid>
|
||||||
|
|
||||||
|
<van-cell-group>
|
||||||
|
<!-- <van-cell icon="user-o" title="订单" is-link />-->
|
||||||
|
<!-- <van-cell icon="location-o" title="设置" is-link />-->
|
||||||
|
<!-- <van-cell icon="location-o" to="/user/change-password" title="修改密码" is-link />-->
|
||||||
|
<van-cell icon="bulb-o" title="更新权限" @click="updatePrivilege" is-link/>
|
||||||
|
<van-cell icon="apps-o" title="开发专用" is-link to="/develop/config"/>
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<div style="margin: 16px;">
|
||||||
|
<van-button block @click="logout" type="warning" size="small">
|
||||||
|
退出登录
|
||||||
|
</van-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { loginApi } from 'api/login';
|
||||||
|
import cookie from '@/lib/cookie';
|
||||||
|
import { userApi } from 'api/user';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
actualName: null
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.actualName = '你好, ' + this.$store.getters['user/actualName'];
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
async updatePrivilege() {
|
||||||
|
this.$smart.loading();
|
||||||
|
try {
|
||||||
|
const res = await userApi.getSession();
|
||||||
|
const loginInfo = res.data;
|
||||||
|
this.$store.commit('user/updateSession', loginInfo);
|
||||||
|
this.$toast('已成功更新权限!');
|
||||||
|
} catch (e) {
|
||||||
|
this.$smartSentry.captureException(e);
|
||||||
|
} finally {
|
||||||
|
this.$smart.loadingClear();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async logout() {
|
||||||
|
this.$smart.loading();
|
||||||
|
try {
|
||||||
|
await loginApi.logout(cookie.getToken());
|
||||||
|
} catch (e) {
|
||||||
|
this.$smartSentry.captureException(e);
|
||||||
|
} finally {
|
||||||
|
cookie.clearToken();
|
||||||
|
this.$smart.loadingClear();
|
||||||
|
this.$router.replace('/login');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
192
smart-admin-h5/vue.config.js
Normal file
192
smart-admin-h5/vue.config.js
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
const path = require('path');
|
||||||
|
const CompressionWebpackPlugin = require('compression-webpack-plugin');
|
||||||
|
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin');
|
||||||
|
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
|
||||||
|
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');
|
||||||
|
const SentryPlugin = require('@sentry/webpack-plugin');
|
||||||
|
const resolve = dir => path.join(__dirname, dir);
|
||||||
|
// 项目配置
|
||||||
|
const projectConfig = require('./src/config/index.js');
|
||||||
|
|
||||||
|
// 生产环境,测试和正式
|
||||||
|
const isProductionEnv = ['production'].includes(process.env.NODE_ENV);
|
||||||
|
const isProductionAppEnv = ['prod', 'pre'].includes(process.env.VUE_APP_ENV);
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
publicPath: projectConfig.publicPath,
|
||||||
|
// 生产环境构建文件的目录
|
||||||
|
outputDir: 'dist',
|
||||||
|
// outputDir的静态资源(js、css、img、fonts)目录
|
||||||
|
assetsDir: 'static',
|
||||||
|
// eslint检测 按需开启
|
||||||
|
lintOnSave: !isProductionEnv,
|
||||||
|
// 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
|
||||||
|
productionSourceMap: false,
|
||||||
|
devServer: {
|
||||||
|
// 设置主机地址
|
||||||
|
host: '0.0.0.0',
|
||||||
|
// 设置默认端口
|
||||||
|
port: 8090,
|
||||||
|
// 禁用host验证
|
||||||
|
disableHostCheck: true,
|
||||||
|
// 启动后打开浏览器
|
||||||
|
open: true,
|
||||||
|
overlay: {
|
||||||
|
// 当出现编译器错误或警告时,在浏览器中显示全屏覆盖层
|
||||||
|
warnings: false,
|
||||||
|
errors: true
|
||||||
|
}
|
||||||
|
// proxy: {
|
||||||
|
// //配置跨域
|
||||||
|
// '/api': {
|
||||||
|
// // 接口前缀
|
||||||
|
// target: "https://sit.smart-h5.1024lab.net/api",
|
||||||
|
// // ws:true,
|
||||||
|
// changOrigin:true,
|
||||||
|
// // 改写规则,把/api 替换为/
|
||||||
|
// pathRewrite:{
|
||||||
|
// '^/api':'/'
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
css: {
|
||||||
|
// 是否将组件中的 CSS 提取至一个独立的 CSS 文件中 (而不是动态注入到 JavaScript 中的 inline 代码)。
|
||||||
|
extract: isProductionEnv,
|
||||||
|
sourceMap: false,
|
||||||
|
modules: false
|
||||||
|
},
|
||||||
|
configureWebpack: config => {
|
||||||
|
config.name = projectConfig.title;
|
||||||
|
},
|
||||||
|
|
||||||
|
chainWebpack: config => {
|
||||||
|
// 移除资源预加载(路由懒加载才能正常使用)
|
||||||
|
config.plugins.delete('preload');
|
||||||
|
config.plugins.delete('prefetch');
|
||||||
|
|
||||||
|
// 别名 alias
|
||||||
|
config.resolve.alias
|
||||||
|
.set('@', resolve('src'))
|
||||||
|
.set('assets', resolve('src/assets'))
|
||||||
|
.set('api', resolve('src/api'))
|
||||||
|
.set('views', resolve('src/views'))
|
||||||
|
.set('components', resolve('src/components'));
|
||||||
|
|
||||||
|
// 应用名字
|
||||||
|
config.plugin('html').tap(args => {
|
||||||
|
args[0].title = projectConfig.title;
|
||||||
|
return args;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 设置保留空格
|
||||||
|
config.module
|
||||||
|
.rule('vue')
|
||||||
|
.use('vue-loader')
|
||||||
|
.loader('vue-loader')
|
||||||
|
.tap(options => {
|
||||||
|
options.compilerOptions.preserveWhitespace = true;
|
||||||
|
return options;
|
||||||
|
})
|
||||||
|
.end();
|
||||||
|
|
||||||
|
// ==================== 生产环境配置 begin ====================
|
||||||
|
if (isProductionEnv) {
|
||||||
|
// 打包分析
|
||||||
|
config.plugin('webpack-report').use(BundleAnalyzerPlugin, [
|
||||||
|
{
|
||||||
|
analyzerMode: 'static'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
// 不显示源码
|
||||||
|
config.devtool('cheap-source-map');
|
||||||
|
|
||||||
|
// cdn
|
||||||
|
config.plugin('html').tap(args => {
|
||||||
|
args[0].cdn = projectConfig.cdn.cdnResource;
|
||||||
|
// 压缩html中的css
|
||||||
|
args[0].minify.minifyCSS = true;
|
||||||
|
return args;
|
||||||
|
});
|
||||||
|
// 指定资源加载cdn
|
||||||
|
config.externals(projectConfig.cdn.externals);
|
||||||
|
|
||||||
|
// 开启gzip , Nginx上也需要配置gzip才会生效
|
||||||
|
config
|
||||||
|
.plugin('compression')
|
||||||
|
.use(CompressionWebpackPlugin)
|
||||||
|
.tap(() => [
|
||||||
|
{
|
||||||
|
// 压缩 js 与 css
|
||||||
|
test: new RegExp(
|
||||||
|
'\\.(js|css)$'
|
||||||
|
),
|
||||||
|
// 资源文件大于10240B=10kB时会被压缩
|
||||||
|
threshold: 10240,
|
||||||
|
// 最小压缩比达到0.8时才会被压缩
|
||||||
|
minRatio: 0.8
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
// sentry
|
||||||
|
if (isProductionAppEnv) {
|
||||||
|
config.plugin('sentry').use(SentryPlugin, [{
|
||||||
|
ignore: ['node_modules'],
|
||||||
|
include: './dist', // 上传dist文件的js
|
||||||
|
configFile: './.sentryclirc' // 配置文件地址
|
||||||
|
}]);
|
||||||
|
}
|
||||||
|
|
||||||
|
config.optimization.minimizer = [
|
||||||
|
new UglifyjsWebpackPlugin({
|
||||||
|
// 生产环境推荐关闭 sourcemap 防止源码泄漏
|
||||||
|
// 服务端通过前端发送的行列,根据 sourcemap 转为源文件位置
|
||||||
|
sourceMap: false,
|
||||||
|
uglifyOptions: {
|
||||||
|
warnings: false,
|
||||||
|
compress: {
|
||||||
|
drop_console: true,
|
||||||
|
drop_debugger: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
config
|
||||||
|
.plugin('ScriptExtHtmlWebpackPlugin')
|
||||||
|
.after('html')
|
||||||
|
.use(ScriptExtHtmlWebpackPlugin, [
|
||||||
|
{
|
||||||
|
// 将 runtime 作为内联引入不单独存在
|
||||||
|
inline: /runtime\..*\.js$/
|
||||||
|
}
|
||||||
|
])
|
||||||
|
.end();
|
||||||
|
|
||||||
|
config.optimization.splitChunks({
|
||||||
|
chunks: 'all',
|
||||||
|
cacheGroups: {
|
||||||
|
commons: {
|
||||||
|
name: 'chunk-commons',
|
||||||
|
test: resolve('src/components'),
|
||||||
|
minChunks: 3, // 模块至少使用次数
|
||||||
|
priority: 5,
|
||||||
|
reuseExistingChunk: true // 模块嵌套引入时,判断是否复用已经被打包的模块
|
||||||
|
},
|
||||||
|
node_vendors: {
|
||||||
|
name: 'chunk-libs',
|
||||||
|
chunks: 'initial',
|
||||||
|
test: /[\\/]node_modules[\\/]/,
|
||||||
|
priority: 10
|
||||||
|
},
|
||||||
|
vantUI: {
|
||||||
|
name: 'chunk-vantUI',
|
||||||
|
priority: 20,
|
||||||
|
test: /[\\/]node_modules[\\/]_?vant(.*)/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// ==================== 生产环境配置 end ====================
|
||||||
|
}
|
||||||
|
};
|
@ -1,19 +1,13 @@
|
|||||||
1 更新密码
|
1 超管默认账号
|
||||||
EmployeeController.updatePwd
|
|
||||||
|
|
||||||
2 更新功能点
|
|
||||||
PrivilegeController functionSaveOrUpdate和menuBatchSave、batchSaveFunctionList
|
|
||||||
|
|
||||||
3 超管默认账号
|
|
||||||
sa/123456
|
sa/123456
|
||||||
|
|
||||||
4 执行脚本:
|
2 执行脚本:
|
||||||
先执行:src/main/resources/sql/smart-admin.sql
|
先执行:src/main/resources/sql/smart-admin.sql
|
||||||
再执行:src/main/resources/sql/quartz_mysql_2.3.0.sql
|
再执行:src/main/resources/sql/quartz_mysql_2.3.0.sql
|
||||||
|
|
||||||
5 除dev之外文件
|
3 除dev之外文件
|
||||||
|
|
||||||
6 刷新页面,获取权限是否走缓存
|
4 刷新页面,获取权限是否走缓存
|
||||||
LoginService.getSession
|
LoginService.getSession
|
||||||
|
|
||||||
7 test类中去掉代码生成run
|
5 test类中去掉代码生成run
|
||||||
|
@ -2,6 +2,7 @@ package net.lab1024.smartadmin.common.anno;
|
|||||||
|
|
||||||
import net.lab1024.smartadmin.module.system.datascope.constant.DataScopeTypeEnum;
|
import net.lab1024.smartadmin.module.system.datascope.constant.DataScopeTypeEnum;
|
||||||
import net.lab1024.smartadmin.module.system.datascope.constant.DataScopeWhereInTypeEnum;
|
import net.lab1024.smartadmin.module.system.datascope.constant.DataScopeWhereInTypeEnum;
|
||||||
|
import net.lab1024.smartadmin.module.system.datascope.strategy.DataScopePowerStrategy;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
@ -27,11 +28,22 @@ public @interface DataScope {
|
|||||||
DataScopeWhereInTypeEnum whereInType() default DataScopeWhereInTypeEnum.EMPLOYEE;
|
DataScopeWhereInTypeEnum whereInType() default DataScopeWhereInTypeEnum.EMPLOYEE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* DataScopeWhereInTypeEnum.CUSTOM_STRATEGY类型 才可使用joinSqlImplClazz属性
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Class<? extends DataScopePowerStrategy> joinSqlImplClazz() default DataScopePowerStrategy.class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
* 第几个where 条件 从0开始
|
* 第几个where 条件 从0开始
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
int whereIndex() default 0;
|
int whereIndex() default 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DataScopeWhereInTypeEnum为CUSTOM_STRATEGY类型时,此属性无效
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
String joinSql() default "";
|
String joinSql() default "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import org.springframework.context.EnvironmentAware;
|
|||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Profile;
|
import org.springframework.context.annotation.Profile;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import springfox.documentation.RequestHandler;
|
import springfox.documentation.RequestHandler;
|
||||||
import springfox.documentation.builders.ApiInfoBuilder;
|
import springfox.documentation.builders.ApiInfoBuilder;
|
||||||
@ -194,7 +195,11 @@ public class SmartSwaggerDynamicGroupConfig implements EnvironmentAware, BeanDef
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
groupIndex++;
|
groupIndex++;
|
||||||
return Predicates.and(RequestHandlerSelectors.withClassAnnotation(RestController.class), methodPredicate);
|
return Predicates.or(
|
||||||
|
Predicates.and(RequestHandlerSelectors.withClassAnnotation(RestController.class),methodPredicate),
|
||||||
|
Predicates.and(
|
||||||
|
RequestHandlerSelectors.withMethodAnnotation(ResponseBody.class),methodPredicate)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ApiInfo serviceApiInfo() {
|
private ApiInfo serviceApiInfo() {
|
||||||
|
@ -41,7 +41,7 @@ public interface NoticeDao extends BaseMapper<NoticeEntity> {
|
|||||||
* @param employeeId
|
* @param employeeId
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@DataScope(joinSql = "n.create_user_department_id in (#departmentIds)", whereInType = DataScopeWhereInTypeEnum.DEPARTMENT)
|
@DataScope(joinSql = "e.department_id in (#departmentIds)", whereInType = DataScopeWhereInTypeEnum.DEPARTMENT)
|
||||||
List<NoticeVO> queryUnreadByPage(Page page, @Param("employeeId") Long employeeId, @Param("sendStatus") Integer sendStatus);
|
List<NoticeVO> queryUnreadByPage(Page page, @Param("employeeId") Long employeeId, @Param("sendStatus") Integer sendStatus);
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
package net.lab1024.smartadmin.module.support.quartz.service;
|
package net.lab1024.smartadmin.module.support.quartz.service;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.lab1024.smartadmin.common.domain.ITask;
|
||||||
import net.lab1024.smartadmin.module.support.quartz.constant.QuartzConst;
|
import net.lab1024.smartadmin.module.support.quartz.constant.QuartzConst;
|
||||||
import net.lab1024.smartadmin.module.support.quartz.constant.TaskResultEnum;
|
import net.lab1024.smartadmin.module.support.quartz.constant.TaskResultEnum;
|
||||||
import net.lab1024.smartadmin.module.support.quartz.domain.entity.QuartzTaskEntity;
|
import net.lab1024.smartadmin.module.support.quartz.domain.entity.QuartzTaskEntity;
|
||||||
import net.lab1024.smartadmin.module.support.quartz.domain.entity.QuartzTaskLogEntity;
|
import net.lab1024.smartadmin.module.support.quartz.domain.entity.QuartzTaskLogEntity;
|
||||||
import net.lab1024.smartadmin.common.domain.ITask;
|
|
||||||
import net.lab1024.smartadmin.third.SmartApplicationContext;
|
import net.lab1024.smartadmin.third.SmartApplicationContext;
|
||||||
import net.lab1024.smartadmin.util.SmartIPUtil;
|
import net.lab1024.smartadmin.util.SmartIPUtil;
|
||||||
import net.lab1024.smartadmin.util.SmartQuartzUtil;
|
import net.lab1024.smartadmin.util.SmartQuartzUtil;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.quartz.JobDetail;
|
import org.quartz.JobDetail;
|
||||||
import org.quartz.JobExecutionContext;
|
import org.quartz.JobExecutionContext;
|
||||||
import org.quartz.JobExecutionException;
|
import org.quartz.JobExecutionException;
|
||||||
@ -17,7 +17,6 @@ import org.springframework.scheduling.quartz.QuartzJobBean;
|
|||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,7 +47,11 @@ public class QuartzTask extends QuartzJobBean {
|
|||||||
QuartzTaskLogEntity taskLogEntity = new QuartzTaskLogEntity();
|
QuartzTaskLogEntity taskLogEntity = new QuartzTaskLogEntity();
|
||||||
taskLogEntity.setTaskId(taskId);
|
taskLogEntity.setTaskId(taskId);
|
||||||
taskLogEntity.setIpAddress(SmartIPUtil.getLocalHostIP());
|
taskLogEntity.setIpAddress(SmartIPUtil.getLocalHostIP());
|
||||||
taskLogEntity.setTaskName(quartzTaskEntity.getTaskName());
|
try {
|
||||||
|
taskLogEntity.setTaskName(quartzTaskEntity.getTaskName());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
String paramsStr = null;
|
String paramsStr = null;
|
||||||
if (params != null) {
|
if (params != null) {
|
||||||
paramsStr = params.toString();
|
paramsStr = params.toString();
|
||||||
|
@ -130,7 +130,12 @@ public class QuartzTaskService {
|
|||||||
taskEntity.setTaskStatus(updateEntity.getTaskStatus());
|
taskEntity.setTaskStatus(updateEntity.getTaskStatus());
|
||||||
taskEntity.setUpdateTime(new Date());
|
taskEntity.setUpdateTime(new Date());
|
||||||
quartzTaskDao.updateById(taskEntity);
|
quartzTaskDao.updateById(taskEntity);
|
||||||
this.updateQuartzTask(scheduler, taskEntity);
|
if(this.checkExist(taskEntity.getId())){
|
||||||
|
this.updateQuartzTask(scheduler, taskEntity);
|
||||||
|
}else{
|
||||||
|
this.createQuartzTask(scheduler,taskEntity);
|
||||||
|
}
|
||||||
|
|
||||||
return ResponseDTO.succ();
|
return ResponseDTO.succ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,7 +170,7 @@ public class QuartzTaskService {
|
|||||||
}
|
}
|
||||||
quartzTaskEntity.setTaskStatus(TaskStatusEnum.PAUSE.getStatus());
|
quartzTaskEntity.setTaskStatus(TaskStatusEnum.PAUSE.getStatus());
|
||||||
quartzTaskDao.updateById(quartzTaskEntity);
|
quartzTaskDao.updateById(quartzTaskEntity);
|
||||||
this.pauseQuartzTask(scheduler, taskId);
|
this.pauseQuartzTask(scheduler, quartzTaskEntity);
|
||||||
return ResponseDTO.succ();
|
return ResponseDTO.succ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,7 +189,7 @@ public class QuartzTaskService {
|
|||||||
}
|
}
|
||||||
quartzTaskEntity.setTaskStatus(TaskStatusEnum.NORMAL.getStatus());
|
quartzTaskEntity.setTaskStatus(TaskStatusEnum.NORMAL.getStatus());
|
||||||
quartzTaskDao.updateById(quartzTaskEntity);
|
quartzTaskDao.updateById(quartzTaskEntity);
|
||||||
this.resumeQuartzTask(scheduler, taskId);
|
this.resumeQuartzTask(scheduler, quartzTaskEntity);
|
||||||
return ResponseDTO.succ();
|
return ResponseDTO.succ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,6 +238,10 @@ public class QuartzTaskService {
|
|||||||
|
|
||||||
jobDetail.getJobDataMap().put(QuartzConst.QUARTZ_PARAMS_KEY, taskEntity.getTaskParams());
|
jobDetail.getJobDataMap().put(QuartzConst.QUARTZ_PARAMS_KEY, taskEntity.getTaskParams());
|
||||||
scheduler.scheduleJob(jobDetail, trigger);
|
scheduler.scheduleJob(jobDetail, trigger);
|
||||||
|
//如果任务是暂停状态,则暂停任务
|
||||||
|
if (TaskStatusEnum.PAUSE.getStatus().equals(taskEntity.getTaskStatus())) {
|
||||||
|
this.pauseQuartzTask(scheduler, taskEntity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -256,7 +265,7 @@ public class QuartzTaskService {
|
|||||||
scheduler.rescheduleJob(triggerKey, trigger);
|
scheduler.rescheduleJob(triggerKey, trigger);
|
||||||
//如果更新之前任务是暂停状态,此时再次暂停任务
|
//如果更新之前任务是暂停状态,此时再次暂停任务
|
||||||
if (TaskStatusEnum.PAUSE.getStatus().equals(taskEntity.getTaskStatus())) {
|
if (TaskStatusEnum.PAUSE.getStatus().equals(taskEntity.getTaskStatus())) {
|
||||||
this.pauseQuartzTask(scheduler, Long.valueOf(taskEntity.getId()));
|
this.pauseQuartzTask(scheduler, taskEntity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,6 +285,11 @@ public class QuartzTaskService {
|
|||||||
JobDataMap dataMap = new JobDataMap();
|
JobDataMap dataMap = new JobDataMap();
|
||||||
dataMap.put(QuartzConst.QUARTZ_PARAMS_KEY, taskEntity.getTaskParams());
|
dataMap.put(QuartzConst.QUARTZ_PARAMS_KEY, taskEntity.getTaskParams());
|
||||||
JobKey jobKey = SmartQuartzUtil.getJobKey(taskEntity.getId());
|
JobKey jobKey = SmartQuartzUtil.getJobKey(taskEntity.getId());
|
||||||
|
if(!scheduler.checkExists(jobKey)){
|
||||||
|
this.createQuartzTask(scheduler,taskEntity);
|
||||||
|
scheduler.triggerJob(jobKey, dataMap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
scheduler.triggerJob(jobKey, dataMap);
|
scheduler.triggerJob(jobKey, dataMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,11 +297,16 @@ public class QuartzTaskService {
|
|||||||
* 暂停任务
|
* 暂停任务
|
||||||
*
|
*
|
||||||
* @param scheduler
|
* @param scheduler
|
||||||
* @param taskId
|
* @param quartzTaskEntity
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
private void pauseQuartzTask(Scheduler scheduler, Long taskId) throws Exception {
|
private void pauseQuartzTask(Scheduler scheduler, QuartzTaskEntity quartzTaskEntity) throws Exception {
|
||||||
JobKey jobKey = SmartQuartzUtil.getJobKey(taskId);
|
JobKey jobKey = SmartQuartzUtil.getJobKey(quartzTaskEntity.getId());
|
||||||
|
if(!scheduler.checkExists(jobKey)){
|
||||||
|
this.createQuartzTask(scheduler,quartzTaskEntity);
|
||||||
|
scheduler.pauseJob(jobKey);
|
||||||
|
return;
|
||||||
|
}
|
||||||
scheduler.pauseJob(jobKey);
|
scheduler.pauseJob(jobKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,11 +314,15 @@ public class QuartzTaskService {
|
|||||||
* 恢复任务
|
* 恢复任务
|
||||||
*
|
*
|
||||||
* @param scheduler
|
* @param scheduler
|
||||||
* @param taskId
|
* @param quartzTaskEntity
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
private void resumeQuartzTask(Scheduler scheduler, Long taskId) throws Exception {
|
private void resumeQuartzTask(Scheduler scheduler, QuartzTaskEntity quartzTaskEntity) throws Exception {
|
||||||
JobKey jobKey = SmartQuartzUtil.getJobKey(taskId);
|
JobKey jobKey = SmartQuartzUtil.getJobKey(quartzTaskEntity.getId());
|
||||||
|
if(!scheduler.checkExists(jobKey)){
|
||||||
|
this.createQuartzTask(scheduler,quartzTaskEntity);
|
||||||
|
return;
|
||||||
|
}
|
||||||
scheduler.resumeJob(jobKey);
|
scheduler.resumeJob(jobKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,6 +335,15 @@ public class QuartzTaskService {
|
|||||||
*/
|
*/
|
||||||
private void deleteQuartzTask(Scheduler scheduler, Long taskId) throws Exception {
|
private void deleteQuartzTask(Scheduler scheduler, Long taskId) throws Exception {
|
||||||
JobKey jobKey = SmartQuartzUtil.getJobKey(taskId);
|
JobKey jobKey = SmartQuartzUtil.getJobKey(taskId);
|
||||||
|
if(!scheduler.checkExists(jobKey)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
scheduler.deleteJob(jobKey);
|
scheduler.deleteJob(jobKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Boolean checkExist(Long taskId) throws Exception{
|
||||||
|
JobKey jobKey = SmartQuartzUtil.getJobKey(taskId);
|
||||||
|
return scheduler.checkExists(jobKey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.lab1024.smartadmin.module.support.quartz.task.test;
|
package net.lab1024.smartadmin.module.support.quartz.task.test;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.lab1024.smartadmin.common.domain.ITask;
|
import net.lab1024.smartadmin.common.domain.ITask;
|
||||||
import net.lab1024.smartadmin.util.SmartDateUtil;
|
import net.lab1024.smartadmin.util.SmartDateUtil;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@ -16,11 +17,12 @@ import java.util.Date;
|
|||||||
* @date 2019/4/13 0013 下午 14:26
|
* @date 2019/4/13 0013 下午 14:26
|
||||||
* @since JDK1.8
|
* @since JDK1.8
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@Component("exampleTask")
|
@Component("exampleTask")
|
||||||
public class Example implements ITask {
|
public class Example implements ITask {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(String paramJson) throws Exception {
|
public void execute(String paramJson) throws Exception {
|
||||||
System.out.println(SmartDateUtil.formatYMDHMS(new Date()) + ",今天搬了" + System.currentTimeMillis() + "块砖,paramJson:" + paramJson);
|
log.warn("{}-今天搬了{}块砖,paramJson:{}",SmartDateUtil.formatYMDHMS(new Date()),System.currentTimeMillis(),paramJson );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package net.lab1024.smartadmin.module.system.datascope.constant;
|
package net.lab1024.smartadmin.module.system.datascope.constant;
|
||||||
|
|
||||||
|
|
||||||
|
import net.lab1024.smartadmin.common.domain.BaseEnum;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [ ]
|
* [ ]
|
||||||
*
|
*
|
||||||
@ -11,30 +13,32 @@ package net.lab1024.smartadmin.module.system.datascope.constant;
|
|||||||
* @date 2019/4/28 0028 下午 15:37
|
* @date 2019/4/28 0028 下午 15:37
|
||||||
* @since JDK1.8
|
* @since JDK1.8
|
||||||
*/
|
*/
|
||||||
public enum DataScopeTypeEnum {
|
public enum DataScopeTypeEnum implements BaseEnum {
|
||||||
|
|
||||||
DEFAULT(0,0,"默认类型","数据范围样例");
|
DEFAULT(0,0,"默认类型","数据范围样例");
|
||||||
|
|
||||||
private Integer type;
|
private Integer value;
|
||||||
private Integer sort;
|
private Integer sort;
|
||||||
private String name;
|
private String name;
|
||||||
private String desc;
|
private String desc;
|
||||||
|
|
||||||
DataScopeTypeEnum(Integer type,Integer sort,String name,String desc) {
|
DataScopeTypeEnum(Integer value,Integer sort,String name,String desc) {
|
||||||
this.type = type;
|
this.value = value;
|
||||||
this.sort = sort;
|
this.sort = sort;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.desc = desc;
|
this.desc = desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getType() {
|
@Override
|
||||||
return type;
|
public Integer getValue() {
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getSort() {
|
public Integer getSort() {
|
||||||
return sort;
|
return sort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getDesc() {
|
public String getDesc() {
|
||||||
return desc;
|
return desc;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package net.lab1024.smartadmin.module.system.datascope.constant;
|
package net.lab1024.smartadmin.module.system.datascope.constant;
|
||||||
|
|
||||||
|
|
||||||
|
import net.lab1024.smartadmin.common.domain.BaseEnum;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@ -14,7 +16,7 @@ import java.util.Optional;
|
|||||||
* @date 2019/4/28 0028 下午 15:37
|
* @date 2019/4/28 0028 下午 15:37
|
||||||
* @since JDK1.8
|
* @since JDK1.8
|
||||||
*/
|
*/
|
||||||
public enum DataScopeViewTypeEnum {
|
public enum DataScopeViewTypeEnum implements BaseEnum {
|
||||||
|
|
||||||
ME(0,0,"本人"),
|
ME(0,0,"本人"),
|
||||||
|
|
||||||
@ -24,32 +26,29 @@ public enum DataScopeViewTypeEnum {
|
|||||||
|
|
||||||
ALL(3,15,"全部");
|
ALL(3,15,"全部");
|
||||||
|
|
||||||
private Integer type;
|
private Integer value;
|
||||||
private Integer level;
|
private Integer level;
|
||||||
private String name;
|
private String desc;
|
||||||
|
|
||||||
DataScopeViewTypeEnum(Integer type,Integer level, String name) {
|
DataScopeViewTypeEnum(Integer value,Integer level, String desc) {
|
||||||
this.type = type;
|
this.value = value;
|
||||||
this.level = level;
|
this.level = level;
|
||||||
this.name = name;
|
this.desc = desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getType() {
|
@Override
|
||||||
return type;
|
public Integer getValue() {
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getLevel() {
|
public Integer getLevel() {
|
||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
@Override
|
||||||
return name;
|
public String getDesc() {
|
||||||
|
return desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DataScopeViewTypeEnum valueOf(Integer type) {
|
|
||||||
DataScopeViewTypeEnum[] values = DataScopeViewTypeEnum.values();
|
|
||||||
Optional<DataScopeViewTypeEnum> first = Arrays.stream(values).filter(e -> e.getType().equals(type)).findFirst();
|
|
||||||
return !first.isPresent() ? null : first.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package net.lab1024.smartadmin.module.system.datascope.constant;
|
package net.lab1024.smartadmin.module.system.datascope.constant;
|
||||||
|
|
||||||
|
import net.lab1024.smartadmin.common.domain.BaseEnum;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [ ]
|
* [ ]
|
||||||
*
|
*
|
||||||
@ -10,25 +12,28 @@ package net.lab1024.smartadmin.module.system.datascope.constant;
|
|||||||
* @date 2019/5/8 0008 下午 16:00
|
* @date 2019/5/8 0008 下午 16:00
|
||||||
* @since JDK1.8
|
* @since JDK1.8
|
||||||
*/
|
*/
|
||||||
public enum DataScopeWhereInTypeEnum {
|
public enum DataScopeWhereInTypeEnum implements BaseEnum {
|
||||||
|
|
||||||
EMPLOYEE(0,"以员工IN"),
|
EMPLOYEE(0,"以员工IN"),
|
||||||
|
|
||||||
DEPARTMENT(1,"以部门IN");
|
DEPARTMENT(1,"以部门IN"),
|
||||||
|
|
||||||
private Integer type;
|
CUSTOM_STRATEGY(2,"自定义策略");
|
||||||
|
|
||||||
|
private Integer value;
|
||||||
private String desc;
|
private String desc;
|
||||||
|
|
||||||
DataScopeWhereInTypeEnum(Integer type, String desc) {
|
DataScopeWhereInTypeEnum(Integer value, String desc) {
|
||||||
this.type = type;
|
this.value = value;
|
||||||
this.desc = desc;
|
this.desc = desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getType() {
|
@Override
|
||||||
return type;
|
public Integer getValue() {
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getDesc() {
|
public String getDesc() {
|
||||||
return desc;
|
return desc;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package net.lab1024.smartadmin.module.system.datascope.domain.dto;
|
package net.lab1024.smartadmin.module.system.datascope.domain.dto;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import net.lab1024.smartadmin.module.system.datascope.constant.DataScopeTypeEnum;
|
||||||
|
import net.lab1024.smartadmin.module.system.datascope.constant.DataScopeWhereInTypeEnum;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [ ]
|
* [ ]
|
||||||
@ -15,11 +17,24 @@ import lombok.Data;
|
|||||||
@Data
|
@Data
|
||||||
public class DataScopeSqlConfigDTO {
|
public class DataScopeSqlConfigDTO {
|
||||||
|
|
||||||
private Integer dataScopeType;
|
/**
|
||||||
|
* 数据范围类型
|
||||||
|
* {@link DataScopeTypeEnum}
|
||||||
|
*/
|
||||||
|
private DataScopeTypeEnum dataScopeType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* join sql 具体实现类
|
||||||
|
*/
|
||||||
|
private Class joinSqlImplClazz;
|
||||||
|
|
||||||
private String joinSql;
|
private String joinSql;
|
||||||
|
|
||||||
private Integer whereIndex;
|
private Integer whereIndex;
|
||||||
|
|
||||||
private Integer dataScopeWhereInType;
|
/**
|
||||||
|
* whereIn类型
|
||||||
|
* {@link DataScopeWhereInTypeEnum}
|
||||||
|
*/
|
||||||
|
private DataScopeWhereInTypeEnum dataScopeWhereInType;
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ public class DataScopeService {
|
|||||||
DataScopeViewTypeEnum[] enums = DataScopeViewTypeEnum.class.getEnumConstants();
|
DataScopeViewTypeEnum[] enums = DataScopeViewTypeEnum.class.getEnumConstants();
|
||||||
DataScopeViewTypeVO dataScopeViewTypeDTO;
|
DataScopeViewTypeVO dataScopeViewTypeDTO;
|
||||||
for (DataScopeViewTypeEnum viewTypeEnum : enums) {
|
for (DataScopeViewTypeEnum viewTypeEnum : enums) {
|
||||||
dataScopeViewTypeDTO = DataScopeViewTypeVO.builder().viewType(viewTypeEnum.getType()).viewTypeLevel(viewTypeEnum.getLevel()).viewTypeName(viewTypeEnum.getName()).build();
|
dataScopeViewTypeDTO = DataScopeViewTypeVO.builder().viewType(viewTypeEnum.getValue()).viewTypeLevel(viewTypeEnum.getLevel()).viewTypeName(viewTypeEnum.getDesc()).build();
|
||||||
viewTypeList.add(dataScopeViewTypeDTO);
|
viewTypeList.add(dataScopeViewTypeDTO);
|
||||||
}
|
}
|
||||||
Comparator<DataScopeViewTypeVO> comparator = (h1, h2) -> h1.getViewTypeLevel().compareTo(h2.getViewTypeLevel());
|
Comparator<DataScopeViewTypeVO> comparator = (h1, h2) -> h1.getViewTypeLevel().compareTo(h2.getViewTypeLevel());
|
||||||
@ -72,7 +72,7 @@ public class DataScopeService {
|
|||||||
DataScopeDTO dataScopeDTO;
|
DataScopeDTO dataScopeDTO;
|
||||||
for (DataScopeTypeEnum typeEnum : enums) {
|
for (DataScopeTypeEnum typeEnum : enums) {
|
||||||
dataScopeDTO =
|
dataScopeDTO =
|
||||||
DataScopeDTO.builder().dataScopeType(typeEnum.getType()).dataScopeTypeDesc(typeEnum.getDesc()).dataScopeTypeName(typeEnum.getName()).dataScopeTypeSort(typeEnum.getSort()).build();
|
DataScopeDTO.builder().dataScopeType(typeEnum.getValue()).dataScopeTypeDesc(typeEnum.getDesc()).dataScopeTypeName(typeEnum.getName()).dataScopeTypeSort(typeEnum.getSort()).build();
|
||||||
dataScopeTypeList.add(dataScopeDTO);
|
dataScopeTypeList.add(dataScopeDTO);
|
||||||
}
|
}
|
||||||
Comparator<DataScopeDTO> comparator = (h1, h2) -> h1.getDataScopeTypeSort().compareTo(h2.getDataScopeTypeSort());
|
Comparator<DataScopeDTO> comparator = (h1, h2) -> h1.getDataScopeTypeSort().compareTo(h2.getDataScopeTypeSort());
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
package net.lab1024.smartadmin.module.system.datascope.service;
|
package net.lab1024.smartadmin.module.system.datascope.service;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.lab1024.smartadmin.common.anno.DataScope;
|
import net.lab1024.smartadmin.common.anno.DataScope;
|
||||||
|
import net.lab1024.smartadmin.module.system.datascope.constant.DataScopeTypeEnum;
|
||||||
|
import net.lab1024.smartadmin.module.system.datascope.constant.DataScopeViewTypeEnum;
|
||||||
import net.lab1024.smartadmin.module.system.datascope.constant.DataScopeWhereInTypeEnum;
|
import net.lab1024.smartadmin.module.system.datascope.constant.DataScopeWhereInTypeEnum;
|
||||||
import net.lab1024.smartadmin.module.system.datascope.domain.dto.DataScopeSqlConfigDTO;
|
import net.lab1024.smartadmin.module.system.datascope.domain.dto.DataScopeSqlConfigDTO;
|
||||||
|
import net.lab1024.smartadmin.module.system.datascope.strategy.DataScopePowerStrategy;
|
||||||
import net.lab1024.smartadmin.module.system.login.domain.RequestTokenBO;
|
import net.lab1024.smartadmin.module.system.login.domain.RequestTokenBO;
|
||||||
|
import net.lab1024.smartadmin.third.SmartApplicationContext;
|
||||||
import net.lab1024.smartadmin.util.SmartRequestTokenUtil;
|
import net.lab1024.smartadmin.util.SmartRequestTokenUtil;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@ -32,6 +37,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
* @date 2019/4/29 0029 上午 10:12
|
* @date 2019/4/29 0029 上午 10:12
|
||||||
* @since JDK1.8
|
* @since JDK1.8
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class DataScopeSqlConfigService {
|
public class DataScopeSqlConfigService {
|
||||||
|
|
||||||
@ -67,10 +73,10 @@ public class DataScopeSqlConfigService {
|
|||||||
DataScope dataScopeAnnotation = method.getAnnotation(DataScope.class);
|
DataScope dataScopeAnnotation = method.getAnnotation(DataScope.class);
|
||||||
if (dataScopeAnnotation != null) {
|
if (dataScopeAnnotation != null) {
|
||||||
DataScopeSqlConfigDTO configDTO = new DataScopeSqlConfigDTO();
|
DataScopeSqlConfigDTO configDTO = new DataScopeSqlConfigDTO();
|
||||||
configDTO.setDataScopeType(dataScopeAnnotation.dataScopeType().getType());
|
configDTO.setDataScopeType(dataScopeAnnotation.dataScopeType());
|
||||||
configDTO.setJoinSql(dataScopeAnnotation.joinSql());
|
configDTO.setJoinSql(dataScopeAnnotation.joinSql());
|
||||||
configDTO.setWhereIndex(dataScopeAnnotation.whereIndex());
|
configDTO.setWhereIndex(dataScopeAnnotation.whereIndex());
|
||||||
configDTO.setDataScopeWhereInType(dataScopeAnnotation.whereInType().getType());
|
configDTO.setDataScopeWhereInType(dataScopeAnnotation.whereInType());
|
||||||
dataScopeMethodMap.put(method.getDeclaringClass().getSimpleName() + "." + method.getName(), configDTO);
|
dataScopeMethodMap.put(method.getDeclaringClass().getSimpleName() + "." + method.getName(), configDTO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,12 +101,26 @@ public class DataScopeSqlConfigService {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public String getJoinSql(DataScopeSqlConfigDTO sqlConfigDTO) {
|
public String getJoinSql(DataScopeSqlConfigDTO sqlConfigDTO) {
|
||||||
Integer dataScopeType = sqlConfigDTO.getDataScopeType();
|
DataScopeTypeEnum dataScopeTypeEnum = sqlConfigDTO.getDataScopeType();
|
||||||
String joinSql = sqlConfigDTO.getJoinSql();
|
String joinSql = sqlConfigDTO.getJoinSql();
|
||||||
RequestTokenBO requestToken = SmartRequestTokenUtil.getThreadLocalUser();
|
RequestTokenBO requestToken = SmartRequestTokenUtil.getThreadLocalUser();
|
||||||
Long employeeId = requestToken.getRequestUserId();
|
Long employeeId = requestToken.getRequestUserId();
|
||||||
if (DataScopeWhereInTypeEnum.EMPLOYEE.getType().equals(sqlConfigDTO.getDataScopeWhereInType())) {
|
if (DataScopeWhereInTypeEnum.CUSTOM_STRATEGY == sqlConfigDTO.getDataScopeWhereInType()) {
|
||||||
List<Long> canViewEmployeeIds = dataScopeViewService.getCanViewEmployeeId(dataScopeType, employeeId);
|
Class strategyClass = sqlConfigDTO.getJoinSqlImplClazz();
|
||||||
|
if(strategyClass == null){
|
||||||
|
log.warn("data scope custom strategy class is null");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
DataScopePowerStrategy powerStrategy = (DataScopePowerStrategy)SmartApplicationContext.getBean(sqlConfigDTO.getJoinSqlImplClazz());
|
||||||
|
if (powerStrategy == null) {
|
||||||
|
log.warn("data scope custom strategy class:{} ,bean is null",sqlConfigDTO.getJoinSqlImplClazz());
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
DataScopeViewTypeEnum viewTypeEnum = dataScopeViewService.getEmployeeDataScopeViewType(dataScopeTypeEnum, employeeId);
|
||||||
|
return powerStrategy.getCondition(viewTypeEnum,sqlConfigDTO);
|
||||||
|
}
|
||||||
|
if (DataScopeWhereInTypeEnum.EMPLOYEE == sqlConfigDTO.getDataScopeWhereInType()) {
|
||||||
|
List<Long> canViewEmployeeIds = dataScopeViewService.getCanViewEmployeeId(dataScopeTypeEnum, employeeId);
|
||||||
if (CollectionUtils.isEmpty(canViewEmployeeIds)) {
|
if (CollectionUtils.isEmpty(canViewEmployeeIds)) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@ -108,8 +128,8 @@ public class DataScopeSqlConfigService {
|
|||||||
String sql = joinSql.replaceAll(EMPLOYEE_PARAM, employeeIds);
|
String sql = joinSql.replaceAll(EMPLOYEE_PARAM, employeeIds);
|
||||||
return sql;
|
return sql;
|
||||||
}
|
}
|
||||||
if (DataScopeWhereInTypeEnum.DEPARTMENT.getType().equals(sqlConfigDTO.getDataScopeWhereInType())) {
|
if (DataScopeWhereInTypeEnum.DEPARTMENT == sqlConfigDTO.getDataScopeWhereInType()) {
|
||||||
List<Long> canViewDepartmentIds = dataScopeViewService.getCanViewDepartmentId(dataScopeType, employeeId);
|
List<Long> canViewDepartmentIds = dataScopeViewService.getCanViewDepartmentId(dataScopeTypeEnum, employeeId);
|
||||||
if (CollectionUtils.isEmpty(canViewDepartmentIds)) {
|
if (CollectionUtils.isEmpty(canViewDepartmentIds)) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package net.lab1024.smartadmin.module.system.datascope.service;
|
package net.lab1024.smartadmin.module.system.datascope.service;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import net.lab1024.smartadmin.module.system.datascope.DataScopeRoleDao;
|
import net.lab1024.smartadmin.module.system.datascope.DataScopeRoleDao;
|
||||||
|
import net.lab1024.smartadmin.module.system.datascope.constant.DataScopeTypeEnum;
|
||||||
import net.lab1024.smartadmin.module.system.datascope.constant.DataScopeViewTypeEnum;
|
import net.lab1024.smartadmin.module.system.datascope.constant.DataScopeViewTypeEnum;
|
||||||
import net.lab1024.smartadmin.module.system.datascope.domain.entity.DataScopeRoleEntity;
|
import net.lab1024.smartadmin.module.system.datascope.domain.entity.DataScopeRoleEntity;
|
||||||
import net.lab1024.smartadmin.module.system.department.DepartmentTreeService;
|
import net.lab1024.smartadmin.module.system.department.DepartmentTreeService;
|
||||||
@ -10,7 +12,7 @@ import net.lab1024.smartadmin.module.system.employee.domain.entity.EmployeeEntit
|
|||||||
import net.lab1024.smartadmin.module.system.employee.domain.vo.EmployeeVO;
|
import net.lab1024.smartadmin.module.system.employee.domain.vo.EmployeeVO;
|
||||||
import net.lab1024.smartadmin.module.system.privilege.service.PrivilegeEmployeeService;
|
import net.lab1024.smartadmin.module.system.privilege.service.PrivilegeEmployeeService;
|
||||||
import net.lab1024.smartadmin.module.system.role.roleemployee.RoleEmployeeDao;
|
import net.lab1024.smartadmin.module.system.role.roleemployee.RoleEmployeeDao;
|
||||||
import com.google.common.collect.Lists;
|
import net.lab1024.smartadmin.util.SmartBaseEnumUtil;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -51,33 +53,40 @@ public class DataScopeViewService {
|
|||||||
/**
|
/**
|
||||||
* 获取某人可以查看的所有人员信息
|
* 获取某人可以查看的所有人员信息
|
||||||
*
|
*
|
||||||
* @param dataScopeType
|
* @param dataScopeTypeEnum
|
||||||
* @param employeeId
|
* @param employeeId
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public List<Long> getCanViewEmployeeId(Integer dataScopeType, Long employeeId) {
|
public List<Long> getCanViewEmployeeId(DataScopeTypeEnum dataScopeTypeEnum, Long employeeId) {
|
||||||
Integer viewType = this.getEmployeeDataScopeViewType(dataScopeType, employeeId);
|
DataScopeViewTypeEnum viewType = this.getEmployeeDataScopeViewType(dataScopeTypeEnum, employeeId);
|
||||||
if (DataScopeViewTypeEnum.ME.getType().equals(viewType)) {
|
if (DataScopeViewTypeEnum.ME == viewType) {
|
||||||
return this.getMeEmployeeIdList(employeeId);
|
return this.getMeEmployeeIdList(employeeId);
|
||||||
}
|
}
|
||||||
if (DataScopeViewTypeEnum.DEPARTMENT.getType().equals(viewType)) {
|
if (DataScopeViewTypeEnum.DEPARTMENT == viewType) {
|
||||||
return this.getDepartmentEmployeeIdList(employeeId);
|
return this.getDepartmentEmployeeIdList(employeeId);
|
||||||
}
|
}
|
||||||
if (DataScopeViewTypeEnum.DEPARTMENT_AND_SUB.getType().equals(viewType)) {
|
if (DataScopeViewTypeEnum.DEPARTMENT_AND_SUB == viewType) {
|
||||||
return this.getDepartmentAndSubEmployeeIdList(employeeId);
|
return this.getDepartmentAndSubEmployeeIdList(employeeId);
|
||||||
}
|
}
|
||||||
return Lists.newArrayList();
|
return Lists.newArrayList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Long> getCanViewDepartmentId(Integer dataScopeType, Long employeeId) {
|
/**
|
||||||
Integer viewType = this.getEmployeeDataScopeViewType(dataScopeType, employeeId);
|
* 获取某人可以查看的所有部门信息
|
||||||
if (DataScopeViewTypeEnum.ME.getType().equals(viewType)) {
|
*
|
||||||
|
* @param dataScopeTypeEnum
|
||||||
|
* @param employeeId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<Long> getCanViewDepartmentId(DataScopeTypeEnum dataScopeTypeEnum, Long employeeId) {
|
||||||
|
DataScopeViewTypeEnum viewType = this.getEmployeeDataScopeViewType(dataScopeTypeEnum, employeeId);
|
||||||
|
if (DataScopeViewTypeEnum.ME == viewType) {
|
||||||
return this.getMeDepartmentIdList(employeeId);
|
return this.getMeDepartmentIdList(employeeId);
|
||||||
}
|
}
|
||||||
if (DataScopeViewTypeEnum.DEPARTMENT.getType().equals(viewType)) {
|
if (DataScopeViewTypeEnum.DEPARTMENT == viewType) {
|
||||||
return this.getMeDepartmentIdList(employeeId);
|
return this.getMeDepartmentIdList(employeeId);
|
||||||
}
|
}
|
||||||
if (DataScopeViewTypeEnum.DEPARTMENT_AND_SUB.getType().equals(viewType)) {
|
if (DataScopeViewTypeEnum.DEPARTMENT_AND_SUB == viewType) {
|
||||||
return this.getDepartmentAndSubIdList(employeeId);
|
return this.getDepartmentAndSubIdList(employeeId);
|
||||||
}
|
}
|
||||||
return Lists.newArrayList();
|
return Lists.newArrayList();
|
||||||
@ -101,28 +110,28 @@ public class DataScopeViewService {
|
|||||||
* @param employeeId
|
* @param employeeId
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private Integer getEmployeeDataScopeViewType(Integer dataScopeType, Long employeeId) {
|
public DataScopeViewTypeEnum getEmployeeDataScopeViewType(DataScopeTypeEnum dataScopeTypeEnum, Long employeeId) {
|
||||||
if (employeeId == null) {
|
if (employeeId == null) {
|
||||||
return DataScopeViewTypeEnum.ME.getType();
|
return DataScopeViewTypeEnum.ME;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (privilegeEmployeeService.isSuperman(employeeId)) {
|
if (privilegeEmployeeService.isSuperman(employeeId)) {
|
||||||
return DataScopeViewTypeEnum.ALL.getType();
|
return DataScopeViewTypeEnum.ALL;
|
||||||
}
|
}
|
||||||
List<Long> roleIdList = roleEmployeeDao.selectRoleIdByEmployeeId(employeeId);
|
List<Long> roleIdList = roleEmployeeDao.selectRoleIdByEmployeeId(employeeId);
|
||||||
//未设置角色 默认本人
|
//未设置角色 默认本人
|
||||||
if (CollectionUtils.isEmpty(roleIdList)) {
|
if (CollectionUtils.isEmpty(roleIdList)) {
|
||||||
return DataScopeViewTypeEnum.ME.getType();
|
return DataScopeViewTypeEnum.ME;
|
||||||
}
|
}
|
||||||
//未设置角色数据范围 默认本人
|
//未设置角色数据范围 默认本人
|
||||||
List<DataScopeRoleEntity> dataScopeRoleList = dataScopeRoleDao.listByRoleIdList(roleIdList);
|
List<DataScopeRoleEntity> dataScopeRoleList = dataScopeRoleDao.listByRoleIdList(roleIdList);
|
||||||
if (CollectionUtils.isEmpty(dataScopeRoleList)) {
|
if (CollectionUtils.isEmpty(dataScopeRoleList)) {
|
||||||
return DataScopeViewTypeEnum.ME.getType();
|
return DataScopeViewTypeEnum.ME;
|
||||||
}
|
}
|
||||||
Map<Integer, List<DataScopeRoleEntity>> listMap = dataScopeRoleList.stream().collect(Collectors.groupingBy(DataScopeRoleEntity :: getDataScopeType));
|
Map<Integer, List<DataScopeRoleEntity>> listMap = dataScopeRoleList.stream().collect(Collectors.groupingBy(DataScopeRoleEntity::getDataScopeType));
|
||||||
List<DataScopeRoleEntity> viewLevelList = listMap.get(dataScopeType);
|
List<DataScopeRoleEntity> viewLevelList = listMap.get(dataScopeTypeEnum.getValue());
|
||||||
DataScopeRoleEntity maxLevel = viewLevelList.stream().max(Comparator.comparing(e -> DataScopeViewTypeEnum.valueOf(e.getViewType()).getLevel())).get();
|
DataScopeRoleEntity maxLevel = viewLevelList.stream().max(Comparator.comparing(e -> SmartBaseEnumUtil.getEnumByValue(e.getViewType(), DataScopeViewTypeEnum.class).getLevel())).get();
|
||||||
return maxLevel.getViewType();
|
return SmartBaseEnumUtil.getEnumByValue(maxLevel.getViewType(), DataScopeViewTypeEnum.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -134,6 +143,7 @@ public class DataScopeViewService {
|
|||||||
private List<Long> getMeEmployeeIdList(Long employeeId) {
|
private List<Long> getMeEmployeeIdList(Long employeeId) {
|
||||||
return Lists.newArrayList(employeeId);
|
return Lists.newArrayList(employeeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取本部门相关 可查看员工id
|
* 获取本部门相关 可查看员工id
|
||||||
*
|
*
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
package net.lab1024.smartadmin.module.system.datascope.strategy;
|
||||||
|
import net.lab1024.smartadmin.module.system.datascope.constant.DataScopeViewTypeEnum;
|
||||||
|
import net.lab1024.smartadmin.module.system.datascope.domain.dto.DataScopeSqlConfigDTO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [ 数据范围策略 ,使用DataScopeWhereInTypeEnum.CUSTOM_STRATEGY类型,DataScope注解的joinSql属性无用]
|
||||||
|
*
|
||||||
|
* @author yandanyang
|
||||||
|
* @version 1.0
|
||||||
|
* @company 1024lab.net
|
||||||
|
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
|
||||||
|
* @date 2020/11/28 0008 下午 16:00
|
||||||
|
* @since JDK1.8
|
||||||
|
*/
|
||||||
|
public abstract class DataScopePowerStrategy {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取joinsql 字符串
|
||||||
|
* @param viewTypeEnum 查看的类型
|
||||||
|
* @param sqlConfigDTO
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public abstract String getCondition(DataScopeViewTypeEnum viewTypeEnum, DataScopeSqlConfigDTO sqlConfigDTO);
|
||||||
|
}
|
@ -86,7 +86,6 @@ public class EmployeeController {
|
|||||||
public ResponseDTO<String> updatePwd(@Valid @RequestBody EmployeeUpdatePwdDTO updatePwdDTO) {
|
public ResponseDTO<String> updatePwd(@Valid @RequestBody EmployeeUpdatePwdDTO updatePwdDTO) {
|
||||||
RequestTokenBO requestToken = SmartRequestTokenUtil.getRequestUser();
|
RequestTokenBO requestToken = SmartRequestTokenUtil.getRequestUser();
|
||||||
return employeeService.updatePwd(updatePwdDTO, requestToken);
|
return employeeService.updatePwd(updatePwdDTO, requestToken);
|
||||||
// return ResponseDTO.succ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation(value = "通过部门id获取当前部门的人员&没有部门的人", notes = "@author yandanyang")
|
@ApiOperation(value = "通过部门id获取当前部门的人员&没有部门的人", notes = "@author yandanyang")
|
||||||
|
@ -22,11 +22,9 @@ public class EmployeeLoginFormDTO {
|
|||||||
@ApiModelProperty(example = "123456")
|
@ApiModelProperty(example = "123456")
|
||||||
private String loginPwd;
|
private String loginPwd;
|
||||||
|
|
||||||
@NotNull(message = "验证码id不能为空")
|
|
||||||
@ApiModelProperty(value = "验证码uuid")
|
@ApiModelProperty(value = "验证码uuid")
|
||||||
private String codeUuid;
|
private String codeUuid;
|
||||||
|
|
||||||
@NotNull(message = "验证码不能为空")
|
|
||||||
@ApiModelProperty(value = "验证码")
|
@ApiModelProperty(value = "验证码")
|
||||||
private String code;
|
private String code;
|
||||||
|
|
||||||
|
@ -83,15 +83,15 @@ public class LoginService {
|
|||||||
* @return 登录用户基本信息
|
* @return 登录用户基本信息
|
||||||
*/
|
*/
|
||||||
public ResponseDTO<LoginDetailVO> login(@Valid EmployeeLoginFormDTO loginForm, HttpServletRequest request) {
|
public ResponseDTO<LoginDetailVO> login(@Valid EmployeeLoginFormDTO loginForm, HttpServletRequest request) {
|
||||||
String redisVerificationCode = redisValueOperations.get(loginForm.getCodeUuid());
|
// String redisVerificationCode = redisValueOperations.get(loginForm.getCodeUuid());
|
||||||
//增加删除已使用的验证码方式 频繁登录
|
// //增加删除已使用的验证码方式 频繁登录
|
||||||
redisValueOperations.getOperations().delete(loginForm.getCodeUuid());
|
// redisValueOperations.getOperations().delete(loginForm.getCodeUuid());
|
||||||
if (StringUtils.isEmpty(redisVerificationCode)) {
|
// if (StringUtils.isEmpty(redisVerificationCode)) {
|
||||||
return ResponseDTO.wrap(EmployeeResponseCodeConst.VERIFICATION_CODE_INVALID);
|
// return ResponseDTO.wrap(EmployeeResponseCodeConst.VERIFICATION_CODE_INVALID);
|
||||||
}
|
// }
|
||||||
if (!redisVerificationCode.equalsIgnoreCase(loginForm.getCode())) {
|
// if (!redisVerificationCode.equalsIgnoreCase(loginForm.getCode())) {
|
||||||
return ResponseDTO.wrap(EmployeeResponseCodeConst.VERIFICATION_CODE_INVALID);
|
// return ResponseDTO.wrap(EmployeeResponseCodeConst.VERIFICATION_CODE_INVALID);
|
||||||
}
|
// }
|
||||||
String loginPwd = SmartDigestUtil.encryptPassword(CommonConst.Password.SALT_FORMAT, loginForm.getLoginPwd());
|
String loginPwd = SmartDigestUtil.encryptPassword(CommonConst.Password.SALT_FORMAT, loginForm.getLoginPwd());
|
||||||
EmployeeDTO employeeDTO = employeeDao.login(loginForm.getLoginName(), loginPwd);
|
EmployeeDTO employeeDTO = employeeDao.login(loginForm.getLoginName(), loginPwd);
|
||||||
if (null == employeeDTO) {
|
if (null == employeeDTO) {
|
||||||
|
@ -42,7 +42,6 @@ public class PrivilegeController {
|
|||||||
@PostMapping("/privilege/menu/batchSaveMenu")
|
@PostMapping("/privilege/menu/batchSaveMenu")
|
||||||
public ResponseDTO<String> menuBatchSave(@Valid @RequestBody ValidateList<PrivilegeMenuDTO> menuList) {
|
public ResponseDTO<String> menuBatchSave(@Valid @RequestBody ValidateList<PrivilegeMenuDTO> menuList) {
|
||||||
return privilegeService.menuBatchSave(menuList);
|
return privilegeService.menuBatchSave(menuList);
|
||||||
// return ResponseDTO.succ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -57,14 +56,12 @@ public class PrivilegeController {
|
|||||||
@PostMapping("/privilege/function/saveOrUpdate")
|
@PostMapping("/privilege/function/saveOrUpdate")
|
||||||
public ResponseDTO<String> functionSaveOrUpdate(@Valid @RequestBody PrivilegeFunctionDTO privilegeFunctionDTO) {
|
public ResponseDTO<String> functionSaveOrUpdate(@Valid @RequestBody PrivilegeFunctionDTO privilegeFunctionDTO) {
|
||||||
return privilegeService.functionSaveOrUpdate(privilegeFunctionDTO);
|
return privilegeService.functionSaveOrUpdate(privilegeFunctionDTO);
|
||||||
// return ResponseDTO.succ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation(value = "批量保存功能点")
|
@ApiOperation(value = "批量保存功能点")
|
||||||
@PostMapping("/privilege/function/batchSave")
|
@PostMapping("/privilege/function/batchSave")
|
||||||
public ResponseDTO<String> batchSaveFunctionList(@Valid @RequestBody ValidateList<PrivilegeFunctionDTO> functionList) {
|
public ResponseDTO<String> batchSaveFunctionList(@Valid @RequestBody ValidateList<PrivilegeFunctionDTO> functionList) {
|
||||||
return privilegeService.batchSaveFunctionList(functionList);
|
return privilegeService.batchSaveFunctionList(functionList);
|
||||||
// return ResponseDTO.succ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user