Commit 71dd8c44 authored by trumansdo's avatar trumansdo
Browse files

- 更新README.md

parent ed4f1651
# springboot-plus 基于vue-element-admin 改版 # springboot-plus 基于vue-element-admin 改版 
### 开发说明
1. 技术栈说明
2. 前端配置架构说明
3. 后端配置架构说明
4. 自定义开发的<General-Page> 组件说明
#### 技术栈说明
> 主要前端技术:
1. Vue+Vuex+Vue Router 2.6 响应式js编程库
2. Element-UI 2.13 基于vue的饿了么UI组件
3. Axios 0.18.1 基于Promise异步编程的请求库
4. lodash 4.17.15 js工具库
5. tinyMCE 未来会使用到的富文本编辑器js库
6. qs 6.9.1 object转请求参数编码库
7. mockjs 1.0.1-beta3 前端接口mock数据库
> 主要后端技术(不列版本,保持更新最新版本号):
1. springboot
2. beetl/beetlsql dao框架
3. hutool 工具库
4. caffeine JVM缓存库
5. hikaricp 连接池
6. undertow 听说比tomcat好的服务器
7. hibernate-validator 参数校验
8. log4j2 日志框架
9. jose4j jwt库
10. jxls2 模板化excel导入导出库
#### 前端配置架构说明
&emsp; 前端项目使用了PanJia大神的vue-element-admin项目,若前端有bug,可以先到vue-element-admin项目查看。
```
主要目录:
src
api:数据请求接口
component:自定义公共vue组件
router:静态路由表
services:业务js代码
view:功能页面
utils:自定义工具库,建议优先使用lodash
```
约定:
> 前端代码中的object的key永远用下划线,在axios的拦截器(代码在src/util/request.js中)中复制一份转为驼峰式。后端永远返回下划线的object,已通过Jackson配置处理。
> 在axios中每次请求都将jwt的token携带了,后端保持五分钟内有效,超过五分钟没有任何请求。token失效,需要重新登录。
> 每个组件使用必须添加key属性,key不同,复用组件的生命周期才不会共用。简单使用Math.random()赋值。实际使用可以考虑实现snowflake等id赋值。
&emsp; 主要的配置:
** 动态路由:**
`警告`,此功能的vue bug让人有点懵,建议等我重新测试。凡是前端需要跳转链接页面的,都属于动态路由部分,目前使用动态路由需要完成数据库数据插入,不显示在菜单的路由也挂在到同Menu级别下;同时在前端代码中也需要填入静态路由表(在src/router/maps下的对应文件中)。动态路由代码的文件观看顺序:src/permission.js, src/store/modules/permission.js。
原理:后台数据库存放路由/菜单,根据登录用户权限,查出路由树。此时路由树没有component属性,前端同时存放所有路由树,有component属性,在遍历后端传递的路由树在前端静态路由树中将component拼接到后端传递的路由树中。以此实现动态路由.。`注:这可能是vue的bug导致,经由另一个网友项目测试,vue官网的路由懒加载是可行的,但是在我项目中不可行。`
**文件上传:**
在 src/components/Upload/FileUpload.vue 中封装了element-ui的文件上传组件,使用axios实现的上传逻辑。可以直接使用该组件。
**级联选择器:**
封装elementUI的el-cascader,因为原本的级联器的选中值是一个数组形式的,这样还得处理选中值变成请求参数中的key/value形式,这样很麻烦,所以重新封装了一下。代码在src/components/Wrapper/Sp-cascader。使用可以参考views/user/add-user-role.vue
**通用页面组件<General-Page>:**
代码在src/components/GeneralPage目录。目的是为了后期代码生成,只生成后端代码,不用生成复杂的前端代码。可以主要参考view/user的实现。包括头部区域条件搜索,中间数据表格和分页,增删改查四个按钮。增加/修改的弹出编辑弹窗。预留了功能按钮组插槽、搜索条件插槽、编辑弹窗插槽,用于扩展自定义的功能和表单。
#### 后端配置架构说明
```
admin-core :基本entity、dao、service,主要配置,Platform service等核心功能
admin-console:后台管理代码
```
**主要配置:**
请求和响应的Jackson配置,驼峰式转下划线
字典字段使用枚举,实现DictTypeEnum接口,参照StateEnum
beetlsql主要配置:DictTypeEnum字段与数据库字段的类型转换;简单关联结果集映射,代码参照conf/beetl/JsonBeanProcessor。使用参照coreFunction.md。
自定义注解 RequestBodyPlus,实现用jsonPath直接从json参数中提取值注入controller参数,减少不必要的实体类接收json参数。
后台Jose4j实现jwt,代码在JoseJwtUtil。
代码风格使用intellij-java-google-style.xml,idea可直接在code style中导入。
**约定**
在旧版和新版的代码未完成更替完成时,controller和Service层类命名以ElController和ElService结尾。
...@@ -138,6 +138,20 @@ public class UserConsoleElController { ...@@ -138,6 +138,20 @@ public class UserConsoleElController {
return JsonResult.success(); return JsonResult.success();
} }
/**
* 管理员重置用户密码
*
* @return
*/
@PostMapping("/changePassword")
@Function("user.reset")
@ResponseBody
public JsonResult changePassword(
@RequestBodyPlus("id") Long id, @RequestBodyPlus("password") String password) {
userConsoleService.resetPassword(id, password);
return JsonResult.success();
}
@PostMapping("/excel/export") @PostMapping("/excel/export")
@Function("user.export") @Function("user.export")
public JsonResult<String> export(@RequestBody CoreUserParam coreUserParam) { public JsonResult<String> export(@RequestBody CoreUserParam coreUserParam) {
......
import cn.hutool.core.util.EnumUtil; import cn.hutool.core.collection.CollUtil;
import com.ibeetl.admin.ConsoleApplication; import com.ibeetl.admin.ConsoleApplication;
import com.ibeetl.admin.core.dao.CoreFunctionDao; import com.ibeetl.admin.core.dao.CoreFunctionDao;
import com.ibeetl.admin.core.entity.CoreRoute; import com.ibeetl.admin.core.entity.CoreRoute;
import entity.CmsBlog; import entity.CmsBlog;
import entity.CmsBlogTypeEnum; import entity.CmsBlogTypeEnum;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import org.beetl.sql.core.SQLManager; import org.beetl.sql.core.SQLManager;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
...@@ -36,4 +46,5 @@ public class CustomBeanProcessorTest { ...@@ -36,4 +46,5 @@ public class CustomBeanProcessorTest {
blog.setCreateUserId(1L); blog.setCreateUserId(1L);
sqlManager.lambdaQuery(CmsBlog.class).insert(blog); sqlManager.lambdaQuery(CmsBlog.class).insert(blog);
} }
} }
import java.io.Serializable;
import lombok.Data;
@Data
public class GetLastProductByJobsBean implements Serializable {
private String jobNo;
private Integer operNo;
private String createBy;
}
\ No newline at end of file
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import org.junit.Test;
public class SimpleTest {
@Test
public void testStream() {
GetLastProductByJobsBean b1 = new GetLastProductByJobsBean();
b1.setJobNo("JB05");
b1.setOperNo(60);
b1.setCreateBy("a");
GetLastProductByJobsBean b2 = new GetLastProductByJobsBean();
b2.setJobNo("JF00");
b2.setOperNo(10);
b2.setCreateBy("b");
GetLastProductByJobsBean b3 = new GetLastProductByJobsBean();
b3.setJobNo("JF00");
b3.setOperNo(20);
b3.setCreateBy("c");
List<GetLastProductByJobsBean> lists = CollUtil.newArrayList(b1, b2, b3);
Map<String, Map<Integer, String>> collect =
lists.stream()
.collect(
Collectors.groupingBy(
GetLastProductByJobsBean::getJobNo,
Collectors.groupingBy(
k -> k.getOperNo(),
new Collector<GetLastProductByJobsBean, StringBuffer, String>() {
@Override
public Supplier<StringBuffer> supplier() {
// 相当于做一个容器
return () -> new StringBuffer();
}
@Override
public BiConsumer<StringBuffer, GetLastProductByJobsBean> accumulator() {
// 这里将真的值存放到上面的容器里
return (o, getLastProductByJobsBean) ->
o.append(getLastProductByJobsBean.getCreateBy());
}
@Override
public BinaryOperator<StringBuffer> combiner() {
// 这里冲突里就用第二个吧,其实用不到,不是map的容器
return (o, o2) -> o2;
}
@Override
public Function<StringBuffer, String> finisher() {
return o -> o.toString();
}
@Override
public Set<Characteristics> characteristics() {
return Collections.unmodifiableSet(
EnumSet.of(
Collector.Characteristics.UNORDERED,
Collector.Characteristics.IDENTITY_FINISH));
}
})));
System.out.println(collect);
}
@Test
public void music() {
String signStr = "C,Db,D,Eb,E,F,F#,G,Ab,A,Bb,B";
List<String> signList = StrUtil.split(signStr, ',');
List<String> allSignList = new ArrayList<>();
for (int i = 0; i <= 8; i++) {
for (String sign : signList) {
allSignList.add(sign + i);
}
}
allSignList = CollUtil.sub(allSignList, 9, 97);
printAll(allSignList);
signStr =
"C,Db,D,Eb,E,F,F#,G,Ab,A,Bb,B,C,Db,D,Eb,E,F,F#,G,Ab,A,Bb,B,C,Db,D,Eb,E,F,F#,G,Ab,A,Bb,B,C,Db,D,Eb,E,F,F#,G,Ab,A,Bb,B";
signList = StrUtil.split(signStr, ',');
int[] major = new int[] {2, 2, 1, 2, 2, 2, 1};
int[] minor = new int[] {2, 1, 2, 2, 1, 2, 2};
Map<String, Map<String, List<String>>> rsMaps = new LinkedHashMap<>();
String majorStr = "Major";
String minorStr = "Minor";
rsMaps.put(majorStr, new LinkedHashMap<>());
rsMaps.put(minorStr, new LinkedHashMap<>());
for (int i = 0; i < 12; i++) {
String lead = signList.get(i);
List rs = new ArrayList();
rs.add(lead);
int previous = i;
for (int j = 0; j < major.length; j++) {
previous = previous + major[j];
String t = signList.get(previous);
rs.add(t);
}
rsMaps.get(majorStr).put(lead, CollUtil.newArrayList(rs));
rs.clear();
rs.add(lead);
previous = i;
for (int j = 0; j < minor.length; j++) {
previous = previous + minor[j];
String t = signList.get(previous);
rs.add(t);
}
rsMaps.get(minorStr).put(lead, CollUtil.newArrayList(rs));
}
printRsmap(rsMaps);
List<Map<String, List<String>>> relationMaps = new ArrayList<>();
Set<Entry<String, List<String>>> majorEntries = rsMaps.get(majorStr).entrySet();
Set<Entry<String, List<String>>> minorEntries = rsMaps.get(minorStr).entrySet();
for (Entry<String, List<String>> majorEntry : majorEntries) {
Map<String, List<String>> tempRelMap = new LinkedHashMap<>();
String majorEntryKey = majorEntry.getKey();
tempRelMap.put(majorEntryKey + "-" + majorStr, majorEntry.getValue());
for (Entry<String, List<String>> minorEntry : minorEntries) {
boolean isRelation = isRelation(majorEntry.getValue(), minorEntry.getValue());
if (isRelation) {
tempRelMap.put(minorEntry.getKey() + "-" + minorStr, minorEntry.getValue());
}
}
relationMaps.add(tempRelMap);
}
printRelMap(relationMaps);
}
private void printRelMap(List<Map<String, List<String>>> relationMaps) {
String majorStr = "Major";
String minorStr = "Minor";
for (Map<String, List<String>> relationMap : relationMaps) {
for (Entry<String, List<String>> entry : relationMap.entrySet()) {
String[] split = entry.getKey().split("-");
String n = split[1].equals(majorStr)?"大调":"小调";
System.out.println(split[0]+n+" : " +CollUtil.join(entry.getValue(), ","));
}
System.out.println("* * * ");
}
}
private void printRsmap(Map<String, Map<String, List<String>>> rsMaps) {
String majorStr = "Major";
String minorStr = "Minor";
Map<String, List<String>> majorMaps = rsMaps.get(majorStr);
System.out.println("所有的自然大调:");
for (Entry<String, List<String>> entry : majorMaps.entrySet()) {
System.out.println(entry.getKey()+" : "+CollUtil.join(entry.getValue(), ","));
}
Map<String, List<String>> minorMaps = rsMaps.get(minorStr);
System.out.println("所有的自然小调:");
for (Entry<String, List<String>> entry : minorMaps.entrySet()) {
System.out.println(entry.getKey()+" : "+CollUtil.join(entry.getValue(), ","));
}
}
private void printAll(List<String> allSignList) {
System.out.println("88键钢琴键位从左往右:"+CollUtil.join(allSignList, ","));
System.out.println("A4是标准音440HZ");
}
// 降E大调音阶是<Eb、F、G、Ab、Bb、C、D>,c小调的音阶是<C、D、Eb、F、G、Ab、Bb>
private boolean isRelation(List<String> majors, List<String> minors) {
List<String> copyMajors = CollUtil.newArrayList(majors);
copyMajors.remove(copyMajors.size() - 1);
List<String> copyMiniors = CollUtil.newArrayList(minors);
copyMiniors.remove(copyMiniors.size() - 1);
for (int i = 0; i < copyMajors.size(); i++) {
String major = copyMajors.get(i);
copyMiniors.remove(major);
}
return copyMiniors.isEmpty();
}
}
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
<properties> <properties>
<maven.test.skip>true</maven.test.skip> <maven.test.skip>true</maven.test.skip>
<druid.version>1.1.10</druid.version> <druid.version>1.1.10</druid.version>
<lombok.version>1.18.2</lombok.version> <lombok.version>1.18.12</lombok.version>
<disruptor.version>3.4.2</disruptor.version> <disruptor.version>3.4.2</disruptor.version>
</properties> </properties>
<dependencies> <dependencies>
...@@ -70,7 +70,7 @@ ...@@ -70,7 +70,7 @@
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>${lombok.version}</version> <version>${lombok.version}</version>
<optional>true</optional> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>
......
...@@ -68,7 +68,7 @@ ...@@ -68,7 +68,7 @@
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>1.18.8</version> <version>1.18.12</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
</dependencies> </dependencies>
......
/* /*
* @Author: 一日看尽长安花 * @Author: 一日看尽长安花
* @since: 2019-09-04 20:55:14 * @since: 2019-09-04 20:55:14
* @LastEditTime: 2020-04-26 20:49:26 * @LastEditTime: 2020-04-27 14:58:13
* @LastEditors: 一日看尽长安花 * @LastEditors: 一日看尽长安花
* @Description: * @Description:
*/ */
...@@ -130,3 +130,15 @@ export function deleteUserRoles(data) { ...@@ -130,3 +130,15 @@ export function deleteUserRoles(data) {
data data
}); });
} }
/**
* 修改用户密码
* @param {Object} data {id,password}
*/
export function changePassword(data) {
return request({
url: '/users/changePassword',
method: 'post',
data
});
}
/* /*
* @Author: 一日看尽长安花 * @Author: 一日看尽长安花
* @since: 2020-01-13 23:12:07 * @since: 2020-01-13 23:12:07
* @LastEditTime: 2020-04-19 20:32:05 * @LastEditTime: 2020-04-27 15:00:42
* @LastEditors: 一日看尽长安花 * @LastEditors: 一日看尽长安花
* @Description: 与业务有关的非纯api的js * @Description: 与业务有关的非纯api的js
*/ */
...@@ -50,7 +50,7 @@ export function handleCascaderValue(obj, keyNames = []) { ...@@ -50,7 +50,7 @@ export function handleCascaderValue(obj, keyNames = []) {
const path = keyNames[i]; const path = keyNames[i];
const node = get(obj, path); const node = get(obj, path);
const node_type = Object.prototype.toString.call(node); const node_type = Object.prototype.toString.call(node);
if (node_type !== '[object String]') { if (node_type === '[object Object]') {
obj = omit(obj, path); obj = omit(obj, path);
} }
} }
......
<!-- <!--
* @Author: 一日看尽长安花 * @Author: 一日看尽长安花
* @since: 2020-04-05 13:21:44 * @since: 2020-04-05 13:21:44
* @LastEditTime: 2020-04-26 18:32:27 * @LastEditTime: 2020-04-27 14:59:57
* @LastEditors: 一日看尽长安花 * @LastEditors: 一日看尽长安花
* @Description: * @Description:
--> -->
...@@ -116,9 +116,8 @@ export default { ...@@ -116,9 +116,8 @@ export default {
this.init(); this.init();
}, },
createUserRole() { createUserRole() {
debugger;
const Vue = this; const Vue = this;
handleCascaderValue(Vue.dialogData_, ['orgId', 'roleId']); handleCascaderValue(Vue.dialogData_, ['org_id', 'role_id']);
let params = { let params = {
user_id: Vue.dialogData_.id, user_id: Vue.dialogData_.id,
name: Vue.dialogData_.name, name: Vue.dialogData_.name,
...@@ -129,6 +128,12 @@ export default { ...@@ -129,6 +128,12 @@ export default {
addUserRoles(params).then(response => { addUserRoles(params).then(response => {
const { code, message, data } = { ...response }; const { code, message, data } = { ...response };
Vue.$nextTick(() => { Vue.$nextTick(() => {
Vue.$notify({
title: '成功',
message: '授权角色成功',
type: 'success',
duration: 2000
});
Vue.init(); Vue.init();
}); });
}); });
......
<!--
* @Author: 一日看尽长安花
* @since: 2020-04-27 09:46:14
* @LastEditTime: 2020-04-27 18:27:34
* @LastEditors: 一日看尽长安花
* @Description:
-->
<template id="changePassword">
<div class="sp-edit-dialog">
<el-dialog
:fullscreen="true"
:center="true"
:destroy-on-close="true"
:show-close="false"
:title="title"
:visible="visible"
:close-on-click-modal="false"
@close="closeDialog"
>
<div class="sp-dialog-container">
<el-form
ref="editForm"
:model="dialogData_"
label-position="right"
label-width="10vw"
class="sp-form"
status-icon
:rules="rules"
>
<el-form-item label="用户名">
<el-input v-model="dialogData_['name']" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="用户账号">
<el-input v-model="dialogData_['code']" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input
v-model="dialogData_['password']"
type="password"
></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="confirm_password">
<el-input
v-model="dialogData_['confirm_password']"
type="password"
></el-input>
</el-form-item>
</el-form>
</div>
<template v-slot:footer>
<div class="sp-dialog-footer">
<el-button @click="closeDialog">
取消
</el-button>
<el-button type="primary" @click="changePassword">
确定
</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script>
import { changePassword } from '@/api/user';
export default {
name: 'ChangePassword',
components: {},
props: {
dialogData: {
type: Object,
default: function() {
return {};
}
},
visible: {
type: Boolean,
default: false
},
title: {
type: String,
default: '添加角色'
}
},
data() {
var passwordValidator = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入密码'));
} else {
if (this.dialogData_.confirm_password !== '') {
this.$refs.editForm.validateField('confirm_password');
}
callback();
}
};
var confirmPasswordValidator = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'));
} else if (value !== this.dialogData_.password) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
};
return {
dialogData_: { ...this.dialogData },
rules: {
password: [{ validator: passwordValidator, trigger: 'blur' }],
confirm_password: [
{ validator: confirmPasswordValidator, trigger: 'blur' }
]
}
};
},
methods: {
init() {
this.$emit('update:visible', false);
},
closeDialog() {
this.init();
},
changePassword() {
debugger;
const Vue = this;
let params = {
id: Vue.dialogData_.id,
password: Vue.dialogData_.password
};
changePassword(params).then(response => {
const { code, message, data } = { ...response };
Vue.$nextTick(() => {
Vue.$notify({
title: '成功',
message: '修改密码成功',
type: 'success',
duration: 2000
});
Vue.init();
});
});
}
}
};
</script>
<style scoped>
.sp-dialog-container {
margin: 0 auto;
width: 50%;
}
.el-cascader {
width: 100%;
}
</style>
<!-- <!--
* @Author: 一日看尽长安花 * @Author: 一日看尽长安花
* @since: 2019-10-12 15:43:18 * @since: 2019-10-12 15:43:18
* @LastEditTime: 2020-04-26 18:31:56 * @LastEditTime: 2020-04-27 15:02:24
* @LastEditors: 一日看尽长安花 * @LastEditors: 一日看尽长安花
* @Description: * @Description:
--> -->
...@@ -72,6 +72,16 @@ ...@@ -72,6 +72,16 @@
> >
操作角色 操作角色
</el-button> </el-button>
<el-button
class="filter-item"
style="margin-left: 10px;"
type="primary"
size="mini"
icon="el-icon-edit"
@click="showChangePswAlert"
>
修改密码
</el-button>
<el-button <el-button
class="filter-item" class="filter-item"
style="margin-left: 10px;" style="margin-left: 10px;"
...@@ -147,6 +157,14 @@ ...@@ -147,6 +157,14 @@
</el-form-item> </el-form-item>
</template> </template>
</general-page> </general-page>
<change-password
:key="Math.random()"
ref="editDialog"
:dialog-data="chgPwsDialogData"
title="修改密码"
:visible.sync="chgPwsVisible"
>
</change-password>
</div> </div>
</template> </template>
...@@ -154,6 +172,7 @@ ...@@ -154,6 +172,7 @@
import GeneralPage from '@/components/GeneralPage'; import GeneralPage from '@/components/GeneralPage';
import FileUpload from '@/components/Upload/FileUpload'; import FileUpload from '@/components/Upload/FileUpload';
import SpCascader from '@/components/Wrapper/SpCascader'; import SpCascader from '@/components/Wrapper/SpCascader';
import ChangePassword from './change-password';
import { import {
users, users,
...@@ -171,7 +190,7 @@ import { layzyLoadOrgTree } from '@/services/org'; ...@@ -171,7 +190,7 @@ import { layzyLoadOrgTree } from '@/services/org';
export default { export default {
name: 'CoreUsersView', name: 'CoreUsersView',
components: { GeneralPage, FileUpload, SpCascader }, components: { GeneralPage, FileUpload, SpCascader, ChangePassword },
props: {}, props: {},
data() { data() {
return { return {
...@@ -193,7 +212,9 @@ export default { ...@@ -193,7 +212,9 @@ export default {
stateCascaderProps: { stateCascaderProps: {
checkStrictly: true, checkStrictly: true,
options: [] options: []
} },
chgPwsDialogData: {},
chgPwsVisible: false
}; };
}, },
computed: {}, computed: {},
...@@ -309,10 +330,10 @@ export default { ...@@ -309,10 +330,10 @@ export default {
* 将回调延迟到下次 DOM 更新循环之后执行。 * 将回调延迟到下次 DOM 更新循环之后执行。
* 而数据更新就代表dom更新,所以如果创建成功,数据就会更新 * 而数据更新就代表dom更新,所以如果创建成功,数据就会更新
*/ */
thVueis.$nextTick(() => { Vue.$nextTick(() => {
Vue.$notify({ Vue.$notify({
title: '成功', title: '成功',
message: '修改成功1', message: '修改成功',
type: 'success', type: 'success',
duration: 2000 duration: 2000
}); });
...@@ -413,6 +434,20 @@ export default { ...@@ -413,6 +434,20 @@ export default {
const _selected = _table.selection[0]; const _selected = _table.selection[0];
const _router = this.$router; const _router = this.$router;
_router.push({ name: 'ManagerUserRole', params: { id: _selected.id } }); _router.push({ name: 'ManagerUserRole', params: { id: _selected.id } });
},
showChangePswAlert() {
const _table = this.$children[0].$refs.dataTableGP.$refs.dataTable;
const isSelection = _table.selection.length > 0 ? true : false;
if (!isSelection) {
this.$message({
type: 'warning',
message: '请选择一行数据'
});
return;
}
const _selected = _table.selection[0];
this.chgPwsVisible = true;
this.chgPwsDialogData = _selected;
} }
} }
}; };
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment