From bbb68ef7ae4c64e14824d00bc87119cdd8202766 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=87=AA=E5=B8=A6=E5=A4=A7=E4=BD=AC=E6=B0=94=E5=9C=BA?= <188633308@qq.com> Date: Sun, 20 Jun 2021 15:07:31 +0800 Subject: [PATCH] =?UTF-8?q?add=20=E6=9F=A5=E8=AF=A2=E8=A1=A8=E6=A0=BC?= =?UTF-8?q?=E7=A7=8D=E5=AD=90=E6=96=87=E4=BB=B6=E5=8F=8A=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../public/seed/query-table-form/form.jsx | 77 +++++ web-react/public/seed/query-table/index.jsx | 237 ++++++++++++++++ web-react/src/pages/system/config/form.jsx | 134 +++++++++ web-react/src/pages/system/config/index.jsx | 263 ++++++++++++++++++ 4 files changed, 711 insertions(+) create mode 100644 web-react/public/seed/query-table-form/form.jsx create mode 100644 web-react/public/seed/query-table/index.jsx create mode 100644 web-react/src/pages/system/config/form.jsx create mode 100644 web-react/src/pages/system/config/index.jsx diff --git a/web-react/public/seed/query-table-form/form.jsx b/web-react/public/seed/query-table-form/form.jsx new file mode 100644 index 0000000..0c83022 --- /dev/null +++ b/web-react/public/seed/query-table-form/form.jsx @@ -0,0 +1,77 @@ +import React, { Component } from 'react' +import { Form, Spin } from 'antd' +import { AntIcon } from 'components' +import { cloneDeep } from 'lodash' + +const initialValues = {} + +export default class form extends Component { + state = { + // 加载状态 + loading: true, + } + + // 表单实例 + form = React.createRef() + + // 初始化数据 + record = {} + + /** + * mount后回调 + */ + componentDidMount() { + this.props.created && this.props.created(this) + } + + /** + * 填充数据 + * 可以在设置this.record之后对其作出数据结构调整 + * [异步,必要] + * @param {*} params + */ + async fillData(params) { + this.record = cloneDeep(params.record) + //#region 从后端转换成前段所需格式,也可以在此处调用获取详细数据接口 + //#endregion + this.form.current.setFieldsValue(this.record) + + this.setState({ + loading: false, + }) + } + + /** + * 获取数据 + * 可以对postData进行数据结构调整 + * [异步,必要] + * @returns + */ + async getData() { + const form = this.form.current + + const valid = await form.validateFields() + if (valid) { + const postData = form.getFieldsValue() + if (this.record) { + postData.id = this.record.id + } + //#region 从前段转换后端所需格式 + //#endregion + return postData + } + } + + //#region 自定义方法 + //#endregion + + render() { + return ( +
+ }> +
+
+
+ ) + } +} diff --git a/web-react/public/seed/query-table/index.jsx b/web-react/public/seed/query-table/index.jsx new file mode 100644 index 0000000..26773b8 --- /dev/null +++ b/web-react/public/seed/query-table/index.jsx @@ -0,0 +1,237 @@ +import React, { Component } from 'react' +import { Button, Card, Form, Input, message as Message, Popconfirm } from 'antd' +import { AntIcon, Auth, Container, ModalForm, QueryTable, QueryTableActions } from 'components' +import { api } from 'common/api' +import auth from 'components/authorized/handler' +import { isEqual } from 'lodash' +import getDictData from 'util/dic' +import { toCamelCase } from 'util/format' +import FormBody from './form' + +/** + * 注释段[\/**\/]为必须要改 + */ + +/** + * 配置页面所需接口函数 + */ +const apiAction = { + page: api /**/, + add: api /**/, + edit: api /**/, + delete: api /**/, +} + +/** + * 用于弹窗标题 + * [必要] + */ +const name = '/**/' + +/** + * 统一配置权限标识 + * [必要] + */ +const authName = '/**/' + +export default class index extends Component { + state = { + codes: {}, + } + + // 表格实例 + table = React.createRef() + + // 新增窗口实例 + addForm = React.createRef() + // 编辑窗口实例 + editForm = React.createRef() + + columns = [] + + /** + * 构造函数,在渲染前动态添加操作字段等 + * @param {*} props + */ + constructor(props) { + super(props) + + const flag = auth({ [authName]: [['edit'], ['delete']] }) + + if (flag) { + this.columns.push({ + title: '操作', + width: 150, + dataIndex: 'actions', + render: (text, record) => ( + + + this.onOpen(this.editForm, record)}>编辑 + + + this.onDelete(record)} + > + 删除 + + + + ), + }) + } + } + + /** + * 阻止外部组件引发的渲染,提升性能 + * 可自行添加渲染条件 + * [必要] + * @param {*} props + * @param {*} state + * @returns + */ + shouldComponentUpdate(props, state) { + return !isEqual(this.state, state) + } + + /** + * 加载字典数据,之后开始加载表格数据 + * 如果必须要加载字典数据,可直接对表格设置autoLoad=true + */ + componentDidMount() { + const { onLoading, onLoadData } = this.table.current + onLoading() + getDictData(/**/).then(codes => { + this.setState({ codes }, () => { + onLoadData() + }) + }) + } + + /** + * 调用加载数据接口,可在调用前对query进行处理 + * [异步,必要] + * @param {*} params + * @param {*} query + * @returns + */ + loadData = async (params, query) => { + const { data } = await apiAction.page({ + ...params, + ...query, + }) + return data + } + + /** + * 绑定字典数据 + * @param {*} code + * @param {*} name + * @returns + */ + bindCodeValue(code, name) { + name = toCamelCase(name) + const codes = this.state.codes[name] + if (codes) { + const c = codes.find(p => p.code === code) + if (c) { + return c.value + } + } + return null + } + + /** + * 打开新增/编辑弹窗 + * @param {*} modal + * @param {*} record + */ + onOpen(modal, record) { + modal.current.open({ + record, + }) + } + + /** + * 对表格上的操作进行统一处理 + * [异步] + * @param {*} action + * @param {*} successMessage + */ + async onAction(action, successMessage) { + const { onLoading, onLoaded, onReloadData } = this.table.current + onLoading() + try { + if (action) { + await action + } + if (successMessage) { + Message.success(successMessage) + } + onReloadData() + } catch { + onLoaded() + } + } + + /** + * 删除 + * @param {*} record + */ + onDelete(record) { + this.onAction(apiAction.delete(record), '删除成功') + } + + //#region 自定义方法 + //#endregion + + render() { + return ( + +
+ + } + operator={ + + + + } + /> + + + + this.table.current.onReloadData()} + > + + + + + + this.table.current.onReloadData()} + > + + + +
+ ) + } +} diff --git a/web-react/src/pages/system/config/form.jsx b/web-react/src/pages/system/config/form.jsx new file mode 100644 index 0000000..0321461 --- /dev/null +++ b/web-react/src/pages/system/config/form.jsx @@ -0,0 +1,134 @@ +import React, { Component } from 'react' +import { Form, Input, Radio, Select, Spin } from 'antd' +import { AntIcon } from 'components' +import { cloneDeep } from 'lodash' +import getDictData from 'util/dic' + +const initialValues = {} + +export default class form extends Component { + state = { + // 加载状态 + loading: true, + + codes: { + constsType: [], + }, + } + + // 表单实例 + form = React.createRef() + + // 初始化数据 + record = {} + + /** + * mount后回调 + */ + componentDidMount() { + this.props.created && this.props.created(this) + } + + /** + * 填充数据 + * 可以在设置this.record之后对其作出数据结构调整 + * [异步,必要] + * @param {*} params + */ + async fillData(params) { + this.record = cloneDeep(params.record) + //#region 从后端转换成前段所需格式,也可以在此处调用获取详细数据接口 + const codes = await getDictData('consts_type') + this.setState({ codes }) + //#endregion + this.form.current.setFieldsValue(this.record) + + this.setState({ + loading: false, + }) + } + + /** + * 获取数据 + * 可以对postData进行数据结构调整 + * [异步,必要] + * @returns + */ + async getData() { + const form = this.form.current + + const valid = await form.validateFields() + if (valid) { + const postData = form.getFieldsValue() + if (this.record) { + postData.id = this.record.id + } + //#region 从前段转换后端所需格式 + //#endregion + return postData + } + } + + //#region 自定义方法 + //#endregion + + render() { + const { codes } = this.state + + return ( +
+ }> +
+ + + + + + + + + + + + + + + + + + + + + +
+
+
+ ) + } +} diff --git a/web-react/src/pages/system/config/index.jsx b/web-react/src/pages/system/config/index.jsx new file mode 100644 index 0000000..9668b4f --- /dev/null +++ b/web-react/src/pages/system/config/index.jsx @@ -0,0 +1,263 @@ +import React, { Component } from 'react' +import { Button, Card, Form, Input, message as Message, Popconfirm } from 'antd' +import { AntIcon, Auth, Container, ModalForm, QueryTable, QueryTableActions } from 'components' +import { api } from 'common/api' +import auth from 'components/authorized/handler' +import { isEqual } from 'lodash' +import getDictData from 'util/dic' +import { toCamelCase } from 'util/format' +import FormBody from './form' + +// 配置页面所需接口函数 +const apiAction = { + page: api.sysConfigPage, + add: api.sysConfigAdd, + edit: api.sysConfigEdit, + delete: api.sysConfigDelete, +} + +// 用于弹窗标题 +const name = '应用' + +// 统一配置权限标识 +const authName = 'sysConfig' + +export default class index extends Component { + state = { + codes: { + constsType: [], + }, + } + + // 表格实例 + table = React.createRef() + + // 新增窗口实例 + addForm = React.createRef() + // 编辑窗口实例 + editForm = React.createRef() + + columns = [ + { + title: '参数名称', + dataIndex: 'name', + sorter: true, + }, + { + title: '唯一编码', + dataIndex: 'code', + sorter: true, + }, + { + title: '参数值', + dataIndex: 'value', + sorter: true, + }, + { + title: '所属分类', + dataIndex: 'groupCode', + sorter: true, + render: text => this.bindCodeValue(text, 'consts_type'), + }, + { + title: '备注', + dataIndex: 'remark', + sorter: true, + }, + ] + + /** + * 构造函数,在渲染前动态添加操作字段等 + * @param {*} props + */ + constructor(props) { + super(props) + + const flag = auth({ [authName]: [['edit'], ['delete']] }) + + if (flag) { + this.columns.push({ + title: '操作', + width: 150, + dataIndex: 'actions', + render: (text, record) => ( + + + this.onOpen(this.editForm, record)}>编辑 + + + this.onDelete(record)} + > + 删除 + + + + ), + }) + } + } + + /** + * 阻止外部组件引发的渲染,提升性能 + * 可自行添加渲染条件 + * [必要] + * @param {*} props + * @param {*} state + * @returns + */ + shouldComponentUpdate(props, state) { + return !isEqual(this.state, state) + } + + /** + * 加载字典数据,之后开始加载表格数据 + * 如果必须要加载字典数据,可直接对表格设置autoLoad=true + */ + componentDidMount() { + const { onLoading, onLoadData } = this.table.current + onLoading() + getDictData('consts_type').then(codes => { + this.setState({ codes }, () => { + onLoadData() + }) + }) + } + + /** + * 调用加载数据接口,可在调用前对query进行处理 + * [异步,必要] + * @param {*} params + * @param {*} query + * @returns + */ + loadData = async (params, query) => { + const { data } = await apiAction.page({ + ...params, + ...query, + }) + return data + } + + /** + * 绑定字典数据 + * @param {*} code + * @param {*} name + * @returns + */ + bindCodeValue(code, name) { + name = toCamelCase(name) + const codes = this.state.codes[name] + if (codes) { + const c = codes.find(p => p.code === code) + if (c) { + return c.value + } + } + return null + } + + /** + * 打开新增/编辑弹窗 + * @param {*} modal + * @param {*} record + */ + onOpen(modal, record) { + modal.current.open({ + record, + }) + } + + /** + * 对表格上的操作进行统一处理 + * [异步] + * @param {*} action + * @param {*} successMessage + */ + async onAction(action, successMessage) { + const { onLoading, onLoaded, onReloadData } = this.table.current + onLoading() + try { + if (action) { + await action + } + if (successMessage) { + Message.success(successMessage) + } + onReloadData() + } catch { + onLoaded() + } + } + + /** + * 删除 + * @param {*} record + */ + onDelete(record) { + this.onAction(apiAction.delete(record), '删除成功') + } + + //#region 自定义方法 + //#endregion + + render() { + return ( + +
+ + + + + + + + + + } + operator={ + + + + } + /> + + + + this.table.current.onReloadData()} + > + + + + + + this.table.current.onReloadData()} + > + + + +
+ ) + } +}