This commit is contained in:
zhuoda
2021-05-02 11:54:19 +08:00
parent 8b1863511c
commit ca770b208d
103 changed files with 16993 additions and 748 deletions

View File

@@ -1,4 +1,4 @@
NODE_ENV=development
VUE_APP_TYPE=dev
VUE_APP_URL=http://172.16.0.145:10086/smart-admin-api/
VUE_APP_SOCKET_URL=ws://172.16.0.145:10086/smart-admin-api/
VUE_APP_URL=http://127.0.0.1:10086/smart-admin-api/
VUE_APP_SOCKET_URL=ws://127.0.0.1:10086/smart-admin-api/

View File

@@ -2,8 +2,6 @@
node_modules
/dist
package-lock.json
/tests/e2e/videos/
/tests/e2e/screenshots/

15500
smart-admin-web/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -23,6 +23,7 @@
"cropperjs": "^1.2.2",
"dayjs": "^1.7.7",
"decimal.js": "^10.1.1",
"e-guide-layer": "^0.1.1",
"echarts": "^4.0.4",
"gq-plus": "^2.1.5",
"html2canvas": "^1.0.0-alpha.12",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -12,3 +12,8 @@
}
}
}
.step-bottom-btn{
width: 380px !important;
}

View File

@@ -6,7 +6,7 @@
icon="icon iconfont icondaohangzhedie"
/>
<div class="custom-bread-crumb" style="margin-left: 30px;">
<div class="custom-bread-crumb" style="margin-left: 30px;" id="topMenuSelectDiv">
<div class="ivu-breadcrumb" >
<Dropdown @on-click="changeTopMenu">
<a href="javascript:void(0)" style="font-size:15px;font-weight:600">
@@ -35,6 +35,7 @@
<div class="custom-content-con">
<slot></slot>
</div>
</div>
</template>
<script>
@@ -64,6 +65,27 @@ export default {
required:true
}
},
data(){
return {
guideActiveIndex: 0,
guideList: [
{
confirmBtnText: '第一步选择顶级菜单SmartAdmin是支持四级菜单的哦',
targetDom: '#topMenuSelectDiv',
clickHandle: () => {
this.guideActiveIndex = 1
},
},
{
confirmBtnText: '第二步:选择顶级下单下的三级菜单',
targetDom: '.side-menu-wrapper',
clickHandle: () => {
this.guideActiveIndex = 2
}
}
],
}
},
computed: {
// 面包屑集合
breadCrumbList() {
@@ -80,3 +102,5 @@ export default {
}
};
</script>

View File

@@ -20,14 +20,14 @@
v-else
>
<common-icon :type="item.children[0].icon || ''" />
<span>{{ showTitle(item.children[0]) }}</span>
<span>{{ showTitle(item.children[0]) }} </span>
</menu-item>
</template>
<template v-else>
<side-menu-item :key="`menu-${item.name}`" :parent-item="item" v-if="item.children && item.children.length > 0"></side-menu-item>
<menu-item :key="`menu-${item.name}`" :name="getNameOrHref(item)" v-else>
<common-icon :type="item.icon || ''" />
<span>{{ showTitle(item) }}</span>
<span>{{ showTitle(item) }} </span>
</menu-item>
</template>
</template>

View File

@@ -18,7 +18,7 @@
.scrollbar;
}
.logo-con{
padding: 19px 0 15px 20px;
padding: 19px 10px 15px 5px;
&.collapsed{
padding: 19px 0 15px;
text-align: center;
@@ -28,7 +28,7 @@
margin-left: 200px;
}
.search-bar{
padding:0 20px;
padding:0 14px;
margin-bottom: 20px;
&.collapsed{
padding:0 12px;

View File

@@ -3,7 +3,7 @@
<Sider
:collapsed-width="60"
:style="{overflow: 'hidden'}"
:width="256"
:width="185"
class="left-sider"
collapsible
hide-trigger

View File

@@ -23,9 +23,13 @@ import enumInfo from '@/constants';
// 处理table操作按钮
import tableAction from './lib/table-action';
//时间
import moment from 'moment';
// 时间
import moment from 'moment';
import 'e-guide-layer/dist/e-guide-layer.css'
import eGuideLayer from 'e-guide-layer'
Vue.use(eGuideLayer);
Vue.prototype.$tableAction = tableAction;
Vue.use(Enum, { enumInfo });
@@ -42,7 +46,7 @@ Number.prototype.toFixed = function (length) {
};
//时间处理
moment.locale('zh-cn'); //设置语言 或 moment.lang('zh-cn');
moment.locale('zh-cn'); //设置语言 或 moment.lang('zh-cn');
Vue.prototype.$moment = moment;//赋值使用

View File

@@ -20,24 +20,26 @@ export const threeRouter = [
children: [
{
path: '/three-router/level-two/level-three1',
name: 'RoleOneTwo',
name: 'ThreeLevelRouterView',
meta: {
title: '三级A',
title: '三级菜单子颗粒',
privilege: [
{ title: '添加', name: 'roleOneTwo-add' },
{ title: '删除', name: 'roleOneTwo-delete' }
{ title: '添加', name: 'three-level-router-view-add' },
{ title: '查询', name: 'three-level-router-view-query' },
]
},
component: () => import('@/views/system/system-setting/system-config/system-config.vue')
component: () => import('@/views/business/three-level-router/three-level-router-view.vue')
},
{
path: '/three-router/level-two/level-three2',
name: 'RoleTwoTwo',
meta: {
title: '三级B',
title: '三级菜单子哈',
privilege: [
{ title: '添加', name: 'roleTwoTwo-add' },
{ title: '删除', name: 'roleTwoTwo-delete' }
{ title: '删除', name: 'roleTwoTwo-delete' },
{ title: '删除', name: 'roleTwoTwo-delete1' },
{ title: '删除', name: 'roleTwoTwo-delete2' },
]
},
component: () => import('@/views/support/monitor/sql.vue')

View File

@@ -42,7 +42,7 @@ export const systemSetting = [
path: '/system-setting/system-privilege',
name: 'SystemPrivilege',
meta: {
title: '菜单权限',
title: '菜单设置',
privilege: [
{
title: '编辑',

View File

@@ -31,7 +31,7 @@
}
.ivu-menu-submenu-title {
padding: 10px 24px !important;
padding: 8px 24px !important;
}
.ivu-menu-submenu-has-parent-submenu {
@@ -41,7 +41,7 @@
// 二级菜单
.ivu-menu-item,
.ivu-menu-submenu-has-parent-submenu {
padding: 9px 0 9px 65px !important;
padding: 8px 0 9px 48px !important;
background: url('../assets/images/slider/sub_slider_default.png') 30px 0
no-repeat !important;
@@ -63,9 +63,9 @@
}
}
.ivu-menu-submenu-has-parent-submenu {
padding-left: 41px !important;
padding-left: 31px !important;
.ivu-menu-submenu-title {
padding: 0 24px !important;
padding: 0 17px !important;
}
&.ivu-menu-child-item-active {
background: url('../assets/images/slider/sub_slider_active.png') 30px
@@ -73,12 +73,12 @@
border-right: 0;
}
.ivu-menu {
padding-top: 10px;
padding-top: 8px;
}
.ivu-menu-item,
.ivu-menu-item-active:hover {
background: none !important;
padding-left: 52px !important;
padding-left: 32px !important;
}
}
}

View File

@@ -94,6 +94,7 @@ export default {
let g = this;
g.editor = new WangEditor('#editor');
g.editor.customConfig = {
zIndex:1,
// 功能键
menus: [
'head', // 标题

View File

@@ -0,0 +1,58 @@
<template>
<Card class="warp-card" dis-hover>
<Alert>
<h3>三级路由第四级页面</h3>
<pre>
当前页面为第四级页面页面中有两个按钮进行权限测试
</pre>
</Alert>
<Form class="tools" inline>
<FormItem>
<Input placeholder="请输入" v-model="searchString">
<Button icon="ios-search" slot="append"></Button>
</Input>
</FormItem>
<FormItem>
<Button @click="addContent" v-privilege="'three-level-router-view-add'" icon="md-add" type="primary">添加</Button>
</FormItem>
</Form>
<Table :columns="columns" :data="tableData" border></Table>
</Card>
</template>
<script>
export default {
name: 'ThreeLevelRouterView',
components: {},
props: {},
data() {
return {
sourceData: [
{ name: '张三' },
{ name: '李四' },
{ name: '王二' },
{ name: '唐三' },
{ name: '赵大' },
{ name: '李二' }
],
columns: [
{
title: '名称',
key: 'name'
}
],
tableData: [],
searchString: ''
};
},
mounted() {
},
methods: {
addContent() {
this.$Message.success('哇哦,你点击了添加操作哦~');
}
}
};
</script>
<style lang="less" scoped>
</style>

View File

@@ -7,10 +7,10 @@
<FormItem prop="loginPwd">
<Input placeholder="请输入密码" type="password" v-model="formData.loginPwd"></Input>
</FormItem>
<FormItem prop="code">
<!-- <FormItem prop="code">
<Input class="code-input" placeholder="请输入验证码" v-model="formData.code"></Input>
<img :src="codeUrl" @click="verificationCode" class="codeUrl" v-if="codeUrl" />
</FormItem>
</FormItem> -->
<FormItem class="remember">
<Checkbox>记住密码</Checkbox>
</FormItem>
@@ -18,7 +18,7 @@
<Button :loading="btnLoading" @click="login" long type="primary">登录</Button>
</FormItem>
<div class="other-way">
<p class="inline" style="float:left">其他方式登陆(账号demo/123456 demo1/123456)</p>
<p class="inline" style="float:left">其他方式登陆(账号demo/123456)</p>
<div class="inline align" style="float:right">
<img alt class="marginLeft" src="../../../assets/images/login-taobao.png" />
<img alt class="marginLeft" src="../../../assets/images/login-alipay.png" />
@@ -47,14 +47,15 @@ export default {
default: () => {
return [{ required: true, message: '密码不能为空', trigger: 'blur' }];
}
},
// 验证码规则
codedRules: {
type: Array,
default: () => {
return [{ required: true, message: '验证码不能为空', trigger: 'blur' }];
}
}
// ,
// // 验证码规则
// codedRules: {
// type: Array,
// default: () => {
// return [{ required: true, message: '验证码不能为空', trigger: 'blur' }];
// }
// }
},
data() {
return {
@@ -63,7 +64,7 @@ export default {
formData: {
code: '',
codeUuid: '',
loginName: 'demo',
loginName: 'sa',
loginPwd: '123456'
},
codeUrl: ''
@@ -79,7 +80,7 @@ export default {
}
},
mounted() {
this.verificationCode();
// this.verificationCode();
},
methods: {
// 获取验证码
@@ -125,9 +126,9 @@ export default {
//TODO zhuoda sentry
console.error(e);
this.btnLoading = false;
this.verificationCode();
//this.verificationCode();
}
}
}
};
</script>
</script>

View File

@@ -26,7 +26,7 @@
width: 424px;
background: #fff;
padding: 32px 32px;
border-radius: 0 8px 8px 0;
border-radius: 8px;
.ivu-input {
border: 1px solid #E8E8EE;
border-radius: 4px;

View File

@@ -365,6 +365,7 @@ export default {
} catch (e) {
//TODO zhuoda sentry
console.error(e);
} finally {
this.loading = false;
}
},
@@ -400,33 +401,52 @@ export default {
},
// 删除任务
async deleteTask(id) {
let result = await taskApi.deleteTask(id);
this.$Message.success('删除任务成功!');
this.getTaskList();
this.$Spin.show();
try{
let result = await taskApi.deleteTask(id);
this.$Message.success('删除任务成功!');
this.getTaskList();
} catch (error) {
console.error(e);
} finally {
this.$Spin.hide();
}
},
// 操作任务
async controlTask(type, id) {
this.$Spin.show();
switch (type) {
case 'RUN':
await taskApi.updateTaskRun(id);
break;
case 'PAUSE':
await taskApi.updateTaskPause(id);
break;
case 'RESUME':
await taskApi.updateTaskResume(id);
break;
try{
switch (type) {
case 'RUN':
await taskApi.updateTaskRun(id);
break;
case 'PAUSE':
await taskApi.updateTaskPause(id);
break;
case 'RESUME':
await taskApi.updateTaskResume(id);
break;
}
this.$Message.success('操作成功');
this.getTaskList();
} catch (error) {
console.error(e);
} finally {
this.$Spin.hide();
}
this.$Spin.hide();
this.$Message.success('操作成功');
this.getTaskList();
},
// 触发更新
handleUpdate() {
this.$refs['updateRef'].validate(valid => {
if (valid) {
this.updateTask();
this.$Spin.show();
try{
this.updateTask();
} catch (error) {
console.error(e);
} finally {
this.$Spin.hide();
}
} else {
this.$Message.success('验证信息不通过');
}
@@ -444,6 +464,7 @@ export default {
} catch (e) {
//TODO zhuoda sentry
console.error(e);
} finally {
this.updateLoading = false;
}
},
@@ -464,6 +485,7 @@ export default {
} catch (e) {
//TODO zhuoda sentry
console.error(e);
} finally {
this.saveLoading = false;
}
},

View File

@@ -21,19 +21,19 @@
<div class="level-one">
<Checkbox
:label="module.key"
@click.prevent.native="selectCheckbox(tree, moduleIndex)"
>{{module.name}}</Checkbox>
@click.prevent.native="selectCheckbox(module)"
>{{module.name}} </Checkbox>
</div>
<!--div 二级权限模块 start-->
<div
:key="childrenModule.key"
class="level-teo"
class="level-two"
v-for="(childrenModule, childrenModuleIndex) in module.children"
>
<Checkbox
:label="childrenModule.key"
@click.prevent.native="selectCheckbox(module.children,childrenModuleIndex,tree)"
class="level-teo-label"
@click.prevent.native="selectCheckbox(childrenModule)"
class="level-two-label"
>{{childrenModule.name}}</Checkbox>
<!--div 三级权限模块 start-->
<div class="level-three">
@@ -46,23 +46,56 @@
<Checkbox
:key="pages.key"
:label="pages.key"
@click.prevent.native="selectCheckbox(childrenModule.children,pagesIndex,module.children)"
@click.prevent.native="selectCheckbox(pages)"
class="level-three-label"
>{{pages.name}}</Checkbox>
<div :key="pagesIndex" class="Level-four" v-if="pages.children.length > 0">
<!--div 四级权限模块 start-->
<div :key="pagesIndex" class="level-four" v-if="pages.children.length > 0">
<template v-for="(page, pageIndex) in pages.children">
<Checkbox
:key="page.key"
:label="page.key"
@click.prevent.native="selectCheckbox(pages.children, pageIndex,childrenModule.children,module.children)"
>{{page.name}}</Checkbox>
<!---
如果是第四级菜单的话会继续往下一层遍历
-->
<template v-if="page.children && page.children.length > 0">
<!--div 五级权限模块 start-->
<div :key="page.key" class="isLevel-four">
<Checkbox
:label="page.key"
@click.prevent.native="selectCheckbox(page)"
class="level-three-label"
>{{page.name}}</Checkbox>
<!--div 五级权限的功能点 start-->
<div
class="level-four"
v-if="page.children && page.children.length > 0"
>
<template
v-for="(fiveLevelFunction, fiveLevelIndex) in page.children"
>
<Checkbox
:label="fiveLevelFunction.key"
@click.prevent.native="selectCheckbox(fiveLevelFunction)"
>{{fiveLevelFunction.name}}</Checkbox>
</template>
</div>
<!--div 五级权限的功能点 start-->
</div>
<!--div 五级权限模块 start-->
</template>
<template v-else>
<Checkbox
:key="page.key"
:label="page.key"
@click.prevent.native="selectCheckbox(page)"
>{{page.name}}</Checkbox>
</template>
</template>
</div>
<!--div 四级权限模块 start-->
</div>
<Checkbox
:key="pages.key"
:label="pages.key"
@click.prevent.native="selectCheckbox(childrenModule.children,pagesIndex,module.children)"
@click.prevent.native="selectCheckbox(pages)"
v-else
>{{pages.name}}</Checkbox>
</template>
@@ -101,6 +134,8 @@ export default {
return {
// 权限数据
tree: [],
//权限铺平的map
treeMap: null,
loading: false,
// 提交保存数据
rolePower: {
@@ -133,118 +168,95 @@ export default {
activated() {},
methods: {
// 勾选权限
selectCheckbox(
currentModuleList,
moduleIndex,
upOneModuleList,
upTwoModuleList
) {
let module = currentModuleList[moduleIndex];
selectCheckbox(module) {
// 是否勾选
let findIndex = this.checkedData.indexOf(module.key);
if (findIndex !== -1) {
this.spliceCheck(module);
// 取消的上级ID
// 判断同级是否全部已取消勾选
let currentLevelAllUnchecked = this.isUnCheckedThisLevel(
currentModuleList
);
if (currentLevelAllUnchecked && upOneModuleList) {
// 判断上级是否全部已取消勾选
let upOneLevelAllUnchecked = this.isUnCheckedThisLevel(
upOneModuleList
);
if (upOneLevelAllUnchecked && upTwoModuleList) {
// 判断上上级是否全部已取消勾选
this.isUnCheckedThisLevel(upTwoModuleList);
//取消自己和孩子
this.removeCheckAndChidlrenCheck(module);
//判断父级及其以上是否有重复
if (module.parentKey) {
let parentPrivilege = this.treeMap.get(module.parentKey);
if (parentPrivilege) {
this.unCheckedParent(parentPrivilege);
}
}
} else {
// 选中子级所有checkBox
this.addCheck(module);
// 选中上级组件
if (module.parentKey) {
if (
this.checkedData.findIndex(val => val === module.parentKey) === -1
) {
this.checkedData.push(module.parentKey);
}
}
// 选中上上级组件
if (upOneModuleList) {
let upOneFindIndex = upOneModuleList.findIndex(
e => e.key === module.parentKey
);
let upOneFind =
upOneFindIndex === -1 ? null : upOneModuleList[upOneFindIndex];
if (
upOneFind &&
upOneFind.parentKey &&
this.checkedData.findIndex(val => val === upOneFind.parentKey) ===
-1
) {
this.checkedData.push(upOneFind.parentKey);
}
// 选中上上上级组件
if (upTwoModuleList) {
console.log(1111, upTwoModuleList, upOneFind);
let upTwoFindIndex = upTwoModuleList.findIndex(
e => e.key === upOneFind.parentKey
);
let upTwoFind =
upTwoFindIndex === -1 ? null : upTwoModuleList[upTwoFindIndex];
if (
upTwoFind &&
upTwoFind.parentKey &&
this.checkedData.findIndex(val => val === upTwoFind.parentKey) ===
-1
) {
this.checkedData.push(upTwoFind.parentKey);
this.addCheckAndChildrenCheck(module);
// 父类集合选中
let parentKey = module.parentKey;
while (parentKey != null) {
let parentPrivilege = this.treeMap.get(parentKey);
if (parentPrivilege) {
let findIndex = this.checkedData.findIndex(val => val == parentKey);
if (findIndex == -1) {
this.checkedData.push(parentKey);
}
parentKey = parentPrivilege.parentKey;
} else {
parentKey = null;
}
}
}
},
// 判断同级是否全部已取消勾选
isUnCheckedThisLevel(moduleList) {
let thisLevelAllUnchecked = true;
moduleList.forEach(e => {
let brotherIndex = this.checkedData.findIndex(val => val == e.key);
if (brotherIndex != -1) {
thisLevelAllUnchecked = false;
}
});
if (thisLevelAllUnchecked) {
let number = this.checkedData.findIndex(
e => e == moduleList[0].parentKey
);
if (number != -1) {
this.checkedData.splice(number, 1);
// 取消父级check
unCheckedParent(parentPrivilege) {
if (
parentPrivilege &&
parentPrivilege.children &&
parentPrivilege.children.length > 0
) {
if (!this.judgeArrayExistCheck(parentPrivilege.children)) {
let findIndex = this.checkedData.findIndex(
val => val == parentPrivilege.key
);
if (findIndex != -1) {
this.checkedData.splice(findIndex, 1);
}
parentPrivilege = this.treeMap.get(parentPrivilege.parentKey);
this.unCheckedParent(parentPrivilege);
}
}
return thisLevelAllUnchecked;
},
//判断权限数组是否有选中的有返回true,没有任何选中返回false
judgeArrayExistCheck(privilegeArray) {
if (!privilegeArray) {
return false;
}
for (let privilege of privilegeArray) {
let findIndex = this.checkedData.findIndex(val => val == privilege.key);
if (findIndex != -1) {
return true;
}
}
return false;
},
// 选中子级所有checkBox
addCheck(module) {
addCheckAndChildrenCheck(module) {
let findIndex = this.checkedData.findIndex(val => val == module.key);
if (findIndex == -1) {
this.checkedData.push(module.key);
}
if (module.children) {
module.children.forEach(item => {
this.addCheck(item);
this.addCheckAndChildrenCheck(item);
});
}
},
// 取消自己和下级勾选
spliceCheck(module) {
removeCheckAndChidlrenCheck(module) {
let findIndex = this.checkedData.findIndex(val => val == module.key);
if (findIndex != -1) {
this.checkedData.splice(findIndex, 1);
}
if (module.children) {
module.children.forEach(item => {
this.spliceCheck(item);
this.removeCheckAndChidlrenCheck(item);
});
}
},
@@ -272,13 +284,23 @@ export default {
this.$Spin.hide();
}
},
//将权限tree 打平成map
tree2map(tree) {
if (tree) {
for (const privilege of tree) {
this.treeMap.set(privilege.key, privilege);
this.tree2map(privilege.children);
}
}
},
// 获取角色可选的功能权限
async getListPrivilegeByRoleId(id) {
try {
let response = await privilegeApi.getListPrivilegeByRoleId(id);
let datas = response.data;
this.tree = datas.privilege;
console.log('tree', this.tree);
this.treeMap = new Map();
this.tree2map(this.tree);
this.checkedData = datas.selectedKey || [];
} catch (e) {
console.error(e);
@@ -360,14 +382,14 @@ export default {
border-bottom: 1px solid rgb(240, 240, 240);
padding: 10px 0;
}
.level-teo {
.level-two {
display: flex;
align-items: center;
margin-left: 4%;
position: relative;
border-bottom: 1px solid rgb(240, 240, 240);
line-height: 40px;
.level-teo-label {
.level-two-label {
width: 12%;
min-width: 120px;
}
@@ -381,15 +403,21 @@ export default {
.isLevel-four {
display: flex;
align-items: center;
border-bottom: 1px rgb(240, 240, 240) solid;
.level-three-label {
width: 12%;
min-width: 120px;
}
.Level-four {
.level-four {
padding-left: 4%;
flex: 1;
min-height: 40px;
border-left: 1px rgb(240, 240, 240) solid;
.level-five {
padding-left: 4%;
min-height: 40px;
border-left: 1px rgb(240, 240, 240) solid;
}
}
}
}

View File

@@ -17,7 +17,7 @@
<Form-item label="功能Key" prop="functionKey" required>
<Input disabled placeholder="请输入功能Key" v-model="privilege.functionKey"></Input>
</Form-item>
<Form-item label="Url" required>
<Form-item label="Url">
<Select filterable multiple v-model="urlArray">
<OptionGroup :key="i" :label="items.label" v-for="(items, i) in urlList">
<Option :key="j" :label="item.url" :value="item.name" v-for="(item, j) in items.data">

View File

@@ -113,7 +113,7 @@
:title="formData.title"
:typeDisabled="typeDisabled"
@closeModal="closeModal"
@updateMenuSuccess="getPrivilegeList"
@updateMenuSuccess="loadPrivilegeTableData"
></privilege-form>
</Col>
</Row>
@@ -366,6 +366,16 @@ console.error(privilegeTree)
pointsChangeNum++;
}
}
//如果服务端比前端的要多,则说明需要删除
if(serverPointData.length > frontPrivilegeData.length){
for (const serverFunction of serverPointData) {
if(frontPrivilegeData.findIndex(e => e.name === serverFunction.functionKey ) === -1){
//前端的功能点呗删除
pointsChangeNum++;
}
}
}
this.pointsChangeNum = pointsChangeNum;
this.privilegeTableData = frontPrivilegeData;
},