fix 片区管理

This commit is contained in:
2021-06-23 17:36:29 +08:00
parent 3734dda2db
commit a9173e3812
10 changed files with 272 additions and 202 deletions

View File

@@ -1456,5 +1456,20 @@
上报备注
</summary>
</member>
<member name="P:Ewide.Application.AddHouseZoneInput.Pid">
<summary>
所属街道
</summary>
</member>
<member name="P:Ewide.Application.AddHouseZoneInput.Name">
<summary>
名称
</summary>
</member>
<member name="P:Ewide.Application.UpdateHouseZoneInput.Id">
<summary>
机构Id
</summary>
</member>
</members>
</doc>

View File

@@ -1,4 +1,5 @@
using System;
using Ewide.Core.Service;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
@@ -13,4 +14,28 @@ namespace Ewide.Application
[MinLength(9, ErrorMessage = "区域编码长度必须为9位及以上")]
public string AreaCode { get; set; }
}
public class AddHouseZoneInput : OrgInput
{
/// <summary>
/// 所属街道
/// </summary>
[Required(ErrorMessage = "所属街道不能为空")]
public override string Pid { get; set; }
/// <summary>
/// 名称
/// </summary>
[Required(ErrorMessage = "片区名称不能为空")]
public override string Name { get; set; }
}
public class UpdateHouseZoneInput : AddHouseZoneInput
{
/// <summary>
/// 机构Id
/// </summary>
[Required(ErrorMessage = "片区Id不能为空")]
public string Id { get; set; }
}
}

View File

