1
0
mirror of https://github.com/chillzhuang/Sword synced 2024-11-23 18:59:27 +08:00

🎉 2.7.1.RELEASE,增加行政区划管理,支持seata1.2

This commit is contained in:
smallchill 2020-06-12 11:53:17 +08:00
parent 50cbbe6524
commit 43a49063e2
9 changed files with 467 additions and 8 deletions

View File

@ -1,9 +1,9 @@
<p align="center"> <p align="center">
<img src="https://img.shields.io/badge/Release-V2.7.0-green.svg" alt="Downloads"> <img src="https://img.shields.io/badge/Release-V2.7.1-green.svg" alt="Downloads">
<img src="https://img.shields.io/badge/JDK-1.8+-green.svg" alt="Build Status"> <img src="https://img.shields.io/badge/JDK-1.8+-green.svg" alt="Build Status">
<img src="https://img.shields.io/badge/license-Apache%202-blue.svg" alt="Build Status"> <img src="https://img.shields.io/badge/license-Apache%202-blue.svg" alt="Build Status">
<img src="https://img.shields.io/badge/Spring%20Cloud-Hoxton.SR3-blue.svg" alt="Coverage Status"> <img src="https://img.shields.io/badge/Spring%20Cloud-Hoxton.SR5-blue.svg" alt="Coverage Status">
<img src="https://img.shields.io/badge/Spring%20Boot-2.2.6.RELEASE-blue.svg" alt="Downloads"> <img src="https://img.shields.io/badge/Spring%20Boot-2.2.7.RELEASE-blue.svg" alt="Downloads">
<a target="_blank" href="https://bladex.vip"> <a target="_blank" href="https://bladex.vip">
<img src="https://img.shields.io/badge/Author-Small%20Chill-ff69b4.svg" alt="Downloads"> <img src="https://img.shields.io/badge/Author-Small%20Chill-ff69b4.svg" alt="Downloads">
</a> </a>
@ -58,7 +58,8 @@ SpringBlade
* 会员计划:[SpringBlade会员计划](https://gitee.com/smallc/SpringBlade/wikis/SpringBlade会员计划) * 会员计划:[SpringBlade会员计划](https://gitee.com/smallc/SpringBlade/wikis/SpringBlade会员计划)
* 交流一群:`477853168`(满) * 交流一群:`477853168`(满)
* 交流二群:`751253339`(满) * 交流二群:`751253339`(满)
* 交流三群:`784729540` * 交流三群:`784729540`(满)
* 交流四群:`1034621754`
## 在线演示 ## 在线演示
* Saber-基于Vue[https://saber.bladex.vip](https://saber.bladex.vip) * Saber-基于Vue[https://saber.bladex.vip](https://saber.bladex.vip)

View File

@ -90,6 +90,18 @@ export default [
}, },
], ],
}, },
{
path: '/base',
routes: [
{
path: '/base/region',
routes: [
{ path: '/base/region', redirect: '/base/region/detail' },
{ path: '/base/region/detail', component: './Base/Region/Region' },
],
},
],
},
{ {
path: '/system', path: '/system',
routes: [ routes: [

View File

@ -6,6 +6,8 @@ export default {
'menu.dashboard.workplace': 'Workplace', 'menu.dashboard.workplace': 'Workplace',
'menu.desk': 'desktop', 'menu.desk': 'desktop',
'menu.desk.notice': 'notice', 'menu.desk.notice': 'notice',
'menu.base': 'base',
'menu.base.region': 'region',
'menu.system': 'system', 'menu.system': 'system',
'menu.system.user': 'user', 'menu.system.user': 'user',
'menu.system.dept': 'department', 'menu.system.dept': 'department',

View File

@ -6,6 +6,8 @@ export default {
'menu.dashboard.workplace': '工作台', 'menu.dashboard.workplace': '工作台',
'menu.desk': '工作台', 'menu.desk': '工作台',
'menu.desk.notice': '通知公告', 'menu.desk.notice': '通知公告',
'menu.base': '基础配置',
'menu.base.region': '行政区划',
'menu.system': '系统管理', 'menu.system': '系统管理',
'menu.system.user': '用户管理', 'menu.system.user': '用户管理',
'menu.system.dept': '部门管理', 'menu.system.dept': '部门管理',

View File

@ -6,6 +6,8 @@ export default {
'menu.dashboard.workplace': '工作台', 'menu.dashboard.workplace': '工作台',
'menu.desk': '工作台', 'menu.desk': '工作台',
'menu.desk.notice': '通知公告', 'menu.desk.notice': '通知公告',
'menu.base': '基礎配置',
'menu.base.region': '行政區劃',
'menu.system': '系統管理', 'menu.system': '系統管理',
'menu.system.user': '用戶管理', 'menu.system.user': '用戶管理',
'menu.system.dept': '部門管理', 'menu.system.dept': '部門管理',

View File

@ -0,0 +1,399 @@
import React, { PureComponent } from 'react';
import {
Button,
Card,
Col,
Form,
Input,
InputNumber,
Row,
Tree,
Cascader,
Radio,
message,
Modal,
} from 'antd';
import Panel from '../../../components/Panel';
import styles from '@/layouts/Sword.less';
import { getLazyTree, detail, submit, remove } from '../../../services/region';
import { getButton, hasButton } from '../../../utils/authority';
import Func from '../../../utils/Func';
const FormItem = Form.Item;
const { TreeNode } = Tree;
const { TextArea } = Input;
const ButtonGroup = Button.Group;
@Form.create()
class Region extends PureComponent {
state = {
topCode: '00',
treeData: [],
treeCascader: [],
debugVisible: false,
};
// ============ 初始化数据 ===============
componentWillMount() {
this.initTree();
this.initCascader('00');
}
initTree = () => {
const { topCode } = this.state;
getLazyTree({ parentCode: topCode }).then(resp => {
if (resp.success) {
this.setState({
treeData: resp.data.map(item => {
return { ...item, isLeaf: !item.hasChildren };
}),
});
}
});
};
initCascader = code => {
getLazyTree({ parentCode: code }).then(resp => {
if (resp.success) {
this.setState({
treeCascader: resp.data.map(item => {
return {
label: item.title,
value: item.value,
isLeaf: !item.hasChildren,
};
}),
});
}
});
};
onSelect = checkedTreeKeys => {
const code = checkedTreeKeys[0];
if (Func.isEmpty(code)) {
return;
}
detail({ code }).then(resp => {
if (resp.success) {
const { form } = this.props;
const { data } = resp;
form.setFieldsValue({
parentCode: data.parentCode,
parentName: data.parentName,
code: data.code,
name: data.name,
level: data.level,
sort: data.sort,
remark: data.remark,
});
}
});
};
onLoadData = treeNode =>
new Promise(resolve => {
if (treeNode.props.children) {
resolve();
return;
}
getLazyTree({ parentCode: treeNode.props.id }).then(resp => {
if (resp.success) {
const { treeData } = this.state;
// eslint-disable-next-line no-param-reassign
treeNode.props.dataRef.children = resp.data.map(item => {
return { ...item, isLeaf: !item.hasChildren };
});
this.setState({
treeData: [...treeData],
});
}
resolve();
});
});
onCascaderChange = (value, selectedOptions) => {
window.console.log(value, selectedOptions);
};
onLoadCascaderData = selectedOptions => {
const targetOption = selectedOptions[selectedOptions.length - 1];
targetOption.loading = true;
getLazyTree({ parentCode: targetOption.value }).then(resp => {
if (resp.success) {
targetOption.loading = false;
targetOption.children = resp.data.map(item => {
return {
label: item.title,
value: item.value,
isLeaf: !item.hasChildren,
};
});
const { treeCascader } = this.state;
this.setState({
treeCascader: [...treeCascader],
});
}
});
};
handleAdd = () => {
const { form } = this.props;
const region = form.getFieldsValue();
if (!region.code || !region.name) {
message.warn('请先选择一项区划!');
return;
}
form.setFieldsValue({
parentCode: region.code,
parentName: region.name,
code: region.code,
name: '',
level: region.level < 5 ? region.level + 1 : region.level,
remark: region.remark,
});
};
handleDelete = () => {
const { form } = this.props;
const code = form.getFieldValue('code');
Modal.confirm({
title: '删除确认',
content: '确定删除该条记录?',
okText: '确定',
okType: 'danger',
cancelText: '取消',
onOk() {
remove({ id: code }).then(resp => {
if (resp.success) {
message.success(resp.msg);
form.resetFields();
} else {
message.error(resp.msg || '删除失败');
}
});
},
onCancel() {},
});
};
handleDebug = () => {
this.setState({ debugVisible: true });
};
handleDebugCancel = () => {
this.setState({ debugVisible: false });
};
handleSubmit = e => {
e.preventDefault();
const { form } = this.props;
const { topCode } = this.state;
form.validateFieldsAndScroll((err, values) => {
if (err) return;
const parentCode = form.getFieldValue('parentCode');
const code = form.getFieldValue('code');
if (parentCode === code) {
message.warn('请输入正确的区划子编号!');
return;
}
const params = {
...values,
parentCode: parentCode === topCode ? '' : parentCode,
};
submit(params).then(resp => {
if (resp.success) {
message.success(resp.msg);
form.resetFields();
} else {
message.error(resp.msg || '提交失败');
}
});
});
};
handleReset = () => {
const { form } = this.props;
form.resetFields();
};
renderTreeNodes = data =>
data.map(item => {
if (item.children) {
return (
<TreeNode title={item.title} key={item.key} dataRef={item}>
{this.renderTreeNodes(item.children)}
</TreeNode>
);
}
return <TreeNode {...item} title={item.title} key={item.key} dataRef={item} />;
});
render() {
const {
form: { getFieldDecorator },
} = this.props;
const buttons = getButton('region');
const {
treeData,
treeCascader,
debugVisible,
} = this.state;
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 12 },
md: { span: 16 },
},
};
return (
<Panel>
<Row gutter={24}>
<Col span={8}>
<Card className={styles.card} bordered={false} style={{ marginRight: '10px' }}>
<Tree onSelect={this.onSelect} loadData={this.onLoadData}>
{this.renderTreeNodes(treeData)}
</Tree>
</Card>
</Col>
<Col span={16}>
<Row gutter={24}>
<Card className={styles.card} bordered={false}>
<Col span={18}>
<ButtonGroup>
{hasButton(buttons, 'region_add') ? (
<Button type="primary" icon="plus" onClick={this.handleAdd}>
新增下级
</Button>
) : null}
{hasButton(buttons, 'region_delete') ? (
<Button type="danger" icon="delete" onClick={this.handleDelete}>
删除
</Button>
) : null}
{hasButton(buttons, 'region_debug') ? (
<Button icon="right-circle" onClick={this.handleDebug}>
调试
</Button>
) : null}
</ButtonGroup>
</Col>
<Col span={6} style={{ textAlign: 'right' }}>
<ButtonGroup>
<Button type="primary" htmlType="submit" onClick={this.handleSubmit}>
</Button>
<Button onClick={this.handleReset}> </Button>
</ButtonGroup>
</Col>
</Card>
</Row>
<Row gutter={24}>
<Card className={styles.card} bordered={false}>
<Form>
<FormItem {...formItemLayout} label="父区划编号">
{getFieldDecorator('parentCode', {
rules: [
{
required: true,
message: '请输入父区划编号',
},
],
})(<Input disabled placeholder="请输入父区划编号" />)}
</FormItem>
<FormItem {...formItemLayout} label="父区划名称">
{getFieldDecorator('parentName', {
rules: [
{
required: true,
message: '请输入父区划名称',
},
],
})(<Input disabled placeholder="请输入父区划名称" />)}
</FormItem>
<FormItem {...formItemLayout} label="区划编号">
{getFieldDecorator('code', {
rules: [
{
required: true,
message: '请输入区划编号',
},
],
})(<Input placeholder="请输入区划编号" />)}
</FormItem>
<FormItem {...formItemLayout} label="区划名称">
{getFieldDecorator('name', {
rules: [
{
required: true,
message: '请输入区划名称',
},
],
})(<Input placeholder="请输入区划名称" />)}
</FormItem>
<FormItem {...formItemLayout} label="区划等级">
{getFieldDecorator('level', {
rules: [
{
required: true,
message: '请输入区划等级',
},
],
})(
<Radio.Group>
<Radio value={0}>国家</Radio>
<Radio value={1}>省份/直辖市</Radio>
<Radio value={2}>地市</Radio>
<Radio value={3}>区县</Radio>
<Radio value={4}>乡镇</Radio>
<Radio value={5}>村委</Radio>
</Radio.Group>
)}
</FormItem>
<FormItem {...formItemLayout} className={styles.inputItem} label="区划排序">
{getFieldDecorator('sort', {
rules: [
{
required: true,
message: '请输入区划排序',
},
],
})(<InputNumber placeholder="请输入区划排序" />)}
</FormItem>
<FormItem {...formItemLayout} label="区划备注">
{getFieldDecorator('remark', {})(<TextArea placeholder="请输入区划备注" />)}
</FormItem>
</Form>
</Card>
</Row>
</Col>
</Row>
<Modal
title="行政区划数据调试"
width={500}
visible={debugVisible}
onOk={this.handleDebugCancel}
onCancel={this.handleDebugCancel}
footer={null}
>
<Cascader
style={{ width: '100%' }}
options={treeCascader}
loadData={this.onLoadCascaderData}
onChange={this.onCascaderChange}
changeOnSelect
/>
</Modal>
</Panel>
);
}
}
export default Region;

View File

@ -14,14 +14,14 @@ class Workplace extends PureComponent {
<Row gutter={24}> <Row gutter={24}>
<Col span={24}> <Col span={24}>
<div style={{ textAlign: 'center' }}> <div style={{ textAlign: 'center' }}>
<img src="https://img.shields.io/badge/Release-V2.7.0-green.svg" alt="Downloads" /> <img src="https://img.shields.io/badge/Release-V2.7.1-green.svg" alt="Downloads" />
<img src="https://img.shields.io/badge/JDK-1.8+-green.svg" alt="Build Status" /> <img src="https://img.shields.io/badge/JDK-1.8+-green.svg" alt="Build Status" />
<img <img
src="https://img.shields.io/badge/Spring%20Cloud-Hoxton.SR3-blue.svg" src="https://img.shields.io/badge/Spring%20Cloud-Hoxton.SR5-blue.svg"
alt="Coverage Status" alt="Coverage Status"
/> />
<img <img
src="https://img.shields.io/badge/Spring%20Boot-2.2.6.RELEASE-blue.svg" src="https://img.shields.io/badge/Spring%20Boot-2.2.7.RELEASE-blue.svg"
alt="Downloads" alt="Downloads"
/> />
<a href="https://bladex.vip"> <a href="https://bladex.vip">
@ -206,7 +206,19 @@ class Workplace extends PureComponent {
</Row> </Row>
<Row gutter={24}> <Row gutter={24}>
<Card className={styles.card} bordered={false}> <Card className={styles.card} bordered={false}>
<Collapse bordered={false} defaultActiveKey={['17']}> <Collapse bordered={false} defaultActiveKey={['18']}>
<Panel header="2.7.1发布 增加行政区划管理支持seata1.2" key="18">
<div>1.升级至 SpringCloud Hoxton.SR5</div>
<div>2.升级至 SpringBoot 2.2.7.RELEASE</div>
<div>3.升级至 Seata 1.2.0</div>
<div>4.升级至 FastJson 1.2.70</div>
<div>5.升级至 Avue 2.5.3</div>
<div>6.新增行政区划管理模块</div>
<div>7.优化用户导入的密码配置逻辑</div>
<div>8.优化INode结构支持懒加载数据格式</div>
<div>9.优化代码生成模板支持最新版Saber结构</div>
<div>10.修复Log模块在多线程异步场景下报错的问题</div>
</Panel>
<Panel header="2.7.0发布 内核全面升级,增加岗位管理,用户导入导出" key="17"> <Panel header="2.7.0发布 内核全面升级,增加岗位管理,用户导入导出" key="17">
<div>1.升级至 SpringCloud Hoxton.SR3</div> <div>1.升级至 SpringCloud Hoxton.SR3</div>
<div>2.升级至 SpringBoot 2.2.6.RELEASE</div> <div>2.升级至 SpringBoot 2.2.6.RELEASE</div>

25
src/services/region.js Normal file
View File

@ -0,0 +1,25 @@
import { stringify } from 'qs';
import request from '../utils/request';
import func from '../utils/Func';
export async function getLazyTree(params) {
return request(`/api/blade-system/region/lazy-tree?${stringify(params)}`);
}
export async function remove(params) {
return request('/api/blade-system/region/remove', {
method: 'POST',
body: func.toFormData(params),
});
}
export async function submit(params) {
return request('/api/blade-system/region/submit', {
method: 'POST',
body: params,
});
}
export async function detail(params) {
return request(`/api/blade-system/region/detail?${stringify(params)}`);
}

View File

@ -51,6 +51,10 @@ export function setRoutes(routes) {
localStorage.setItem('sword-routes', JSON.stringify(routes)); localStorage.setItem('sword-routes', JSON.stringify(routes));
} }
export function hasButton(buttons, code) {
return buttons.filter(button => button.code === code).length > 0;
}
export function getButtons() { export function getButtons() {
return JSON.parse(localStorage.getItem('sword-buttons')) || []; return JSON.parse(localStorage.getItem('sword-buttons')) || [];
} }