diff --git a/lib/field/detail/bit_select.js b/lib/field/detail/bit_select.js index 6d72c6de7b576ff0110233bd3dcabe36fe06ca9a..6b3d0240465c48a85e5f460cddabb783df729b87 100644 --- a/lib/field/detail/bit_select.js +++ b/lib/field/detail/bit_select.js @@ -9,7 +9,6 @@ var __importStar = (this && this.__importStar) || function (mod) { Object.defineProperty(exports, "__esModule", { value: true }); const React = __importStar(require("react")); const Storage = __importStar(require("./storage")); -const Render = __importStar(require("../util/render")); const Field = __importStar(require("../../config")); class BitSelect extends React.PureComponent { constructor() { @@ -31,9 +30,7 @@ class BitSelect extends React.PureComponent { }; this._renderLine = (item, key) => { const valueLabel = this._getValueLabel(item); - return valueLabel === null ? null : (React.createElement("div", { key: key, className: "xc-bit-select-view" }, - item.fieldLabel + ": " + valueLabel, - Render.description(item.description, item.showTag))); + return valueLabel === null ? null : (React.createElement("div", { key: key, className: "xc-bit-select-view" }, item.fieldLabel + ": " + valueLabel)); }; } render() { @@ -48,8 +45,7 @@ class BitSelect extends React.PureComponent { const item = field.options.dataSource[idx]; const valueLabel = this._getValueLabel(item); return (React.createElement("div", { className: "xc-detail-content" }, - React.createElement("span", { style: { width: field.options.valueWidth || "auto" } }, valueLabel), - Render.description(item.description, item.showTag))); + React.createElement("span", { style: { width: field.options.valueWidth || "auto" } }, valueLabel))); } return (React.createElement("div", null, field.options.dataSource.map(this._renderLine))); } diff --git a/lib/field/detail/date_time.js b/lib/field/detail/date_time.js index ec59bf0ae11140a0cb62f289df02ad52d5a092ef..25157391f3c7d184bf4d6c9d23752a1e53027907 100644 --- a/lib/field/detail/date_time.js +++ b/lib/field/detail/date_time.js @@ -13,7 +13,6 @@ Object.defineProperty(exports, "__esModule", { value: true }); const React = __importStar(require("react")); const moment_1 = __importDefault(require("moment")); const Storage = __importStar(require("./storage")); -const Render = __importStar(require("../util/render")); const Field = __importStar(require("../../config")); class DateTime extends React.PureComponent { constructor() { @@ -57,8 +56,7 @@ class DateTime extends React.PureComponent { return value === "" ? React.createElement("div", { className: "xc-detail-content" }) : React.createElement("div", { className: "xc-detail-content" }, - React.createElement("span", { style: { width: field.options.valueWidth || "auto" } }, value), - Render.description(field.options.description, field.options.showTag)); + React.createElement("span", { style: { width: field.options.valueWidth || "auto" } }, value)); } } Storage.set(Field.DateTime.Type, (option) => React.createElement(DateTime, Object.assign({}, option))); diff --git a/lib/field/detail/digit.js b/lib/field/detail/digit.js index bc202b700cd45a7c7519a6c912559fd650970aef..55d0c2c185012978439b50a787470cf8c22f1330 100644 --- a/lib/field/detail/digit.js +++ b/lib/field/detail/digit.js @@ -29,8 +29,7 @@ class DigitView extends React.PureComponent { ? React.createElement("div", { className: "xc-detail-content" }) : React.createElement("div", { className: "xc-detail-content" }, React.createElement("span", { style: { width: field.options.valueWidth || "auto" } }, value), - Render.unit(field.options.unitLabel, field.options.showTag, field.options.unitWidth), - Render.description(field.options.description, field.options.showTag)); + Render.unit(field.options.unitLabel, false, field.options.unitWidth)); } } Storage.set(Field.Digit.Type, (option) => React.createElement(DigitView, Object.assign({}, option))); diff --git a/lib/field/detail/select.js b/lib/field/detail/select.js index 6f793594db5ab561544d3ff9217979109f0d462d..6cf79e55ac3c637e47133543de89714e7d521507 100644 --- a/lib/field/detail/select.js +++ b/lib/field/detail/select.js @@ -56,8 +56,7 @@ class Select extends React.PureComponent { ? React.createElement("div", { className: "xc-detail-content" }) : React.createElement("div", { className: "xc-detail-content" }, React.createElement("span", { style: { width: field.options.valueWidth || "auto" } }, value), - Render.unit(field.options.unitLabel, field.options.showTag, field.options.unitWidth), - Render.description(field.options.description, field.options.showTag)); + Render.unit(field.options.unitLabel, false, field.options.unitWidth)); } } Storage.set(Field.Select.Type, (option) => React.createElement(Select, Object.assign({}, option))); diff --git a/lib/field/detail/switch.js b/lib/field/detail/switch.js index b0c7e7f8716a909ac46cf55b71e34a1704058796..b2703a8035ecfddfc204f045c5d5b55fcda744c2 100644 --- a/lib/field/detail/switch.js +++ b/lib/field/detail/switch.js @@ -32,8 +32,7 @@ class Switch extends React.PureComponent { ? (b ? React.createElement("span", { style: { width: "15px", height: "15px", backgroundColor: "green", borderRadius: "50%" } }) : React.createElement("span", { style: { width: "15px", height: "15px", backgroundColor: "red", borderRadius: "50%" } })) - : Render.unit(field.options.unitLabel, field.options.showTag, field.options.unitWidth), - Render.description(field.options.description, field.options.showTag)); + : Render.unit(field.options.unitLabel, false, field.options.unitWidth)); } ; } diff --git a/lib/field/detail/text.js b/lib/field/detail/text.js index 0f05143b411e8e0f8a488d9cc785b4d910787564..4c737e02f6048a0a0f06591c89d681c0420d9c12 100644 --- a/lib/field/detail/text.js +++ b/lib/field/detail/text.js @@ -25,8 +25,7 @@ class TextView extends React.PureComponent { field.options.render === undefined ? React.createElement("span", { style: { width: field.options.valueWidth || "auto" } }, value) : field.options.render(value), - Render.unit(field.options.unitLabel, field.options.showTag, field.options.unitWidth), - Render.description(field.options.description, field.options.showTag)); + Render.unit(field.options.unitLabel, false, field.options.unitWidth)); } } Storage.set(Field.Text.Type, (option) => React.createElement(TextView, Object.assign({}, option))); diff --git a/lib/field/detail/tree_select.js b/lib/field/detail/tree_select.js index 77d69f23159705886df1ab39b28937defca3d8ed..e80954e486b42bf269124f414be6d0f6b13b99dd 100644 --- a/lib/field/detail/tree_select.js +++ b/lib/field/detail/tree_select.js @@ -9,7 +9,6 @@ var __importStar = (this && this.__importStar) || function (mod) { Object.defineProperty(exports, "__esModule", { value: true }); const React = __importStar(require("react")); const Storage = __importStar(require("./storage")); -const Render = __importStar(require("../util/render")); const Field = __importStar(require("../../config")); class TreeSelectView extends React.PureComponent { constructor() { @@ -59,8 +58,7 @@ class TreeSelectView extends React.PureComponent { return value === "" ? React.createElement("div", { className: "xc-detail-content" }) : React.createElement("div", { className: "xc-detail-content" }, - React.createElement("span", { style: { width: field.options.valueWidth || "auto" } }, value), - Render.description(field.options.description, field.options.showTag)); + React.createElement("span", { style: { width: field.options.valueWidth || "auto" } }, value)); } } Storage.set(Field.TreeSelect.Type, (option) => React.createElement(TreeSelectView, Object.assign({}, option))); diff --git a/lib/field/modify/bit_select.js b/lib/field/modify/bit_select.js index c6fa445d69f9e11cbd0161063083256687d7c315..5174fe600e4365346a4419a26ce0903196bc9a8b 100644 --- a/lib/field/modify/bit_select.js +++ b/lib/field/modify/bit_select.js @@ -22,15 +22,16 @@ class BitSelect extends React.PureComponent { return (React.createElement(antd_1.Row, { className: "xc-bit-select-row", key: idx.toString() }, React.createElement(antd_1.Col, { span: field.options.colSpan }, option.fieldLabel), React.createElement(antd_1.Col, { span: 24 - field.options.colSpan }, - React.createElement(antd_1.Form.Item, null, - form.getFieldDecorator(this._bitFieldName(option), { - rules: [{ - required: field.options.required, - message: "请填写" + option.fieldLabel, - }], - initialValue: this._getDefaultValue(option), - })(React.createElement(antd_1.Radio.Group, { name: this._bitFieldName(option), onChange: this._onChange.bind(this, option) }, option.values.map((v, i) => (React.createElement(antd_1.Radio, { key: v, value: v }, option.labels[i]))))), - Render.description(option.description, option.showTag === undefined ? true : option.showTag))))); + React.createElement(antd_1.Form.Item, { className: "xc-modify-content" }, + React.createElement("div", null, + React.createElement("div", null, form.getFieldDecorator(this._bitFieldName(option), { + rules: [{ + required: field.options.required, + message: "请填写" + option.fieldLabel, + }], + initialValue: this._getDefaultValue(option), + })(React.createElement(antd_1.Radio.Group, { name: this._bitFieldName(option), onChange: this._onChange.bind(this, option) }, option.values.map((v, i) => (React.createElement(antd_1.Radio, { key: v, value: v }, option.labels[i])))))), + Render.description(option.description, option.showTag)))))); }; this._onChange = (option, e) => { const { form } = this.props; diff --git a/lib/field/modify/date_time.js b/lib/field/modify/date_time.js index 19aca07793eb5a332ad2692daf38138d34a20c1f..969b28612e6ea685661e9bda76e32da911fb60bb 100644 --- a/lib/field/modify/date_time.js +++ b/lib/field/modify/date_time.js @@ -85,14 +85,15 @@ class DateTime extends React.PureComponent { } } return (React.createElement(antd_1.Form.Item, { className: "xc-modify-content", label: label }, - form.getFieldDecorator(Storage.Prefix + field.name, { - initialValue: initialValue, - rules: [{ - required: field.options.required, - message: "请填写" + label, - }] - })(onlyTime ? (React.createElement(antd_1.TimePicker, { placeholder: field.options.placeholder, format: field.options.dateFormat, style: { width: field.options.valueWidth || 200 }, onChange: this._onChange })) : (React.createElement(antd_1.DatePicker, { showTime: field.options.hasTime, placeholder: field.options.placeholder, format: field.options.dateFormat, style: { width: field.options.valueWidth || 200 }, onChange: this._onChange }))), - Render.description(field.options.description, field.options.showTag === undefined ? true : field.options.showTag))); + React.createElement("div", null, + React.createElement("div", null, form.getFieldDecorator(Storage.Prefix + field.name, { + initialValue: initialValue, + rules: [{ + required: field.options.required, + message: "请填写" + label, + }] + })(onlyTime ? (React.createElement(antd_1.TimePicker, { placeholder: field.options.placeholder, format: field.options.dateFormat, style: { width: field.options.valueWidth || 200 }, onChange: this._onChange })) : (React.createElement(antd_1.DatePicker, { showTime: field.options.hasTime, placeholder: field.options.placeholder, format: field.options.dateFormat, style: { width: field.options.valueWidth || 200 }, onChange: this._onChange })))), + Render.description(field.options.description, field.options.showTag)))); } } Storage.set(Field.DateTime.Type, (option) => React.createElement(DateTime, Object.assign({}, option))); diff --git a/lib/field/modify/digit.js b/lib/field/modify/digit.js index 1ad7dd301a21c50cadaaf455549aefdd3a453760..dd6b1174e52d73570adc854a3cf8c25008700aa6 100644 --- a/lib/field/modify/digit.js +++ b/lib/field/modify/digit.js @@ -48,15 +48,17 @@ class Digit extends React.PureComponent { } } return (React.createElement(antd_1.Form.Item, { className: "xc-modify-content", label: label }, - form.getFieldDecorator(Storage.Prefix + field.name, { - rules: [{ - required: field.options.required, - message: "请填写" + label, - }], - initialValue: initialValue, - })(React.createElement(antd_1.InputNumber, { max: field.options.max, min: field.options.min, step: field.options.step, style: { width: field.options.valueWidth || 200 }, onChange: this._onChange })), - Render.unit(field.options.unitLabel, field.options.showTag === undefined ? true : field.options.showTag, field.options.unitWidth), - Render.description(field.options.description, field.options.showTag === undefined ? true : field.options.showTag))); + React.createElement("div", null, + React.createElement("div", null, + form.getFieldDecorator(Storage.Prefix + field.name, { + rules: [{ + required: field.options.required, + message: "请填写" + label, + }], + initialValue: initialValue, + })(React.createElement(antd_1.InputNumber, { max: field.options.max, min: field.options.min, step: field.options.step, style: { width: field.options.valueWidth || 200 }, onChange: this._onChange })), + Render.unit(field.options.unitLabel, true, field.options.unitWidth)), + Render.description(field.options.description, field.options.showTag)))); } } Storage.set(Field.Digit.Type, (option) => React.createElement(Digit, Object.assign({}, option))); diff --git a/lib/field/modify/select.js b/lib/field/modify/select.js index ca32d35f481deb69c5c8c6bd6f81e28d710b2bc4..3a22cd625d319432b649482821f449679ab9f69a 100644 --- a/lib/field/modify/select.js +++ b/lib/field/modify/select.js @@ -48,20 +48,22 @@ class SelectView extends React.PureComponent { const label = field.options.label || field.label; const mul = field.options.multiple; return (React.createElement(antd_1.Form.Item, { className: "xc-modify-content", label: label, hasFeedback: !mul }, - form.getFieldDecorator(field.name, { - initialValue: this.props.initialValue, - rules: [{ - required: field.options.required, - message: "请填写" + label, - type: mul ? "array" : field.options.valueType, - }], - })(React.createElement(antd_1.Select, { mode: mul ? "multiple" : "default", placeholder: field.options.placeholder, style: { width: field.options.valueWidth || 200 }, showSearch: field.options.filtered, showArrow: field.options.filtered, filterOption: field.options.filtered - ? (value, option) => { - return option.props.children.indexOf(value) >= 0; - } - : undefined, onChange: this._onChange }, this.state.dataSource !== undefined ? this.state.dataSource.map(this._renderSelectOption) : undefined)), - Render.unit(field.options.unitLabel, field.options.showTag === undefined ? true : field.options.showTag, field.options.unitWidth), - Render.description(field.options.description, field.options.showTag === undefined ? true : field.options.showTag))); + React.createElement("div", null, + React.createElement("div", null, + form.getFieldDecorator(field.name, { + initialValue: this.props.initialValue, + rules: [{ + required: field.options.required, + message: "请填写" + label, + type: mul ? "array" : field.options.valueType, + }], + })(React.createElement(antd_1.Select, { mode: mul ? "multiple" : "default", placeholder: field.options.placeholder, style: { width: field.options.valueWidth || 200 }, showSearch: field.options.filtered, showArrow: field.options.filtered, filterOption: field.options.filtered + ? (value, option) => { + return option.props.children.indexOf(value) >= 0; + } + : undefined, onChange: this._onChange }, this.state.dataSource === undefined ? undefined : this.state.dataSource.map(this._renderSelectOption))), + Render.unit(field.options.unitLabel, true, field.options.unitWidth)), + Render.description(field.options.description, field.options.showTag)))); } } Storage.set(Field.Select.Type, (option) => React.createElement(SelectView, Object.assign({}, option))); diff --git a/lib/field/modify/switch.js b/lib/field/modify/switch.js index 15eed88cd31e88e81d4f2b82919e2e715c07fe5c..fbf6299618a922d6f2c96e385fc5cd176693715f 100644 --- a/lib/field/modify/switch.js +++ b/lib/field/modify/switch.js @@ -31,20 +31,22 @@ class SwitchView extends React.PureComponent { const useRadio = field.options.useRadio; const initialValue = this.props.initialValue || false; return (React.createElement(antd_1.Form.Item, { className: "xc-modify-content", label: label }, - form.getFieldDecorator(field.name, { - initialValue: initialValue, - valuePropName: "checked", - rules: [{ - required: field.options.required, - message: "请填写" + label, - }], - })(useRadio - ? React.createElement(antd_1.Radio.Group, { name: field.name, defaultValue: initialValue, style: { width: field.options.valueWidth || 200 }, onChange: this._onRadioChange }, - React.createElement(antd_1.Radio, { value: true }, field.options.trueLabel), - React.createElement(antd_1.Radio, { value: false }, field.options.falseLabel)) - : React.createElement(antd_1.Switch, { checkedChildren: field.options.trueLabel, unCheckedChildren: field.options.falseLabel, style: { width: field.options.valueWidth || "auto" }, onChange: this._onSwitchChange })), - useRadio ? null : Render.unit(field.options.unitLabel, field.options.showTag === undefined ? true : field.options.showTag, field.options.unitWidth), - Render.description(field.options.description, field.options.showTag === undefined ? true : field.options.showTag))); + React.createElement("div", null, + React.createElement("div", null, + form.getFieldDecorator(field.name, { + initialValue: initialValue, + valuePropName: "checked", + rules: [{ + required: field.options.required, + message: "请填写" + label, + }], + })(useRadio + ? React.createElement(antd_1.Radio.Group, { name: field.name, defaultValue: initialValue, style: { width: field.options.valueWidth || 200 }, onChange: this._onRadioChange }, + React.createElement(antd_1.Radio, { value: true }, field.options.trueLabel), + React.createElement(antd_1.Radio, { value: false }, field.options.falseLabel)) + : React.createElement(antd_1.Switch, { checkedChildren: field.options.trueLabel, unCheckedChildren: field.options.falseLabel, style: { width: field.options.valueWidth || "auto" }, onChange: this._onSwitchChange })), + useRadio ? null : Render.unit(field.options.unitLabel, true, field.options.unitWidth)), + Render.description(field.options.description, field.options.showTag)))); } } Storage.set(Field.Switch.Type, (option) => React.createElement(SwitchView, Object.assign({}, option))); diff --git a/lib/field/modify/text.js b/lib/field/modify/text.js index bda6e731b4b31488ef74d1cd89b1ee0f17f1cfbe..c391620d6e2430035f70ca781c704dc071b508ce 100644 --- a/lib/field/modify/text.js +++ b/lib/field/modify/text.js @@ -19,16 +19,18 @@ class TextView extends React.PureComponent { const form = this.props.form; const label = field.options.label || field.label; return (React.createElement(antd_1.Form.Item, { className: "xc-modify-content", label: label }, - form.getFieldDecorator(field.name, { - rules: [{ - required: field.options.required, - message: "请填写" + label, - max: field.options.maxLength > 0 ? field.options.maxLength : undefined, - }], - initialValue: this.props.initialValue || "", - })(React.createElement(antd_1.Input, { placeholder: field.options.placeholder, style: { width: field.options.valueWidth || 200 } })), - Render.unit(field.options.unitLabel, field.options.showTag === undefined ? true : field.options.showTag, field.options.unitWidth), - Render.description(field.options.description, field.options.showTag === undefined ? true : field.options.showTag))); + React.createElement("div", null, + React.createElement("div", null, + form.getFieldDecorator(field.name, { + rules: [{ + required: field.options.required, + message: "请填写" + label, + max: field.options.maxLength > 0 ? field.options.maxLength : undefined, + }], + initialValue: this.props.initialValue || "", + })(React.createElement(antd_1.Input, { placeholder: field.options.placeholder, style: { width: field.options.valueWidth || 200 } })), + Render.unit(field.options.unitLabel, true, field.options.unitWidth)), + Render.description(field.options.description, field.options.showTag)))); } } Storage.set(Field.Text.Type, (option) => React.createElement(TextView, Object.assign({}, option))); diff --git a/lib/field/modify/tree_select.js b/lib/field/modify/tree_select.js index a11fe579a0607dadde8f6e019d4463425ebf66fc..fe97e55eedb89814ba26040c1a5160f94217f862 100644 --- a/lib/field/modify/tree_select.js +++ b/lib/field/modify/tree_select.js @@ -51,7 +51,7 @@ class TreeSelectView extends React.PureComponent { maxHeight: field.options.maxHeight, overflow: 'auto', }, multiple: field.options.multiple, treeData: this.state.tree, placeholder: field.options.placeholder, treeDefaultExpandAll: field.options.defaultExpandAll, style: { width: field.options.valueWidth || 500 }, onChange: this._onChange })), - Render.description(field.options.description, field.options.showTag === undefined ? true : field.options.showTag))); + Render.description(field.options.description, field.options.showTag))); } } Storage.set(Field.TreeSelect.Type, (option) => React.createElement(TreeSelectView, Object.assign({}, option))); diff --git a/lib/field/util/render.js b/lib/field/util/render.js index b10462607860197e6548b996a9c0f32478c91d28..ce9647bce159d085a35a9025b45172c65f237562 100644 --- a/lib/field/util/render.js +++ b/lib/field/util/render.js @@ -18,8 +18,8 @@ function unit(unit, tag, witdh) { exports.unit = unit; function description(desc, tag) { return desc - ? (tag === true + ? (tag === undefined || tag === true ? React.createElement(antd_1.Tag, { color: "blue" }, desc) - : React.createElement("span", null, unit)) : null; + : React.createElement("span", null, desc)) : null; } exports.description = description; diff --git a/lib/page/create.d.ts b/lib/page/create.d.ts index 05b6b949b88399dc4b791197fd8ea3493d234a27..df9357652a5c8d79f781416d6547e29e39842c0b 100644 --- a/lib/page/create.d.ts +++ b/lib/page/create.d.ts @@ -12,6 +12,10 @@ interface Props { * 字段列表。 */ fields: Field.Base.CreateConfig[]; + /** + * 提交按钮是否显示。 + */ + submitShow: boolean; /** * 提交按钮的自定义标签。 */ @@ -52,6 +56,7 @@ interface CreateFormProps extends FormComponentProps, Props { } declare class CreateComponent extends React.PureComponent { static defaultProps: { + submitShow: boolean; submitLabel: string; formProps: {}; submitFormItemProps: {}; @@ -66,5 +71,5 @@ declare class CreateComponent extends React.PureComponent { _onReset: (e: React.MouseEvent) => void; getFormValues: (getFormData: (values: any) => void) => void; } -declare const _default: import("antd/lib/form/interface").ConnectedComponentClass>; +declare const _default: import("antd/lib/form/interface").ConnectedComponentClass>; export default _default; diff --git a/lib/page/create.js b/lib/page/create.js index 7627024644961f9984bc0e008763a4610a318a25..55a1e40757fd66ffddde8407e5f2a6f001ce7dca 100644 --- a/lib/page/create.js +++ b/lib/page/create.js @@ -63,7 +63,9 @@ class CreateComponent extends React.PureComponent { // 渲染按钮 this._renderSubmit = () => { return (React.createElement(antd_1.Form.Item, Object.assign({ className: "xc-form-button", label: " ", colon: false, style: { height: "auto" } }, this.defaultSubmitFormItemProps, this.props.submitFormItemProps), - React.createElement(antd_1.Button, { className: "xc-button-default", icon: "check", type: "primary", htmlType: "submit" }, this.props.submitLabel), + this.props.submitShow + ? React.createElement(antd_1.Button, { className: "xc-button-default", icon: "check", type: "primary", htmlType: "submit" }, this.props.submitLabel) + : null, this.props.action && this.props.action.map((node) => { return node; }), @@ -137,6 +139,7 @@ class CreateComponent extends React.PureComponent { } } CreateComponent.defaultProps = { + submitShow: true, submitLabel: "提交", formProps: {}, submitFormItemProps: {}, diff --git a/lib/page/detail.d.ts b/lib/page/detail.d.ts index 0774440c7a6954a0b44dd1c2ba716f25c3bbae82..cd7729713b57a331e8c5f81b5e4cf58451911f9b 100644 --- a/lib/page/detail.d.ts +++ b/lib/page/detail.d.ts @@ -45,6 +45,7 @@ export default class extends React.PureComponent { _renderWithTitle: () => JSX.Element; _renderWithoutTitle: () => JSX.Element; _renderField: (field: Field.Base.DetailConfig) => React.ReactNode[] | JSX.Element; + _renderLabel: (label: string, width: number, desc?: string | undefined) => JSX.Element; _renderAction: () => JSX.Element | null; } export {}; diff --git a/lib/page/detail.js b/lib/page/detail.js index 6de7bf05b1dd885f1b75b59eba563d7aca2fef2e..2a0a4a80e40b3386ba0a77a2ff1d88d7eb35a9a8 100644 --- a/lib/page/detail.js +++ b/lib/page/detail.js @@ -48,7 +48,7 @@ class default_1 extends React.PureComponent { data: this.props.data, }; const DetailFieldNode = DetailFields.get(option); - items.push(React.createElement(antd_1.Descriptions.Item, { key: idx, label: (React.createElement("div", { style: { width: labelWidth } }, item.fieldLabel)), span: field.options.span }, + items.push(React.createElement(antd_1.Descriptions.Item, { key: idx, label: this._renderLabel(item.fieldLabel, labelWidth, item.description), span: field.options.span }, React.createElement("div", { style: { width: dataWidth } }, DetailFieldNode))); }); return items; @@ -58,10 +58,17 @@ class default_1 extends React.PureComponent { const option = { field, data: this.props.data }; const label = field.options.label || field.label; const DetailFieldNode = DetailFields.get(option); - return (React.createElement(antd_1.Descriptions.Item, { key: field.name, label: (React.createElement("div", { style: { width: labelWidth } }, label)), span: field.options.span }, + return (React.createElement(antd_1.Descriptions.Item, { key: field.name, label: this._renderLabel(label, labelWidth, field.options.description), span: field.options.span }, React.createElement("div", { style: { width: dataWidth } }, DetailFieldNode))); } }; + this._renderLabel = (label, width, desc) => { + return desc === undefined || desc === "" + ? (React.createElement("div", { style: { width: width } }, label)) : (React.createElement(antd_1.Tooltip, { title: desc, placement: "top", arrowPointAtCenter: true, overlayClassName: "xc-detail-description" }, + React.createElement("div", { style: { width: width, cursor: "pointer" } }, + label, + React.createElement(antd_1.Icon, { type: "question-circle", style: { marginLeft: "4px", color: "#f50" } })))); + }; // 渲染按钮 this._renderAction = () => { const labelWidth = this.props.labelWidth || 118; diff --git a/lib/page/list.d.ts b/lib/page/list.d.ts index 08311ea49ec4fda7eddb65d347fe929bb8e7a791..a15a0b3304ef6fead329d2763bd4f2050f530b53 100644 --- a/lib/page/list.d.ts +++ b/lib/page/list.d.ts @@ -18,10 +18,18 @@ export interface FetchDataResult { count: number; } export interface Action { + /** + * 图标类型。 + */ + icon?: string; /** * 文字内容。 */ - label?: React.ReactNode | ((data: any, mainKey: string) => React.ReactNode); + label?: string; + /** + * 提示内容。 + */ + tooltip?: string; /** * 是否启用。 */ @@ -35,24 +43,24 @@ export interface Action { */ modalClick?: (data: any, mainKey: string) => Promise; /** - * 弹框模式的标题栏(优先modalField)。 - */ + * 弹框模式的标题栏(优先modalField)。 + */ modalTitle?: string; /** - * 弹框模式标题栏的取值字段(如果modalField和modalTitle都未设置,则不是弹框)。 - */ + * 弹框模式标题栏的取值字段(如果modalField和modalTitle都未设置,则不是弹框)。 + */ modalField?: string; /** - * 弹框模式的内容。 - */ + * 弹框模式的内容。 + */ modalContent?: string; /** - * 弹框模式的操作成功提示。 - */ + * 弹框模式的操作成功提示。 + */ modalSuccessInfo?: string; /** - * 弹框模式的操作错误提示。 - */ + * 弹框模式的操作错误提示。 + */ modalErrorInfo?: string; } interface Props { @@ -91,7 +99,7 @@ interface Props { /** * 右侧其他操作。 */ - otherActions: Action[]; + otherActions?: Action[]; /** * 操作列的附加属性。 */ @@ -139,7 +147,6 @@ interface State { } export default class ListPage extends React.PureComponent { static defaultProps: { - otherActions: never[]; actionColumnProps: {}; tableProps: {}; autoLoad: boolean; @@ -158,11 +165,10 @@ export default class ListPage extends React.PureComponent { _fetchData: (pageNumber: number, filters: any, sorter: any) => void; _onSelectRows: (selectedKeys: any[]) => void; _renderColumns: () => JSX.Element[]; - _actions: () => Action[]; _renderColumnAction: (text: string, record: { [key: string]: any; }) => JSX.Element; - _getActionLabel: (action: Action, defaultValue: string, data: any, mainKey: string) => any; + _actions: () => Action[]; _onModalClick: (act: Action, data: any, mainKey: string) => void; _onDeleteClick: (data: any, mainKey: string) => void; _onAction: (action: (data: any, mainKey: string) => Promise, data: any, mainKey: string, pn: number, success: string, error: string) => void; diff --git a/lib/page/list.js b/lib/page/list.js index febbd923b8c6fbd38ed8f008c53504f53bd1ecb7..e1070daf96d065ea768208f147cd2a438837716f 100644 --- a/lib/page/list.js +++ b/lib/page/list.js @@ -6,12 +6,16 @@ var __importStar = (this && this.__importStar) || function (mod) { result["default"] = mod; return result; }; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", { value: true }); /** * 通用的列表页。 */ const React = __importStar(require("react")); const antd_1 = require("antd"); +const list_col_action_1 = __importDefault(require("./list_col_action")); const DetailFields = __importStar(require("../field/detail")); class ListPage extends React.PureComponent { constructor() { @@ -38,7 +42,7 @@ class ListPage extends React.PureComponent { showTotal: (total) => "共 " + total + " 条", }; }; - // 表格切换页的回调 + // 列表翻页,过滤和排序的操作 this._onTableChange = (pagination, filters, sorter) => { const pageNumber = pagination.current; this._fetchData(pageNumber, filters, sorter); @@ -87,24 +91,42 @@ class ListPage extends React.PureComponent { } return columns; }; + // 渲染表格"操作"列 + this._renderColumnAction = (text, record) => { + return (React.createElement(list_col_action_1.default, { record: record, mainKey: this.props.mainKey, actions: this._actions() })); + }; // 生成操作项列表 this._actions = () => { const actions = []; if (this.props.editAction) { - const action = Object.assign(Object.assign({}, this.props.editAction), { label: this.props.editAction.label || "编辑" }); + const action = Object.assign(Object.assign({}, this.props.editAction), { icon: this.props.editAction.icon || "edit", label: this.props.editAction.label || "编辑" }); actions.push(action); + if (this.props.otherActions || this.props.deleteAction) { + // 有其他操作或删除操作时增加隔断 + actions.push({ label: "devide1" }); + } + } + if (this.props.otherActions && this.props.otherActions.length > 0) { + this.props.otherActions.forEach((act) => { + const action = { + icon: act.icon || "right", + label: act.label, + tooltip: act.tooltip, + enable: act.enable, + onClick: this._onModalClick.bind(this, act), + }; + actions.push(action); + }); + if (this.props.deleteAction) { + // 有删除操作时增加隔断 + actions.push({ label: "devide2" }); + } } - this.props.otherActions.forEach((act) => { - const action = { - label: act.label, - enable: act.enable, - onClick: this._onModalClick.bind(this, act), - }; - actions.push(action); - }); if (this.props.deleteAction) { const action = { + icon: this.props.deleteAction.icon || "delete", label: this.props.deleteAction.label || "删除", + tooltip: this.props.deleteAction.tooltip, enable: this.props.deleteAction.enable, onClick: this._onDeleteClick, }; @@ -112,37 +134,6 @@ class ListPage extends React.PureComponent { } return actions; }; - // 渲染表格"操作"列 - this._renderColumnAction = (text, record) => { - const actions = this._actions(); - const views = []; - actions.forEach((item, index) => { - const enabled = item.enable ? item.enable(record, this.props.mainKey) : true; - if (!enabled) { - return; - } - const label = this._getActionLabel(item, "未知", record, this.props.mainKey); - views.push(React.createElement("a", { key: index * 2, onClick: (e) => { - item.onClick && item.onClick(record, this.props.mainKey); - e.stopPropagation(); - } }, label)); - views.push(React.createElement(antd_1.Divider, { key: index * 2 + 1, type: "vertical" })); - }); - return (React.createElement("span", null, views.slice(0, views.length - 1))); - }; - // 获取操作标签 - this._getActionLabel = (action, defaultValue, data, mainKey) => { - const label = action.label; - if (typeof label === "function") { - return label && label(data, mainKey); - } - else if (label) { - return label; - } - else { - return defaultValue; - } - }; // 其他操作的弹框模式兼容(操作后刷新数据并保留在当前页) this._onModalClick = (act, data, mainKey) => { if (act.modalClick) { @@ -221,6 +212,7 @@ class ListPage extends React.PureComponent { this.props.deleteAction.onClick(data, mainKey); } }; + // 执行操作 this._onAction = (action, data, mainKey, pn, success, error) => { // 先执行操作再重新加载列表 action(data, mainKey).then(() => { @@ -248,7 +240,6 @@ class ListPage extends React.PureComponent { } exports.default = ListPage; ListPage.defaultProps = { - otherActions: [], actionColumnProps: {}, tableProps: {}, autoLoad: true, diff --git a/lib/page/list_col_action.d.ts b/lib/page/list_col_action.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..2c4ba5c0776f15fdeb4e6e77f9f348e9475c37a7 --- /dev/null +++ b/lib/page/list_col_action.d.ts @@ -0,0 +1,32 @@ +/** + * 通用的列表。 + */ +import * as React from 'react'; +import { ClickParam } from 'antd/lib/menu'; +import { Action } from './list'; +interface Props { + /** + * 字段列表。 + */ + record: { + [key: string]: any; + }; + /** + * 数据主键名称。 + */ + mainKey: string; + /** + * 操作项。 + */ + actions: Action[]; +} +interface State { + visible: boolean; +} +export default class extends React.PureComponent { + state: State; + render(): JSX.Element | null; + onMenuClick: (param: ClickParam) => void; + onDropdownVisibleChange: (visible: boolean) => void; +} +export {}; diff --git a/lib/page/list_col_action.js b/lib/page/list_col_action.js new file mode 100644 index 0000000000000000000000000000000000000000..f0c63b382e8f16a9e25d46bc87cb24f58b1ef52f --- /dev/null +++ b/lib/page/list_col_action.js @@ -0,0 +1,68 @@ +"use strict"; +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result["default"] = mod; + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * 通用的列表。 + */ +const React = __importStar(require("react")); +const antd_1 = require("antd"); +class default_1 extends React.PureComponent { + constructor() { + super(...arguments); + this.state = { visible: false }; + this.onMenuClick = (param) => { + param.domEvent.stopPropagation(); + this.setState({ visible: false }); + }; + this.onDropdownVisibleChange = (visible) => { + this.setState({ visible: visible }); + }; + } + render() { + const actions = this.props.actions.filter((a) => a.enable ? a.enable(this.props.record, this.props.mainKey) : true); + if (actions.length === 0 || actions.filter((a) => a.label === undefined || a.label.indexOf("devide") < 0).length === 0) { + // 没有操作项或没有除devide之外的操作项,则返回空 + return null; + } + const menus = []; + actions.forEach((item, index) => { + const label = item.label || "未知"; + if (label.indexOf("devide1") >= 0) { + // 当devide1为第二个元素时,也即有编辑按钮,则显示分隔符;否则忽略 + if (index === 1) { + menus.push(React.createElement(antd_1.Menu.Divider, { key: index + actions.length + 1 })); + } + } + else if (label.indexOf("devide2") >= 0) { + // 当devide2为倒数第二个元素时,也即有删除2按钮,则显示分隔符;否则忽略 + if (index === actions.length - 2) { + menus.push(React.createElement(antd_1.Menu.Divider, { key: index + actions.length + 1 })); + } + } + else { + // 显示非分隔符的操作项 + menus.push(React.createElement(antd_1.Menu.Item, { key: index, onClick: (e) => { + item.onClick && item.onClick(this.props.record, this.props.mainKey); + }, className: "xc-page-list-op-item" }, + React.createElement(antd_1.Icon, { type: item.icon, style: { marginRight: "12px", color: "#f50" } }), + item.tooltip + ? React.createElement(antd_1.Tooltip, { title: item.tooltip, placement: "top", arrowPointAtCenter: true }, + React.createElement("span", null, label), + React.createElement(antd_1.Icon, { type: "question-circle", style: { marginLeft: "4px", color: "#f50" } })) + : React.createElement("span", null, label))); + } + }); + return (React.createElement(antd_1.Dropdown, { overlay: React.createElement(antd_1.Menu, { onClick: this.onMenuClick }, menus), trigger: ['click'], placement: "bottomRight", visible: this.state.visible, onVisibleChange: this.onDropdownVisibleChange }, + React.createElement(antd_1.Icon, { type: "more", style: { border: "1px solid #d9d9d9", borderRadius: "50%", padding: "2px", cursor: "pointer", color: "#f50" }, onClick: (e) => { + e.stopPropagation(); + } }))); + } + ; +} +exports.default = default_1; diff --git a/src/field/detail/bit_select.tsx b/src/field/detail/bit_select.tsx index c7282988c388eb132960ac0262bb6be4cef48f3d..c541902a1b08eebe542fe2e526f8451a8a63ee7c 100644 --- a/src/field/detail/bit_select.tsx +++ b/src/field/detail/bit_select.tsx @@ -22,7 +22,6 @@ class BitSelect extends React.PureComponent { {valueLabel} - {Render.description(item.description, item.showTag)} ); } @@ -54,7 +53,6 @@ class BitSelect extends React.PureComponent { return valueLabel === null ? null : (
{item.fieldLabel + ": " + valueLabel} - {Render.description(item.description, item.showTag)}
); }; diff --git a/src/field/detail/date_time.tsx b/src/field/detail/date_time.tsx index 61c73fb770fa3612f8414e6486494988f6e649e1..ffc92b42c32f3929ecf06bf544a1b52ca867d7b5 100644 --- a/src/field/detail/date_time.tsx +++ b/src/field/detail/date_time.tsx @@ -16,7 +16,6 @@ class DateTime extends React.PureComponent { {value} - {Render.description(field.options.description, field.options.showTag)} ; } diff --git a/src/field/detail/digit.tsx b/src/field/detail/digit.tsx index 18e5f9cec84ada0c66bf8856d83724b33dbc8523..269f251bf753f367550604fe9cc935f87014db12 100644 --- a/src/field/detail/digit.tsx +++ b/src/field/detail/digit.tsx @@ -24,8 +24,7 @@ class DigitView extends React.PureComponent { {value} - {Render.unit(field.options.unitLabel, field.options.showTag, field.options.unitWidth)} - {Render.description(field.options.description, field.options.showTag)} + {Render.unit(field.options.unitLabel, false, field.options.unitWidth)} ; } } diff --git a/src/field/detail/select.tsx b/src/field/detail/select.tsx index cf36b4ba9e3298da74893e94e074d4cc8d1f26ce..646c27608c5b2daff8ae05759289051eca79e8de 100644 --- a/src/field/detail/select.tsx +++ b/src/field/detail/select.tsx @@ -57,8 +57,7 @@ class Select extends React.PureComponent { {value} - {Render.unit(field.options.unitLabel, field.options.showTag, field.options.unitWidth)} - {Render.description(field.options.description, field.options.showTag)} + {Render.unit(field.options.unitLabel, false, field.options.unitWidth)} ; } } diff --git a/src/field/detail/switch.tsx b/src/field/detail/switch.tsx index 98d81697cc27fc186e185f36233025811b538393..6e8918c9bc1fa1b88d70a04b3c1dcc40e68c68f2 100644 --- a/src/field/detail/switch.tsx +++ b/src/field/detail/switch.tsx @@ -29,9 +29,8 @@ class Switch extends React.PureComponent { ? : ) - : Render.unit(field.options.unitLabel, field.options.showTag, field.options.unitWidth) + : Render.unit(field.options.unitLabel, false, field.options.unitWidth) } - {Render.description(field.options.description, field.options.showTag)} ; }; } diff --git a/src/field/detail/text.tsx b/src/field/detail/text.tsx index 674ff28035cc6d1dc213d08e191369f1975bd8ed..9bd2acc1616bd385dac55de4315e78e6d9ee2b8b 100644 --- a/src/field/detail/text.tsx +++ b/src/field/detail/text.tsx @@ -22,8 +22,7 @@ class TextView extends React.PureComponent { : field.options.render(value) } - {Render.unit(field.options.unitLabel, field.options.showTag, field.options.unitWidth)} - {Render.description(field.options.description, field.options.showTag)} + {Render.unit(field.options.unitLabel, false, field.options.unitWidth)} ; } } diff --git a/src/field/detail/tree_select.tsx b/src/field/detail/tree_select.tsx index 8b5abdd68427c20b82ab4e3a0268b0fb668765f0..f524f8727d1991782e382185c12333150c53bdf9 100644 --- a/src/field/detail/tree_select.tsx +++ b/src/field/detail/tree_select.tsx @@ -49,7 +49,6 @@ class TreeSelectView extends React.PureComponent { {value} - {Render.description(field.options.description, field.options.showTag)} ; } diff --git a/src/field/modify/bit_select.tsx b/src/field/modify/bit_select.tsx index 855f998ab95a3d5dd6053b0665c5580b9ec92c44..7666fddc9391e3889b454289bc2e396177edba73 100644 --- a/src/field/modify/bit_select.tsx +++ b/src/field/modify/bit_select.tsx @@ -39,26 +39,30 @@ class BitSelect extends React.PureComponent { {option.fieldLabel} - - {form.getFieldDecorator(this._bitFieldName(option), { - rules: [{ - required: field.options.required, - message: "请填写" + option.fieldLabel, - }], - initialValue: this._getDefaultValue(option), - })( - - {option.values.map((v, i) => ( - - {option.labels[i]} - - ))} - - )} - {Render.description(option.description, option.showTag === undefined ? true : option.showTag)} + +
{/* 第一层分隔表单控件和验证结果 */} +
{/* 第二层分隔控件,单位和描述 */} + {form.getFieldDecorator(this._bitFieldName(option), { + rules: [{ + required: field.options.required, + message: "请填写" + option.fieldLabel, + }], + initialValue: this._getDefaultValue(option), + })( + + {option.values.map((v, i) => ( + + {option.labels[i]} + + ))} + + )} +
+ {Render.description(option.description, option.showTag)} +
diff --git a/src/field/modify/date_time.tsx b/src/field/modify/date_time.tsx index 13eb42e5750517d5244be7191c37b8a4adb9e694..258b9eefcfc9e8ae8362df700cc63f8b49600aa1 100644 --- a/src/field/modify/date_time.tsx +++ b/src/field/modify/date_time.tsx @@ -26,31 +26,35 @@ class DateTime extends React.PureComponent { } return ( - {form.getFieldDecorator(Storage.Prefix + field.name, { - initialValue: initialValue, - rules: [{ - required: field.options.required, - message: "请填写" + label, - }] - })( - onlyTime ? ( - - ) : ( - - ) - )} - {Render.description(field.options.description, field.options.showTag === undefined ? true : field.options.showTag)} +
{/* 第一层分隔表单控件和验证结果 */} +
{/* 第二层分隔控件,单位和描述 */} + {form.getFieldDecorator(Storage.Prefix + field.name, { + initialValue: initialValue, + rules: [{ + required: field.options.required, + message: "请填写" + label, + }] + })( + onlyTime ? ( + + ) : ( + + ) + )} +
+ {Render.description(field.options.description, field.options.showTag)} +
); } diff --git a/src/field/modify/digit.tsx b/src/field/modify/digit.tsx index 5aa25d96e097d7b5d07d71abed7f1fabff8c0dea..7b894bd704fbd695e87fc430e4af78a1661bfea0 100644 --- a/src/field/modify/digit.tsx +++ b/src/field/modify/digit.tsx @@ -26,23 +26,27 @@ class Digit extends React.PureComponent { } return ( - {form.getFieldDecorator(Storage.Prefix + field.name, { - rules: [{ - required: field.options.required, - message: "请填写" + label, - }], - initialValue: initialValue, - })( - - )} - {Render.unit(field.options.unitLabel, field.options.showTag === undefined ? true : field.options.showTag, field.options.unitWidth)} - {Render.description(field.options.description, field.options.showTag === undefined ? true : field.options.showTag)} +
{/* 第一层分隔表单控件和验证结果 */} +
{/* 第二层分隔控件,单位和描述 */} + {form.getFieldDecorator(Storage.Prefix + field.name, { + rules: [{ + required: field.options.required, + message: "请填写" + label, + }], + initialValue: initialValue, + })( + + )} + {Render.unit(field.options.unitLabel, true, field.options.unitWidth)} +
+ {Render.description(field.options.description, field.options.showTag)} +
); } diff --git a/src/field/modify/select.tsx b/src/field/modify/select.tsx index 503b5216702020529146afe8659cc8e6aa5865e1..46e7e3bb06415073fd3224ad287002fa9e1e85a1 100644 --- a/src/field/modify/select.tsx +++ b/src/field/modify/select.tsx @@ -42,33 +42,37 @@ class SelectView extends React.PureComponent { const mul = field.options.multiple; return ( - {form.getFieldDecorator(field.name, { - initialValue: this.props.initialValue, - rules: [{ - required: field.options.required, - message: "请填写" + label, - type: mul ? "array" : field.options.valueType, - }], - })( - - )} - {Render.unit(field.options.unitLabel, field.options.showTag === undefined ? true : field.options.showTag, field.options.unitWidth)} - {Render.description(field.options.description, field.options.showTag === undefined ? true : field.options.showTag)} +
{/* 第一层分隔表单控件和验证结果 */} +
{/* 第二层分隔控件,单位和描述 */} + {form.getFieldDecorator(field.name, { + initialValue: this.props.initialValue, + rules: [{ + required: field.options.required, + message: "请填写" + label, + type: mul ? "array" : field.options.valueType, + }], + })( + + )} + {Render.unit(field.options.unitLabel, true, field.options.unitWidth)} +
+ {Render.description(field.options.description, field.options.showTag)} +
); } diff --git a/src/field/modify/switch.tsx b/src/field/modify/switch.tsx index 101397ee7ef771786e381c1497e61d8803d84206..c1f2ccfb06fab85469892d58a3ce07b6d3760f6e 100644 --- a/src/field/modify/switch.tsx +++ b/src/field/modify/switch.tsx @@ -15,36 +15,40 @@ class SwitchView extends React.PureComponent { const initialValue = this.props.initialValue || false; return ( - {form.getFieldDecorator(field.name, { - initialValue: initialValue, - valuePropName: "checked", - rules: [{ - required: field.options.required, - message: "请填写" + label, - }], - })(useRadio - ? - - {field.options.trueLabel} - - - {field.options.falseLabel} - - - : - )} - {useRadio ? null : Render.unit(field.options.unitLabel, field.options.showTag === undefined ? true : field.options.showTag, field.options.unitWidth)} - {Render.description(field.options.description, field.options.showTag === undefined ? true : field.options.showTag)} +
{/* 第一层分隔表单控件和验证结果 */} +
{/* 第二层分隔控件,单位和描述 */} + {form.getFieldDecorator(field.name, { + initialValue: initialValue, + valuePropName: "checked", + rules: [{ + required: field.options.required, + message: "请填写" + label, + }], + })(useRadio + ? + + {field.options.trueLabel} + + + {field.options.falseLabel} + + + : + )} + {useRadio ? null : Render.unit(field.options.unitLabel, true, field.options.unitWidth)} +
+ {Render.description(field.options.description, field.options.showTag)} +
); } diff --git a/src/field/modify/text.tsx b/src/field/modify/text.tsx index 866c040e02e193b07553f8f530e1f5eb6fc2944c..ff8f37b09eee97f174a03720f7a250860bc85774 100644 --- a/src/field/modify/text.tsx +++ b/src/field/modify/text.tsx @@ -14,21 +14,25 @@ class TextView extends React.PureComponent { const label = field.options.label || field.label; return ( - {form.getFieldDecorator(field.name, { - rules: [{ - required: field.options.required, - message: "请填写" + label, - max: field.options.maxLength > 0 ? field.options.maxLength : undefined, - }], - initialValue: this.props.initialValue || "", - })( - - )} - {Render.unit(field.options.unitLabel, field.options.showTag === undefined ? true : field.options.showTag, field.options.unitWidth)} - {Render.description(field.options.description, field.options.showTag === undefined ? true : field.options.showTag)} +
{/* 第一层分隔表单控件和验证结果 */} +
{/* 第二层分隔控件,单位和描述 */} + {form.getFieldDecorator(field.name, { + rules: [{ + required: field.options.required, + message: "请填写" + label, + max: field.options.maxLength > 0 ? field.options.maxLength : undefined, + }], + initialValue: this.props.initialValue || "", + })( + + )} + {Render.unit(field.options.unitLabel, true, field.options.unitWidth)} +
+ {Render.description(field.options.description, field.options.showTag)} +
); } diff --git a/src/field/modify/tree_select.tsx b/src/field/modify/tree_select.tsx index e50f4c28774b78b21dddfc41501f35b36556a6c9..1e9d87964c9528859f19659a46d6d9c959041fba 100644 --- a/src/field/modify/tree_select.tsx +++ b/src/field/modify/tree_select.tsx @@ -46,7 +46,7 @@ class TreeSelectView extends React.PureComponent { onChange={this._onChange} /> )} - {Render.description(field.options.description, field.options.showTag === undefined ? true : field.options.showTag)} + {Render.description(field.options.description, field.options.showTag)}
); } diff --git a/src/field/util/render.tsx b/src/field/util/render.tsx index 8fc359b6cd3dfd9167c408877fd68db4ba919ff0..7a82ad5d5c7627d575c58c76ddc91bb27287cbc9 100644 --- a/src/field/util/render.tsx +++ b/src/field/util/render.tsx @@ -16,8 +16,8 @@ export function unit(unit?: string, tag?: boolean, witdh?: number) { export function description(desc?: string, tag?: boolean) { return desc - ? (tag === true + ? (tag === undefined || tag === true ? {desc} - : {unit} + : {desc} ) : null; } diff --git a/src/page/create.tsx b/src/page/create.tsx index b800a563e93a9e7274a5b83cb2fe584952e3392d..e3abad65835805a7d9709c4aba91a21d8226ba7e 100644 --- a/src/page/create.tsx +++ b/src/page/create.tsx @@ -16,6 +16,10 @@ interface Props { * 字段列表。 */ fields: Field.Base.CreateConfig[]; + /** + * 提交按钮是否显示。 + */ + submitShow: boolean; /** * 提交按钮的自定义标签。 */ @@ -57,6 +61,7 @@ interface CreateFormProps extends FormComponentProps, Props { } class CreateComponent extends React.PureComponent { static defaultProps = { + submitShow: true, submitLabel: "提交", formProps: {}, submitFormItemProps: {}, @@ -84,6 +89,7 @@ class CreateComponent extends React.PureComponent { sm: { span: 20 }, }, }; + refForm: Form | null = null; render() { @@ -151,14 +157,17 @@ class CreateComponent extends React.PureComponent { {...this.defaultSubmitFormItemProps} {...this.props.submitFormItemProps} > - + {this.props.submitShow + ? + : null + } {this.props.action && this.props.action.map((node) => { return node; })} diff --git a/src/page/detail.tsx b/src/page/detail.tsx index d2158aea641d7239bf10450b12459f4bb101203f..7120c04eb8c2065eaafd103c1332401970ceadd6 100644 --- a/src/page/detail.tsx +++ b/src/page/detail.tsx @@ -3,7 +3,7 @@ */ import * as React from 'react'; -import { Tabs, Descriptions } from 'antd'; +import { Tabs, Descriptions, Tooltip, Icon } from 'antd'; import { DescriptionsProps } from 'antd/lib/descriptions'; import * as Field from '../config'; import * as DetailFields from '../field/detail'; @@ -115,11 +115,7 @@ export default class extends React.PureComponent { items.push( - {item.fieldLabel} - - )} + label={this._renderLabel(item.fieldLabel, labelWidth, item.description)} span={field.options.span} >
@@ -137,11 +133,7 @@ export default class extends React.PureComponent { return ( - {label} -
- )} + label={this._renderLabel(label, labelWidth, field.options.description)} span={field.options.span} >
@@ -152,6 +144,30 @@ export default class extends React.PureComponent { } }; + _renderLabel = (label: string, width: number, desc?: string) => { + return desc === undefined || desc === "" + ? ( +
+ {label} +
+ ) : ( + +
+ {label} + +
+
+ ); + }; + // 渲染按钮 _renderAction = () => { const labelWidth = this.props.labelWidth || 118; diff --git a/src/page/list.tsx b/src/page/list.tsx index 7bfff6c65fcfc79ef4453d2e6ac42fcc410874f7..7f26a4d915fbf6dfe4ef1108f9a9571f8ee2657d 100644 --- a/src/page/list.tsx +++ b/src/page/list.tsx @@ -2,9 +2,10 @@ * 通用的列表页。 */ import * as React from 'react'; -import { Table, Divider, Modal, Alert, message } from 'antd'; +import { Table, Modal, Alert, message } from 'antd'; import { PaginationConfig } from 'antd/lib/pagination'; import { TableEventListeners, TableProps, ColumnProps } from 'antd/lib/table'; +import ActionColumn from './list_col_action'; import * as Field from '../config'; import * as DetailFields from '../field/detail'; @@ -20,10 +21,18 @@ export interface FetchDataResult { } export interface Action { + /** + * 图标类型。 + */ + icon?: string; /** * 文字内容。 */ - label?: React.ReactNode | ((data: any, mainKey: string) => React.ReactNode); + label?: string; + /** + * 提示内容。 + */ + tooltip?: string; /** * 是否启用。 */ @@ -37,24 +46,24 @@ export interface Action { */ modalClick?: (data: any, mainKey: string) => Promise; /** - * 弹框模式的标题栏(优先modalField)。 - */ + * 弹框模式的标题栏(优先modalField)。 + */ modalTitle?: string; /** - * 弹框模式标题栏的取值字段(如果modalField和modalTitle都未设置,则不是弹框)。 - */ + * 弹框模式标题栏的取值字段(如果modalField和modalTitle都未设置,则不是弹框)。 + */ modalField?: string; /** - * 弹框模式的内容。 - */ + * 弹框模式的内容。 + */ modalContent?: string; /** - * 弹框模式的操作成功提示。 - */ + * 弹框模式的操作成功提示。 + */ modalSuccessInfo?: string; /** - * 弹框模式的操作错误提示。 - */ + * 弹框模式的操作错误提示。 + */ modalErrorInfo?: string; } @@ -94,7 +103,7 @@ interface Props { /** * 右侧其他操作。 */ - otherActions: Action[]; + otherActions?: Action[]; /** * 操作列的附加属性。 */ @@ -142,7 +151,6 @@ interface State { export default class ListPage extends React.PureComponent { static defaultProps = { - otherActions: [], actionColumnProps: {}, tableProps: {}, autoLoad: true, @@ -202,7 +210,7 @@ export default class ListPage extends React.PureComponent { }; }; - // 表格切换页的回调 + // 列表翻页,过滤和排序的操作 _onTableChange = (pagination: PaginationConfig, filters: any, sorter: any) => { const pageNumber = pagination.current as number; this._fetchData(pageNumber, filters, sorter); @@ -281,27 +289,53 @@ export default class ListPage extends React.PureComponent { return columns; }; + // 渲染表格"操作"列 + _renderColumnAction = (text: string, record: { [key: string]: any }) => { + return ( + + ); + }; + // 生成操作项列表 _actions = () => { const actions: Action[] = []; if (this.props.editAction) { const action: Action = { ...this.props.editAction, + icon: this.props.editAction.icon || "edit", label: this.props.editAction.label || "编辑", }; actions.push(action); + if (this.props.otherActions || this.props.deleteAction) { + // 有其他操作或删除操作时增加隔断 + actions.push({ label: "devide1" }); + } + } + if (this.props.otherActions && this.props.otherActions.length > 0) { + this.props.otherActions.forEach((act) => { + const action: Action = { + icon: act.icon || "right", + label: act.label, + tooltip: act.tooltip, + enable: act.enable, + onClick: this._onModalClick.bind(this, act), + }; + actions.push(action); + }); + if (this.props.deleteAction) { + // 有删除操作时增加隔断 + actions.push({ label: "devide2" }); + } } - this.props.otherActions.forEach((act) => { - const action: Action = { - label: act.label, - enable: act.enable, - onClick: this._onModalClick.bind(this, act), - }; - actions.push(action); - }); if (this.props.deleteAction) { const action: Action = { + icon: this.props.deleteAction.icon || "delete", label: this.props.deleteAction.label || "删除", + tooltip: this.props.deleteAction.tooltip, enable: this.props.deleteAction.enable, onClick: this._onDeleteClick, }; @@ -310,48 +344,6 @@ export default class ListPage extends React.PureComponent { return actions; }; - // 渲染表格"操作"列 - _renderColumnAction = (text: string, record: { [key: string]: any }) => { - const actions = this._actions(); - const views: React.ReactNode[] = []; - actions.forEach((item, index) => { - const enabled = item.enable ? item.enable(record, this.props.mainKey) : true; - if (!enabled) { - return; - } - const label = this._getActionLabel(item, "未知", record, this.props.mainKey); - views.push( - ) => { - item.onClick && item.onClick(record, this.props.mainKey); - e.stopPropagation(); - }} - > - {label} - - ); - views.push(); - }); - return ( - - {views.slice(0, views.length - 1)} - - ); - }; - - // 获取操作标签 - _getActionLabel = (action: Action, defaultValue: string, data: any, mainKey: string) => { - const label = action.label; - if (typeof label === "function") { - return label && label(data, mainKey); - } else if (label) { - return label; - } else { - return defaultValue; - } - }; - // 其他操作的弹框模式兼容(操作后刷新数据并保留在当前页) _onModalClick = (act: Action, data: any, mainKey: string) => { if (act.modalClick) { @@ -432,6 +424,7 @@ export default class ListPage extends React.PureComponent { } }; + // 执行操作 _onAction = (action: (data: any, mainKey: string) => Promise, data: any, mainKey: string, pn: number, success: string, error: string) => { // 先执行操作再重新加载列表 action(data, mainKey).then(() => { diff --git a/src/page/list_col_action.tsx b/src/page/list_col_action.tsx new file mode 100644 index 0000000000000000000000000000000000000000..7b6be3b1463744d954863d16ce7a1b58c3a08f1c --- /dev/null +++ b/src/page/list_col_action.tsx @@ -0,0 +1,106 @@ +/** + * 通用的列表。 + */ +import * as React from 'react'; +import { Dropdown, Menu, Icon, Tooltip } from 'antd'; +import { ClickParam } from 'antd/lib/menu'; +import { Action } from './list'; + +interface Props { + /** + * 字段列表。 + */ + record: { [key: string]: any } + /** + * 数据主键名称。 + */ + mainKey: string; + /** + * 操作项。 + */ + actions: Action[]; +} + +interface State { + visible: boolean; +} + +export default class extends React.PureComponent { + state: State = { visible: false }; + + render() { + const actions = this.props.actions.filter((a) => a.enable ? a.enable(this.props.record, this.props.mainKey) : true); + if (actions.length === 0 || actions.filter((a) => a.label === undefined || a.label.indexOf("devide") < 0).length === 0) { + // 没有操作项或没有除devide之外的操作项,则返回空 + return null; + } + const menus: React.ReactNode[] = []; + actions.forEach((item, index) => { + const label = item.label || "未知"; + if (label.indexOf("devide1") >= 0) { + // 当devide1为第二个元素时,也即有编辑按钮,则显示分隔符;否则忽略 + if (index === 1) { + menus.push(); + } + } else if (label.indexOf("devide2") >= 0) { + // 当devide2为倒数第二个元素时,也即有删除2按钮,则显示分隔符;否则忽略 + if (index === actions.length - 2) { + menus.push(); + } + } else { + // 显示非分隔符的操作项 + menus.push( + { + item.onClick && item.onClick(this.props.record, this.props.mainKey); + }} + className="xc-page-list-op-item" + > + + {item.tooltip + ? + {label} + + + : {label} + } + + ); + } + }); + return ( + {menus}} + trigger={['click']} + placement={"bottomRight"} + visible={this.state.visible} + onVisibleChange={this.onDropdownVisibleChange} + > + ) => { + e.stopPropagation(); + }} + /> + + ); + }; + + onMenuClick = (param: ClickParam) => { + param.domEvent.stopPropagation(); + this.setState({ visible: false }); + }; + + onDropdownVisibleChange = (visible: boolean) => { + this.setState({ visible: visible }); + }; +}