优化代码生成器,优化角色级别配置

pull/302/head
Elune 2019-12-22 10:38:35 +08:00
parent 5f41318b9d
commit 4e0deae13d
11 changed files with 160 additions and 148 deletions

View File

@ -3,6 +3,7 @@ package me.zhengjie.service.impl;
import me.zhengjie.domain.GenConfig;
import me.zhengjie.repository.GenConfigRepository;
import me.zhengjie.service.GenConfigService;
import me.zhengjie.utils.StringUtils;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
@ -36,25 +37,27 @@ public class GenConfigServiceImpl implements GenConfigService {
@Override
@CachePut(key = "#p0")
public GenConfig update(String tableName, GenConfig genConfig) {
// 自动设置Api路径注释掉前需要同步取消前端的注释
String separator = File.separator;
String[] paths;
String symbol = "\\";
if (symbol.equals(separator)) {
paths = genConfig.getPath().split("\\\\");
} else {
paths = genConfig.getPath().split(File.separator);
}
StringBuilder api = new StringBuilder();
for (String path : paths) {
api.append(path);
api.append(separator);
if ("src".equals(path)) {
api.append("api");
break;
// 如果 api 路径为空,则自动生成路径
if(StringUtils.isBlank(genConfig.getApiPath())){
String separator = File.separator;
String[] paths;
String symbol = "\\";
if (symbol.equals(separator)) {
paths = genConfig.getPath().split("\\\\");
} else {
paths = genConfig.getPath().split(File.separator);
}
StringBuilder api = new StringBuilder();
for (String path : paths) {
api.append(path);
api.append(separator);
if ("src".equals(path)) {
api.append("api");
break;
}
}
genConfig.setApiPath(api.toString());
}
genConfig.setApiPath(api.toString());
return genConfigRepository.save(genConfig);
}
}

View File

@ -1,20 +1,23 @@
package me.zhengjie;
import me.zhengjie.annotation.AnonymousAccess;
import me.zhengjie.utils.SpringContextHolder;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author Zheng Jie
* @date 2018/11/15 9:20:19
*/
@EnableAsync
@RestController
@SpringBootApplication
@EnableTransactionManagement
public class AppRun {
@ -31,7 +34,17 @@ public class AppRun {
@Bean
public ServletWebServerFactory webServerFactory() {
TomcatServletWebServerFactory fa = new TomcatServletWebServerFactory();
fa.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> connector.setProperty("relaxedQueryChars", "[]{}"));
fa.addConnectorCustomizers(connector -> connector.setProperty("relaxedQueryChars", "[]{}"));
return fa;
}
/**
* 访
* @return /
*/
@GetMapping("/")
@AnonymousAccess
public String index() {
return "Backend service started successfully";
}
}

View File

@ -35,4 +35,11 @@ public interface RoleRepository extends JpaRepository<Role, Long>, JpaSpecificat
@Modifying
@Query(value = "delete from roles_menus where menu_id = ?1",nativeQuery = true)
void untiedMenu(Long id);
/**
*
* @param permission /
* @return /
*/
Role findByPermission(String permission);
}

View File

@ -8,6 +8,7 @@ import me.zhengjie.modules.system.domain.Role;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.system.service.RoleService;
import me.zhengjie.modules.system.service.UserService;
import me.zhengjie.modules.system.service.dto.RoleDto;
import me.zhengjie.modules.system.service.dto.RoleQueryCriteria;
import me.zhengjie.modules.system.service.dto.RoleSmallDto;
import me.zhengjie.modules.system.service.dto.UserDto;
@ -21,7 +22,6 @@ import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
@ -81,9 +81,7 @@ public class RoleController {
@ApiOperation("获取用户级别")
@GetMapping(value = "/level")
public ResponseEntity<Object> getLevel(){
UserDto user = userService.findByName(SecurityUtils.getUsername());
List<Integer> levels = roleService.findByUsersId(user.getId()).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList());
return new ResponseEntity<>(Dict.create().set("level", Collections.min(levels)),HttpStatus.OK);
return new ResponseEntity<>(Dict.create().set("level", getLevels(null)),HttpStatus.OK);
}
@Log("新增角色")
@ -94,6 +92,7 @@ public class RoleController {
if (resources.getId() != null) {
throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
}
getLevels(resources.getLevel());
return new ResponseEntity<>(roleService.create(resources),HttpStatus.CREATED);
}
@ -102,6 +101,7 @@ public class RoleController {
@PutMapping
@PreAuthorize("@el.check('roles:edit')")
public ResponseEntity<Object> update(@Validated(Role.Update.class) @RequestBody Role resources){
getLevels(resources.getLevel());
roleService.update(resources);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
@ -111,7 +111,9 @@ public class RoleController {
@PutMapping(value = "/menu")
@PreAuthorize("@el.check('roles:edit')")
public ResponseEntity<Object> updateMenu(@RequestBody Role resources){
roleService.updateMenu(resources,roleService.findById(resources.getId()));
RoleDto role = roleService.findById(resources.getId());
getLevels(role.getLevel());
roleService.updateMenu(resources,role);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
@ -120,7 +122,31 @@ public class RoleController {
@DeleteMapping
@PreAuthorize("@el.check('roles:del')")
public ResponseEntity<Object> delete(@RequestBody Set<Long> ids){
roleService.delete(ids);
for (Long id : ids) {
RoleDto role = roleService.findById(id);
getLevels(role.getLevel());
}
try {
roleService.delete(ids);
} catch (Throwable e){
ThrowableUtil.throwForeignKeyException(e, "所选角色存在用户关联,请取消关联后再试");
}
return new ResponseEntity<>(HttpStatus.OK);
}
/**
*
* @return /
*/
private int getLevels(Integer level){
UserDto user = userService.findByName(SecurityUtils.getUsername());
List<Integer> levels = roleService.findByUsersId(user.getId()).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList());
int min = Collections.min(levels);
if(level != null){
if(level < min){
throw new BadRequestException("权限不足,你的角色级别:" + min + ",低于操作的角色级别:" + level);
}
}
return min;
}
}

View File

@ -98,12 +98,16 @@ public class RoleServiceImpl implements RoleService {
if(role1 != null && !role1.getId().equals(role.getId())){
throw new EntityExistException(Role.class,"username",resources.getName());
}
role1 = roleRepository.findByPermission(resources.getPermission());
if(role1 != null && !role1.getId().equals(role.getId())){
throw new EntityExistException(Role.class,"permission",resources.getPermission());
}
role.setName(resources.getName());
role.setRemark(resources.getRemark());
role.setDataScope(resources.getDataScope());
role.setDepts(resources.getDepts());
role.setLevel(resources.getLevel());
role.setPermission(resources.getPermission());
roleRepository.save(role);
}
@ -127,11 +131,7 @@ public class RoleServiceImpl implements RoleService {
@Transactional(rollbackFor = Exception.class)
public void delete(Set<Long> ids) {
for (Long id : ids) {
try {
roleRepository.deleteById(id);
}catch (Throwable e){
ThrowableUtil.throwForeignKeyException(e, "该角色存在用户关联,请取消关联后再试");
}
roleRepository.deleteById(id);
}
}

View File

@ -62,18 +62,9 @@ public class ${className}Controller {
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
@DeleteMapping(value = "/{${pkChangeColName}}")
@Log("删除${apiAlias}")
@ApiOperation("删除${apiAlias}")
@PreAuthorize("@el.check('${changeClassName}:del')")
public ResponseEntity<Object> delete(@PathVariable ${pkColumnType} ${pkChangeColName}){
${changeClassName}Service.delete(${pkChangeColName});
return new ResponseEntity<>(HttpStatus.OK);
}
@Log("多选删除${apiAlias}")
@ApiOperation("多选删除${apiAlias}")
@PreAuthorize("@el.check('${changeClassName}:del')")
@DeleteMapping
public ResponseEntity<Object> deleteAll(@RequestBody ${pkColumnType}[] ids) {
${changeClassName}Service.deleteAll(ids);

View File

@ -38,6 +38,11 @@ public class ${className}QueryCriteria{
@Query(type = Query.Type.NOT_EQUAL)
private ${column.columnType} ${column.changeColumnName};
</#if>
<#if column.queryType = 'NotNull'>
/** 不为空 */
@Query(type = Query.Type.NOT_NULL)
private ${column.columnType} ${column.changeColumnName};
</#if>
<#if column.queryType = '>='>
/** 大于等于 */
@Query(type = Query.Type.GREATER_THAN)

View File

@ -50,12 +50,6 @@ public interface ${className}Service {
*/
void update(${className} resources);
/**
* 删除
* @param ${pkChangeColName} /
*/
void delete(${pkColumnType} ${pkChangeColName});
/**
* 多选删除
* @param ids /

View File

@ -27,9 +27,10 @@ import cn.hutool.core.util.IdUtil;
<#if !auto && pkColumnType = 'String'>
import cn.hutool.core.util.IdUtil;
</#if>
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
// 默认不使用缓存
//import org.springframework.cache.annotation.CacheConfig;
//import org.springframework.cache.annotation.CacheEvict;
//import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import me.zhengjie.utils.PageUtil;
@ -46,7 +47,7 @@ import java.util.LinkedHashMap;
* @date ${date}
*/
@Service
@CacheConfig(cacheNames = "${changeClassName}")
//@CacheConfig(cacheNames = "${changeClassName}")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class ${className}ServiceImpl implements ${className}Service {
@ -60,20 +61,20 @@ public class ${className}ServiceImpl implements ${className}Service {
}
@Override
@Cacheable
//@Cacheable
public Map<String,Object> queryAll(${className}QueryCriteria criteria, Pageable pageable){
Page<${className}> page = ${changeClassName}Repository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
return PageUtil.toPage(page.map(${changeClassName}Mapper::toDto));
}
@Override
@Cacheable
//@Cacheable
public List<${className}Dto> queryAll(${className}QueryCriteria criteria){
return ${changeClassName}Mapper.toDto(${changeClassName}Repository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
}
@Override
@Cacheable(key = "#p0")
//@Cacheable(key = "#p0")
public ${className}Dto findById(${pkColumnType} ${pkChangeColName}) {
${className} ${changeClassName} = ${changeClassName}Repository.findById(${pkChangeColName}).orElseGet(${className}::new);
ValidationUtil.isNull(${changeClassName}.get${pkCapitalColName}(),"${className}","${pkChangeColName}",${pkChangeColName});
@ -81,7 +82,7 @@ public class ${className}ServiceImpl implements ${className}Service {
}
@Override
@CacheEvict(allEntries = true)
//@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public ${className}Dto create(${className} resources) {
<#if !auto && pkColumnType = 'Long'>
@ -104,7 +105,7 @@ public class ${className}ServiceImpl implements ${className}Service {
}
@Override
@CacheEvict(allEntries = true)
//@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void update(${className} resources) {
${className} ${changeClassName} = ${changeClassName}Repository.findById(resources.get${pkCapitalColName}()).orElseGet(${className}::new);
@ -127,14 +128,7 @@ public class ${className}ServiceImpl implements ${className}Service {
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void delete(${pkColumnType} ${pkChangeColName}) {
${changeClassName}Repository.deleteById(${pkChangeColName});
}
@Override
@CacheEvict(allEntries = true)
//@CacheEvict(allEntries = true)
public void deleteAll(${pkColumnType}[] ids) {
for (${pkColumnType} id : ids) {
${changeClassName}Repository.deleteById(${pkChangeColName});

View File

@ -8,13 +8,7 @@ export function add(data) {
})
}
export function del(${pkChangeColName}) {
return request({
url: 'api/${changeClassName}/' + ${pkChangeColName},
method: 'delete'
})
}
export function delAll(ids) {
export function del(ids) {
return request({
url: 'api/${changeClassName}/',
method: 'delete',
@ -30,4 +24,4 @@ export function edit(data) {
})
}
export default { add, edit, del, delAll }
export default { add, edit, del }

View File

@ -4,43 +4,41 @@
<!--工具栏-->
<div class="head-container">
<#if hasQuery>
<!-- 搜索 -->
<el-input v-model="query.value" clearable placeholder="输入搜索内容" style="width: 200px;" class="filter-item" @keyup.enter.native="toQuery" />
<el-select v-model="query.type" clearable placeholder="类型" class="filter-item" style="width: 130px">
<el-option v-for="item in queryTypeOptions" :key="item.key" :label="item.display_name" :value="item.key" />
</el-select>
<#if betweens??>
<#list betweens as column>
<#if column.queryType = 'BetWeen'>
<el-date-picker
v-model="query.${column.changeColumnName}"
:default-time="['00:00:00','23:59:59']"
type="daterange"
range-separator=":"
size="small"
class="date-item"
value-format="yyyy-MM-dd HH:mm:ss"
start-placeholder="${column.changeColumnName}Start"
end-placeholder="${column.changeColumnName}End"
/>
<div v-if="crud.props.searchToggle">
<!-- 搜索 -->
<el-input v-model="query.value" clearable placeholder="输入搜索内容" style="width: 200px;" class="filter-item" @keyup.enter.native="crud.toQuery" />
<el-select v-model="query.type" clearable placeholder="类型" class="filter-item" style="width: 130px">
<el-option v-for="item in queryTypeOptions" :key="item.key" :label="item.display_name" :value="item.key" />
</el-select>
<#if betweens??>
<#list betweens as column>
<#if column.queryType = 'BetWeen'>
<el-date-picker
v-model="query.${column.changeColumnName}"
:default-time="['00:00:00','23:59:59']"
type="daterange"
range-separator=":"
size="small"
class="date-item"
value-format="yyyy-MM-dd HH:mm:ss"
start-placeholder="${column.changeColumnName}Start"
end-placeholder="${column.changeColumnName}End"
/>
</#if>
</#list>
</#if>
<rrOperation :crud="crud" />
</div>
</#if>
</#list>
</#if>
<el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="toQuery">搜索</el-button>
</#if>
<!-- 新增 -->
<el-button v-permission="['admin','${changeClassName}:add']" class="filter-item" size="mini" type="primary" icon="el-icon-plus" @click="showAddFormDialog">新增</el-button>
<!-- 导出 -->
<el-button :loading="downloadLoading" size="mini" class="filter-item" type="warning" icon="el-icon-download" @click="downloadMethod">导出</el-button>
<!-- 多选删除 -->
<el-button v-permission="['admin','${changeClassName}:del']" :loading="delAllLoading" :disabled="data.length === 0 || $refs.table.selection.length === 0" class="filter-item" size="mini" type="danger" icon="el-icon-delete" @click="beforeDelAllMethod">删除</el-button>
<!--如果想在工具栏加入更多按钮,可以使用插槽方式, slot = 'left' or 'right'-->
<crudOperation :permission="permission" />
<!--表单组件-->
<el-dialog :append-to-body="true" :close-on-click-modal="false" :before-close="cancel" :visible.sync="dialog" :title="getFormTitle()" width="500px">
<el-dialog :close-on-click-modal="false" :before-close="crud.cancelCU" :visible.sync="crud.status.cu > 0" :title="crud.status.title" width="500px">
<el-form ref="form" :model="form" <#if isNotNullColumns??>:rules="rules"</#if> size="small" label-width="80px">
<#if columns??>
<#list columns as column>
<#if column.formShow>
<el-form-item label="<#if column.remark != ''>${column.remark}<#else>${column.changeColumnName}</#if>" <#if column.istNotNull>prop="${column.changeColumnName}"</#if>>
<el-form-item label="<#if column.remark != ''>${column.remark}<#else>${column.changeColumnName}</#if>"<#if column.istNotNull> prop="${column.changeColumnName}"</#if>>
<#if column.formType = 'Input'>
<el-input v-model="form.${column.changeColumnName}" style="width: 370px;" />
<#elseif column.formType = 'Textarea'>
@ -72,26 +70,26 @@
</#if>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="text" @click="cancel">取消</el-button>
<el-button :loading="loading" type="primary" @click="submitMethod">确认</el-button>
<el-button type="text" @click="crud.cancelCU">取消</el-button>
<el-button :loading="crud.cu === 2" type="primary" @click="crud.submitCU">确认</el-button>
</div>
</el-dialog>
<!--表格渲染-->
<el-table ref="table" v-loading="loading" :data="data" size="small" style="width: 100%;">
<el-table ref="table" v-loading="crud.loading" :data="crud.data" size="small" style="width: 100%;" @selection-change="crud.selectionChangeHandler">
<el-table-column type="selection" width="55" />
<#if columns??>
<#list columns as column>
<#if column.columnShow>
<#if column.dictName??>
<el-table-column prop="${column.changeColumnName}" label="<#if column.remark != ''>${column.remark}<#else>${column.changeColumnName}</#if>">
<el-table-column v-if="columns.visible('${column.changeColumnName}')" prop="${column.changeColumnName}" label="<#if column.remark != ''>${column.remark}<#else>${column.changeColumnName}</#if>">
<template slot-scope="scope">
{{ dict.label.${column.dictName}[scope.row.${column.changeColumnName}] }}
</template>
</el-table-column>
<#elseif column.columnType != 'Timestamp'>
<el-table-column prop="${column.changeColumnName}" label="<#if column.remark != ''>${column.remark}<#else>${column.changeColumnName}</#if>" />
<el-table-column v-if="columns.visible('${column.changeColumnName}')" prop="${column.changeColumnName}" label="<#if column.remark != ''>${column.remark}<#else>${column.changeColumnName}</#if>" />
<#else>
<el-table-column prop="${column.changeColumnName}" label="<#if column.remark != ''>${column.remark}<#else>${column.changeColumnName}</#if>">
<el-table-column v-if="columns.visible('${column.changeColumnName}')" prop="${column.changeColumnName}" label="<#if column.remark != ''>${column.remark}<#else>${column.changeColumnName}</#if>">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.${column.changeColumnName}) }}</span>
</template>
@ -100,51 +98,46 @@
</#if>
</#list>
</#if>
<el-table-column v-if="checkPermission(['admin','${changeClassName}:edit','${changeClassName}:del'])" label="操作" width="150px" align="center">
<el-table-column v-permission="['admin','${changeClassName}:edit','${changeClassName}:del']" label="操作" width="150px" align="center">
<template slot-scope="scope">
<el-button v-permission="['admin','${changeClassName}:edit']" size="mini" type="primary" icon="el-icon-edit" @click="showEditFormDialog(scope.row)" />
<el-popover
:ref="scope.row.${pkChangeColName}"
v-permission="['admin','${changeClassName}:del']"
placement="top"
width="180"
>
<p>确定删除本条数据吗?</p>
<div style="text-align: right; margin: 0">
<el-button size="mini" type="text" @click="$refs[scope.row.${pkChangeColName}].doClose()">取消</el-button>
<el-button :loading="delLoading" type="primary" size="mini" @click="delMethod(scope.row.${pkChangeColName})">确定</el-button>
</div>
<el-button slot="reference" type="danger" icon="el-icon-delete" size="mini" />
</el-popover>
<udOperation
:data="scope.row"
:permission="permission"
/>
</template>
</el-table-column>
</el-table>
<!--分页组件-->
<el-pagination
:total="total"
:current-page="page + 1"
style="margin-top: 8px;"
layout="total, prev, pager, next, sizes"
@size-change="sizeChange"
@current-change="pageChange"
/>
<pagination />
</div>
</div>
</template>
<script>
import crud from '@/mixins/crud'
import crud${className} from '@/api/${changeClassName}'
import CRUD, { presenter, header, form, crud } from '@crud/crud'
import rrOperation from '@crud/RR.operation'
import crudOperation from '@crud/CRUD.operation'
import udOperation from '@crud/UD.operation'
import pagination from '@crud/Pagination'
// crud交由presenter持有
const defaultCrud = CRUD({ title: '${apiAlias}', url: 'api/${changeClassName}', sort: '${pkChangeColName},desc', crudMethod: { ...crud${className} }})
const defaultForm = { <#if columns??><#list columns as column>${column.changeColumnName}: null<#if column_has_next>, </#if></#list></#if> }
export default {
mixins: [crud],
name: '${className}',
components: { pagination, crudOperation, rrOperation, udOperation },
mixins: [presenter(defaultCrud), header(), form(defaultForm), crud()],
<#if hasDict>
dicts: [<#if hasDict??><#list dicts as dict>'${dict}'<#if dict_has_next>, </#if></#list></#if>],
</#if>
data() {
return {
title: '${apiAlias}',
crudMethod: { ...crud${className} },
form: { <#if columns??><#list columns as column>${column.changeColumnName}: null<#if column_has_next>, </#if></#list></#if> },
permission: {
add: ['admin', '${changeClassName}:add'],
edit: ['admin', '${changeClassName}:edit'],
del: ['admin', '${changeClassName}:del']
},
rules: {
<#if isNotNullColumns??>
<#list isNotNullColumns as column>
@ -168,22 +161,14 @@ export default {
</#if>
}
},
created() {
this.$nextTick(() => {
this.init()
})
},
methods: {
// 获取数据前设置好接口地址
beforeInit() {
this.url = 'api/${changeClassName}'
const sort = '${pkChangeColName},desc'
this.params = { page: this.page, size: this.size, sort: sort }
[CRUD.HOOK.beforeRefresh]() {
<#if hasQuery>
const query = this.query
const type = query.type
const value = query.value
if (type && value) { this.params[type] = value }
if (query.type && query.value) {
this.crud.params[query.type] = query.value
}
</#if>
return true
}