@@ -2,9 +2,11 @@
using Ewide.Core.Extension;
using Ewide.Core.Service;
using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System;
@@ -104,9 +106,9 @@ namespace Ewide.Application.Service
}
[HttpGet("/houseZone/autoIncrement")]
public async Task<dynamic> AutoIncrement([FromQuery] string code)
public async Task<dynamic> AutoIncrement([FromQuery] string roadId)
{
var road = await _sysOrgRep.DetachedEntities.FirstOrDefaultAsync(p => p.AreaCode == code);
var road = await _sysOrgRep.DetachedEntities.FirstOrDefaultAsync(p => p.Id == roadId && p.Type == 3);
if (road == null) throw Oops.Oh("组织机构错误");
return await AutoIncrement(road);
}
@@ -119,7 +121,7 @@ namespace Ewide.Application.Service
}
[HttpPost("/houseZone/add")]
public async Task AddZone(AddOrgInput input)
public async Task AddZone(AddHouseZoneInput input)
{
/*
* 区县市限定所属区域/上级机构是否为当前区
@@ -136,15 +138,14 @@ namespace Ewide.Application.Service
var roles = await _userManager.GetUserRoleList();
if (roles.Any(p => p.Code == areaManager))
{
var road = await _sysOrgRep.DetachedEntities.FirstOrDefaultAsync(p => p.AreaCode == input.AreaCode);
if (!road.Pids.Contains(org.Id)) throw Oops.Oh("组织机构错误");
var road = await _sysOrgRep.DetachedEntities.FirstOrDefaultAsync(p => p.Id == input.Pid);
if (!road.Pids.Contains(org.Id)) throw Oops.Oh("当前用户组织机构错误");
input.Pid = road.Id;
input.AreaCode = road.AreaCode;
input.Code = road.Code + (await AutoIncrement(road)).ToString().PadLeft(3, '0');
}
else if (roles.Any(p => p.Code == roadManager))
{
input.Pid = org.Id;
input.AreaCode = org.AreaCode;
input.Code = org.Code + (await AutoIncrement(org)).ToString().PadLeft(3, '0');
@@ -152,7 +153,17 @@ namespace Ewide.Application.Service
input.Type = (int)OrgType.;
await _sysOrgService.AddOrg(input);
AddOrgInput addOrgInput = input.Adapt<AddOrgInput>();
await _sysOrgService.AddOrg(addOrgInput);
}
[HttpPost("/houseZone/edit")]
public async Task EditZone(UpdateHouseZoneInput input)
{
var zone = await _sysOrgRep.DetachedEntities.FirstOrDefaultAsync(z => z.Id == input.Id);
if(zone == null) throw Oops.Oh("修改失败:数据有误,刷新列表后再尝试修改");
zone.Remark = input.Remark;
await zone.UpdateIncludeAsync(new[] { nameof(SysOrg.Remark) }, true);
}
}
}

View File

@@ -10,7 +10,7 @@ namespace Ewide.Core.Service
/// <summary>
/// 父Id
/// </summary>
public string Pid { get; set; }
public virtual string Pid { get; set; }
/// <summary>
/// 父Ids

View File

@@ -7,7 +7,8 @@ const urls = {
houseZoneList: '/houseZone/list',
houseZoneAutoIncrement: '/houseZone/autoIncrement',
houseZoneAdd: ['/houseZone/add', 'post']
houseZoneAdd: ['/houseZone/add', 'post'],
houseZoneEdit: ['/houseZone/edit', 'post']
}
export default urls

View File

@@ -121,6 +121,7 @@ export default class form extends Component {
async loadAreaData() {
const { data } = await api.getAreaTree()
console.log(data)
const clearChiildren = data => {
data.forEach(item => {
if (item.children && item.children.length) {

View File

@@ -47,22 +47,26 @@ export default class index extends Component {
{
title: '项目名称',
dataIndex: 'name',
width: 150,
sorter: true,
},
{
title: '社区',
dataIndex: 'areaName',
width: 100,
sorter: true,
},
{
title: '备注',
dataIndex: 'note',
width: 150,
sorter: true,
},
{
title: '类型',
dataIndex: 'type',
sorter: true,
width: 80,
render: text => <>{this.bindCodeValue(text, 'house_type')}</>,
},
]
@@ -73,7 +77,7 @@ export default class index extends Component {
constructor(props) {
super(props)
const flag = auth({ sysArea: [['edit'], ['delete']] })
const flag = auth({ houseProjectInfo: [['edit'], ['delete']] })
if (flag) {
this.columns.push({

View File

@@ -1,24 +1,36 @@
import React, { Component } from 'react'
import { Cascader, Form, Input, InputNumber, Select, Spin, TreeSelect } from 'antd'
import { Form, Input, InputNumber, Spin, TreeSelect } from 'antd'
import { AntIcon } from 'components'
import { cloneDeep } from 'lodash'
import getDictData from 'util/dic'
import { api } from 'common/api'
import { numberToChinese } from 'util/format';
import { numberToChinese } from 'util/format'
import store from 'store'
const { getState, subscribe } = store
const storePath = 'user'
const initialValues = {
sort: 100
sort: 100,
}
export default class form extends Component {
state = {
// 加载状态
loading: true,
exist: false,
options: {
areaData: []
}
orgData: [],
},
user: getState(storePath),
}
constructor(props) {
super(props)
this.unsubscribe = subscribe(storePath, () => {
this.setState({
user: getState(storePath),
})
})
}
// 表单实例
form = React.createRef()
@@ -31,60 +43,48 @@ export default class form extends Component {
componentDidMount() {
this.props.created && this.props.created(this)
}
componentWillUnmount() {
this.unsubscribe()
}
/**
* 填充数据
* 可以在设置this.record之后对其作出数据结构调整
* [异步,必要]
* @param {*} params
*/
* 填充数据
* 可以在设置this.record之后对其作出数据结构调整
* [异步,必要]
* @param {*} params
*/
async fillData(params) {
const { user } = this.state
this.record = cloneDeep(params.record)
//#region 从后端转换成前段所需格式
const areaData = await this.loadAreaData()
const orgData = await this.loadOrgData()
this.setState({
options: { areaData }
exist: !!params.record,
options: { orgData },
})
const areaCode = [];
const findCode = (data, level) => {
level = level || 0;
for (let i = 0; i < data.length; i++) {
const item = data[i];
areaCode[level] = item.code;
if (item.code === params.record.areaCode) {
areaCode.length = level + 1;
return true;
//街道角色新增,不管左侧树选中与否,默认值均为本街道
if (user.adminType === 2) {
user.roles.map(role => {
if (role.code == 'road_manager') {
params.orgId = user.loginEmpInfo.orgId
}
if (item.children && item.children.length) {
const found = findCode(item.children, level + 1);
if (found) {
return true;
}
}
}
};
if (params.record && params.record.areaCode) {
findCode(areaData);
})
}
this.record = {
pid: params.orgId,
...this.record,
areaCode
}
this.record.areaCode = areaCode
//#endregion
//#endregion
if (!params.record && !!params.orgId) {
this.onOrgIdChanged(params.orgId)
}
this.form.current.setFieldsValue(this.record)
this.setState({
loading: false
loading: false,
})
}
/**
@@ -102,74 +102,64 @@ export default class form extends Component {
if (this.record) {
postData.id = this.record.id
}
//#region 从前段转换后端所需格
postData.areaCode = postData.areaCode[postData.areaCode.length - 1]
//#region 从前段转换后端所需格
//#endregion
return postData
}
}
async loadAreaData() {
const { data } = await api.getAreaTree({ level: 3 })
const clearChiildren = (data) => {
data.forEach((item) => {
if (item.children && item.children.length) {
clearChiildren(item.children);
} else {
delete item.children;
}
});
};
clearChiildren(data);
async loadOrgData() {
const { data } = await api.getOrgTree({ type: 4 })
return data
}
onAreaCodeChange(value) {
this.loading = true;
// const { data } = api.houseZoneAutoIncrement({ code: selectedOptions[selectedOptions.length - 1] });
onOrgIdChanged(value) {
this.loading = true
api.houseZoneAutoIncrement({ code: value[value.length - 1] })
api.houseZoneAutoIncrement({ roadId: value })
.then(({ data }) => {
this.form.current.setFieldsValue({
name: `片区${numberToChinese(data)}`
name: `片区${numberToChinese(data)}`,
sort: data,
})
})
.catch(() => {
this.form.current.setFieldsValue({
name: '',
areaCode: []
sort: 0,
})
})
.finally(() => {
this.loading = false;
});
this.loading = false
})
}
render() {
return (
<Form
initialValues={initialValues}
ref={this.form}
className="yo-form"
>
<Form initialValues={initialValues} ref={this.form} className="yo-form">
<Spin spinning={this.state.loading} indicator={<AntIcon type="loading" />}>
<div className="yo-form-group">
<Form.Item label="所属区域" name="areaCode" rules={[{ required: true, message: '请选择所属区域' }]}>
<Cascader
options={this.state.options.areaData}
fieldNames={{
label: 'name',
value: 'code',
children: 'children'
}}
expandTrigger="hover"
// changeOnSelect
placeholder="请选择所属区域"
onChange={(val, selectedOptions) => this.onAreaCodeChange(val)}
<Form.Item
label="所属街道"
name="pid"
rules={[{ required: true, message: '请选择所属街道' }]}
>
<TreeSelect
treeData={this.state.options.orgData}
dropdownStyle={{ maxHeight: '300px', overflow: 'auto' }}
treeDefaultExpandAll
placeholder="请选择所属街道"
onChange={(value, label, extra) => this.onOrgIdChanged(value)}
disabled={this.state.exist}
/>
</Form.Item>
<Form.Item label="片区名称" name="name" rules={[{ required: true, message: '片区名称', trigger: 'blur' }]}>
<Input autoComplete="off" placeholder="请输入机构名称" />
<Form.Item
label="片区名称"
name="name"
rules={[{ required: true, message: '片区名称', trigger: 'blur' }]}
>
<Input autoComplete="off" placeholder="请输入机构名称" disabled />
</Form.Item>
<Form.Item label="排序" name="sort">
<InputNumber
@@ -177,6 +167,7 @@ export default class form extends Component {
min={0}
placeholder="请输入排序"
className="w-100-p"
disabled
/>
</Form.Item>
<Form.Item label="备注" name="remark">

View File

@@ -1,6 +1,14 @@
import React, { Component } from 'react'
import { Button, Card, Form, Input, message as Message, Popconfirm } from 'antd'
import { AntIcon, Auth, Container, ModalForm, QueryTable, QueryTableActions, QueryTreeLayout } from 'components'
import {
AntIcon,
Auth,
Container,
ModalForm,
QueryTable,
QueryTableActions,
QueryTreeLayout,
} from 'components'
import { api } from 'common/api'
import auth from 'components/authorized/handler'
import { toCamelCase } from 'util/format'
@@ -12,14 +20,13 @@ const apiAction = {
tree: api.getOrgTree,
page: api.houseZonePage,
add: api.houseZoneAdd,
edit: api.sysOrgEdit,
delete: api.sysOrgDelete
edit: api.houseZoneEdit,
delete: api.sysOrgDelete,
}
const name = '片区'
export default class index extends Component {
// 树框架实例
treeLayout = React.createRef()
@@ -63,27 +70,29 @@ export default class index extends Component {
constructor(props) {
super(props)
const flag = auth({ sysOrg: [['edit'], ['delete']] })
const flag = auth({ houseZone: [['edit'], ['delete']] })
if (flag) {
this.columns.push({
title: '操作',
width: 150,
dataIndex: 'actions',
render: (text, record) => (<QueryTableActions>
<Auth auth="sysOrg:edit">
<a onClick={() => this.onOpen(this.editForm, record)}>编辑</a>
</Auth>
<Auth auth="sysOrg:delete">
<Popconfirm
placement="topRight"
title="是否确认删除"
onConfirm={() => this.onDelete(record)}
>
<a>删除</a>
</Popconfirm>
</Auth>
</QueryTableActions>)
render: (text, record) => (
<QueryTableActions>
<Auth auth="houseZone:edit">
<a onClick={() => this.onOpen(this.editForm, record)}>编辑</a>
</Auth>
<Auth auth="houseZone:delete">
<Popconfirm
placement="topRight"
title="是否确认删除"
onConfirm={() => this.onDelete(record)}
>
<a>删除</a>
</Popconfirm>
</Auth>
</QueryTableActions>
),
})
}
}
@@ -118,7 +127,7 @@ export default class index extends Component {
loadData = async (params, query) => {
query = {
...query,
pid: this.selectId
pid: this.selectId,
}
const { data } = await apiAction.page({
@@ -158,7 +167,7 @@ export default class index extends Component {
name = toCamelCase(name)
const codes = this.state.codes[name]
if (codes) {
const c = codes.find((p) => p.code === code)
const c = codes.find(p => p.code === code)
if (c) {
return c.value
}
@@ -174,7 +183,7 @@ export default class index extends Component {
onOpen(modal, record) {
modal.current.open({
orgId: this.selectId,
record
record,
})
}
@@ -205,10 +214,7 @@ export default class index extends Component {
* @param {*} record
*/
onDelete(record) {
this.onAction(
apiAction.delete(record),
'删除成功'
)
this.onAction(apiAction.delete(record), '删除成功')
}
//#region 自定义方法
@@ -220,7 +226,7 @@ export default class index extends Component {
ref={this.treeLayout}
loadData={this.loadTreeData}
defaultExpanded={true}
onSelect={(key) => this.onSelectTree(key)}
onSelect={key => this.onSelectTree(key)}
>
<Container mode="fluid">
<Card bordered={false}>
@@ -239,7 +245,9 @@ export default class index extends Component {
<Button
icon={<AntIcon type="plus" />}
onClick={() => this.onOpen(this.addForm)}
>新增{name}</Button>
>
新增{name}
</Button>
}
/>
</Card>

View File

@@ -1,6 +1,14 @@
import React, { Component } from 'react'
import { Button, Card, Form, Input, message as Message, Popconfirm } from 'antd'
import { AntIcon, Auth, Container, ModalForm, QueryTable, QueryTableActions, QueryTreeLayout } from 'components'
import {
AntIcon,
Auth,
Container,
ModalForm,
QueryTable,
QueryTableActions,
QueryTreeLayout,
} from 'components'
import { api } from 'common/api'
import auth from 'components/authorized/handler'
import { toCamelCase } from 'util/format'
@@ -13,17 +21,16 @@ const apiAction = {
page: api.sysAreaPage,
add: api.sysAreaAdd,
edit: api.sysAreaEdit,
delete: api.sysAreaDelete
delete: api.sysAreaDelete,
}
const name = '区域'
export default class index extends Component {
state = {
codes: {
dicAreacodeType: []
}
areacodeType: [],
},
}
// 表格实例
@@ -41,31 +48,37 @@ export default class index extends Component {
title: '区域类型',
dataIndex: 'levelType',
sorter: true,
render: text => (<>{this.bindCodeValue(text, 'dic_areacode_type')}</>)
width: 50,
render: text => <>{this.bindCodeValue(text, 'areacode_type')}</>,
},
{
title: '区域名称',
dataIndex: 'name',
width: 100,
sorter: true,
},
{
title: '区域编号',
dataIndex: 'code',
width: 80,
sorter: true,
},
{
title: '行政编号',
dataIndex: 'adCode',
width: 80,
sorter: true,
},
{
title: '描述',
dataIndex: 'note',
width: 200,
sorter: false,
},
{
title: '排序',
dataIndex: 'sort',
width: 80,
sorter: true,
},
]
@@ -83,20 +96,22 @@ export default class index extends Component {
title: '操作',
width: 150,
dataIndex: 'actions',
render: (text, record) => (<QueryTableActions>
<Auth auth="sysArea:edit">
<a onClick={() => this.onOpen(this.editForm, record)}>编辑</a>
</Auth>
<Auth auth="sysArea:delete">
<Popconfirm
placement="topRight"
title="是否确认删除"
onConfirm={() => this.onDelete(record)}
>
<a>删除</a>
</Popconfirm>
</Auth>
</QueryTableActions>)
render: (text, record) => (
<QueryTableActions>
<Auth auth="sysArea:edit">
<a onClick={() => this.onOpen(this.editForm, record)}>编辑</a>
</Auth>
<Auth auth="sysArea:delete">
<Popconfirm
placement="topRight"
title="是否确认删除"
onConfirm={() => this.onDelete(record)}
>
<a>删除</a>
</Popconfirm>
</Auth>
</QueryTableActions>
),
})
}
}
@@ -118,31 +133,33 @@ export default class index extends Component {
*/
componentDidMount() {
this.table.current.onLoading()
getDictData('dic_areacode_type').then(res => {
this.setState({
codes: res
}, () => {
this.table.current.onLoadData()
})
getDictData('areacode_type').then(res => {
this.setState(
{
codes: res,
},
() => {
this.table.current.onLoadData()
}
)
})
}
/**
* 调用加载数据接口,可在调用前对query进行处理
* [异步,必要]
* @param {*} params
* @param {*} query
* @returns
*/
* 调用加载数据接口,可在调用前对query进行处理
* [异步,必要]
* @param {*} params
* @param {*} query
* @returns
*/
loadData = async (params, query) => {
query = {
...query,
pcode: this.selectCode
pcode: this.selectCode,
}
//首次加载根据code列升序排序
if (!params.sortField) {
params.sortField = 'code';
params.sortOrder = 'ascend';
params.sortField = 'code'
params.sortOrder = 'ascend'
}
const { data } = await apiAction.page({
...params,
@@ -181,7 +198,7 @@ export default class index extends Component {
name = toCamelCase(name)
const codes = this.state.codes[name]
if (codes) {
const c = codes.find((p) => +p.code === code)
const c = codes.find(p => +p.code === code)
if (c) {
return c.value
}
@@ -197,7 +214,7 @@ export default class index extends Component {
onOpen(modal, record) {
modal.current.open({
pcode: this.pcode,
record
record,
})
}
@@ -223,10 +240,7 @@ export default class index extends Component {
* @param {*} record
*/
onDelete(record) {
this.onAction(
apiAction.delete(record),
'删除成功'
)
this.onAction(apiAction.delete(record), '删除成功')
}
render() {
@@ -234,7 +248,7 @@ export default class index extends Component {
<QueryTreeLayout
loadData={this.loadTreeData}
defaultExpanded={true}
onSelect={(key) => this.onSelectTree(key)}
onSelect={key => this.onSelectTree(key)}
replaceFields={{ value: 'code', title: 'name', children: 'children' }}
>
<Container mode="fluid">
@@ -259,12 +273,12 @@ export default class index extends Component {
<Button
icon={<AntIcon type="plus" />}
onClick={() => this.onOpen(this.addForm)}
>新增{name}</Button>
>
新增{name}
</Button>
</Auth>
}
>
</QueryTable>
></QueryTable>
</Card>
</Container>
<ModalForm