From 8c6c567241a5f356d1d819090f56741966c96b49 Mon Sep 17 00:00:00 2001 From: wangailin Date: Thu, 4 Nov 2021 15:29:01 +0800 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20=E5=88=9D=E5=A7=8B=E5=8C=96head?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/steps/header/index.tsx | 152 +++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 src/steps/header/index.tsx diff --git a/src/steps/header/index.tsx b/src/steps/header/index.tsx new file mode 100644 index 0000000..f179db0 --- /dev/null +++ b/src/steps/header/index.tsx @@ -0,0 +1,152 @@ +import React from 'react' +import QueryString from 'query-string' +import { FieldConfigs } from '../../components/formFields' +import TextField from '../../components/formFields/text' +import Step, { StepConfig } from '../common' +import { getValue } from '../../util/value' +import { set } from 'lodash' +import { ParamConfig } from '../../interface' + +/** + * header页头配置文件格式定义 + * - breadcrumb: 面包屑内容定义 + * - title: 主标题 + * - subTitle: 副标题 + * - back: 返回按钮 + */ +export interface HeaderConfig extends StepConfig { + type: 'header' + fields: FieldConfigs[], + breadcrumb: { + enable: boolean + separator: string + items: breadcrumbConfig[] + }, + title?: Title, + subtitle?: Title, + back: { + enable: boolean + } + default?: { + type: 'static' | 'data' | 'query' | 'hash' | 'step' + value?: any + field?: string + step?: string | number + } +} + +/** + * 面包屑内容 + */ +export interface breadcrumbConfig { + label: string + type: 'normal' | 'bold' + action: TableCCMSOperationConfig +} + +/** + * 标题内容 + */ +export interface Title { + statement: string + params: { field: string, data: ParamConfig }[] +} + +export interface TableCCMSOperationConfig { + type: 'ccms' + page: any + target: 'current' | 'page' | 'open' | 'handle' + targetURL: string + data: { [key: string]: ParamConfig } + callback?: boolean +} + +export default class HeaderStep extends Step { + FieldType: { [type: string]: any } = { + text: TextField + } + + stepPush = async () => { + // async componentDidMount() { + const { + data, + config: { + fields, + default: { + type: defaultType, + value: defaultValue, + field: defaultField, + step: defaultStep + } = {}, + default: defaultConfig + }, + step, + onSubmit + } = this.props + + let result: { [key: string]: any } = {} + + let formDefault: any + + if (defaultConfig) { + switch (defaultType) { + case 'static': + if (defaultValue) { + formDefault = defaultValue + } + break + case 'data': + if (data && data[step]) { + if (defaultField) { + formDefault = getValue(data[step], defaultField) + } else { + formDefault = data[step] + } + } + break + case 'query': + if (window.location.search) { + const query = QueryString.parse(window.location.search) + if (defaultField) { + formDefault = getValue(query, defaultField) + } else { + formDefault = query + } + } + break + case 'hash': + if (window.location.hash) { + try { + const hash = JSON.parse(window.location.hash.substr(1)) + if (defaultField) { + formDefault = getValue(hash, defaultField) + } else { + formDefault = hash + } + } catch (e) { + } + } + break + case 'step': + formDefault = defaultStep && getValue(data[defaultStep] || {}, defaultField) + break + } + for (const formFieldIndex in fields) { + const formFieldConfig = fields[formFieldIndex] + const value = getValue(formDefault, formFieldConfig.field) + if (formFieldConfig.field === '') { + result = value + } else { + set(result, formFieldConfig.field, value) + } + } + } + onSubmit(result) + } + + render () { + return ( + + ) + } +} -- Gitee From a85982ab2ef943a80ca8330568b1c1b896b20b27 Mon Sep 17 00:00:00 2001 From: wangailin Date: Thu, 4 Nov 2021 21:27:36 +0800 Subject: [PATCH 2/7] =?UTF-8?q?feat:=20=E9=A1=B5=E5=A4=B4=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/steps/header/index.tsx | 228 ++++++++++++++++++++++--------------- 1 file changed, 137 insertions(+), 91 deletions(-) diff --git a/src/steps/header/index.tsx b/src/steps/header/index.tsx index f179db0..30d4e28 100644 --- a/src/steps/header/index.tsx +++ b/src/steps/header/index.tsx @@ -1,10 +1,6 @@ -import React from 'react' -import QueryString from 'query-string' +import React, { ReactNode } from 'react' import { FieldConfigs } from '../../components/formFields' -import TextField from '../../components/formFields/text' import Step, { StepConfig } from '../common' -import { getValue } from '../../util/value' -import { set } from 'lodash' import { ParamConfig } from '../../interface' /** @@ -13,6 +9,9 @@ import { ParamConfig } from '../../interface' * - title: 主标题 * - subTitle: 副标题 * - back: 返回按钮 + * -- enable: 启用 + * - mainContent: 主内容 + * - extraContent: 扩展内容 */ export interface HeaderConfig extends StepConfig { type: 'header' @@ -23,16 +22,12 @@ export interface HeaderConfig extends StepConfig { items: breadcrumbConfig[] }, title?: Title, - subtitle?: Title, + subtitle?: Title back: { enable: boolean - } - default?: { - type: 'static' | 'data' | 'query' | 'hash' | 'step' - value?: any - field?: string - step?: string | number - } + }, + mainContent: MainContent + extraContent: extraContent } /** @@ -52,6 +47,109 @@ export interface Title { params: { field: string, data: ParamConfig }[] } +/** + * 主内容 + * - enable: 启用 + * - type: 类型 + * ** plain: 纯文本 + * ** markdown: Markdown格式文本 + * ** html: HTML格式文本 + * ** detail: 详情内容 + * ** statistic: 统计内容 + * - content: 文本内容 仅当type为plain、markdown、html时生效 + * - params: 文本内容参数 仅当type为plain、markdown、html时生效 + * - detailContent: 文本内容参数 仅当type为plain、markdown、html时生效 + */ +export interface MainContent { + enable: boolean + type: 'plain' | 'markdown' | 'html' | 'detail' | 'statistic' + content: string + params: { field: string, data: ParamConfig }[] + detailContent: any + statistics: statistics[] + extraContent: extraContent +} + +/** + * 统计内容 + * - label: 统计的标题 + * - type: 统计的类型 + * - value: 统计的值 + * - options: 统计的枚举选项 + */ +export interface statistics { + label: string + type: 'value' | 'enum' + value: ParamConfig + options: any + // ManualOptionsConfig | InterfaceOptionsConfig +} + +/** + * 扩展内容 + * - enable: 启用 + * - type: 类型 + * - image: 图片 + * -- maxWidth: 图片最大宽度 + * -- maxHeight: 图片最大高度 + * -- src: 图片地址 + */ +export interface extraContent { + enable: boolean + type: 'statistic' | 'image' + statistics?: statistics[] + image?: { + maxWidth: string + maxHeight: string + src: string + } +} + +/** + * 面包屑内容config + * - items: 面包屑内容 + * -- label: 文案 + * -- type: 展示形式 + * -- onClick: 点击事件 + * - separator: 分割符 + */ +export interface IBreadcurmbConfig { + items: Array<{ + label: string + type: 'normal' | 'bold' + onClick: () => void + }> + separator: string +} + +/** + * 绘制统计内容config + * - label: 统计标题 + * - value: 统计数值 + */ +export interface IStatisticConfig { + label: string + type: string | number +} + +/** + * 头部组件config + * - breadcrumb:面包屑内容 + * - title: 主标题 + * - subTitle: 副标题 + * - onBack: 返回按钮点击事件 + * - mainContent: 主内容 + * - extraContent: 扩展内容 + */ +export interface IHeaderConfig { + breadcrumb: ReactNode | undefined + title: string | undefined + subTitle: string | undefined + onBack: () => void | undefined + mainContent: ReactNode + extraContent: ReactNode +} + export interface TableCCMSOperationConfig { type: 'ccms' page: any @@ -62,91 +160,39 @@ export interface TableCCMSOperationConfig { } export default class HeaderStep extends Step { - FieldType: { [type: string]: any } = { - text: TextField + /** + * 用于展示面包屑 + * @param props + * @returns + */ + renderBreadcurmbComponent = (props: IBreadcurmbConfig) => { + return + 您当前使用的UI版本没有实现HeaderStep组件的renderBreadcurmbComponent方法。 + } - stepPush = async () => { - // async componentDidMount() { - const { - data, - config: { - fields, - default: { - type: defaultType, - value: defaultValue, - field: defaultField, - step: defaultStep - } = {}, - default: defaultConfig - }, - step, - onSubmit - } = this.props - - let result: { [key: string]: any } = {} - - let formDefault: any + /** + * 用于展示统计内容 + * @param props + * @returns + */ + renderStatisticComponent = (props: IStatisticConfig) => { + return + 您当前使用的UI版本没有实现HeaderStep组件的renderStatisticComponent方法。 + + } - if (defaultConfig) { - switch (defaultType) { - case 'static': - if (defaultValue) { - formDefault = defaultValue - } - break - case 'data': - if (data && data[step]) { - if (defaultField) { - formDefault = getValue(data[step], defaultField) - } else { - formDefault = data[step] - } - } - break - case 'query': - if (window.location.search) { - const query = QueryString.parse(window.location.search) - if (defaultField) { - formDefault = getValue(query, defaultField) - } else { - formDefault = query - } - } - break - case 'hash': - if (window.location.hash) { - try { - const hash = JSON.parse(window.location.hash.substr(1)) - if (defaultField) { - formDefault = getValue(hash, defaultField) - } else { - formDefault = hash - } - } catch (e) { - } - } - break - case 'step': - formDefault = defaultStep && getValue(data[defaultStep] || {}, defaultField) - break - } - for (const formFieldIndex in fields) { - const formFieldConfig = fields[formFieldIndex] - const value = getValue(formDefault, formFieldConfig.field) - if (formFieldConfig.field === '') { - result = value - } else { - set(result, formFieldConfig.field, value) - } - } - } - onSubmit(result) + renderComponent = (props: IHeaderConfig) => { + return + 您当前使用的UI版本没有实现HeaderStep组件。 + } render () { return ( - + + {/* {this.renderComponent({})} */} + ) } } -- Gitee From f323bada73ed1a6f1585e797f26f01453d623b4a Mon Sep 17 00:00:00 2001 From: niuxiaoguang Date: Fri, 5 Nov 2021 18:12:39 +0800 Subject: [PATCH 3/7] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E9=A1=B5?= =?UTF-8?q?=E5=A4=B4=E6=AD=A5=E9=AA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.tsx | 2 + src/steps/header/index.tsx | 280 ++++++++++++++++++++++++------------- src/steps/index.tsx | 6 +- src/util/statement.ts | 36 +++++ 4 files changed, 228 insertions(+), 96 deletions(-) create mode 100644 src/util/statement.ts diff --git a/src/index.tsx b/src/index.tsx index 3e2e2a1..7a3e926 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -39,4 +39,6 @@ export { default as ImageColumn } from './components/tableColumns/image' export { default as FetchStep } from './steps/fetch' +export { default as HeaderStep } from './steps/header' + export { default as InterfaceHelper } from "./util/interface" \ No newline at end of file diff --git a/src/steps/header/index.tsx b/src/steps/header/index.tsx index 30d4e28..8983f8b 100644 --- a/src/steps/header/index.tsx +++ b/src/steps/header/index.tsx @@ -1,7 +1,11 @@ import React, { ReactNode } from 'react' -import { FieldConfigs } from '../../components/formFields' import Step, { StepConfig } from '../common' import { ParamConfig } from '../../interface' +import StatementHelper, { StatementConfig } from '../../util/statement' +import { InterfaceOptionsConfig, ManualOptionsConfig } from '../../components/formFields/select/common' +import { TableCCMSOperationConfig } from '../table' +import marked from 'marked' +import ParamHelper from '../../util/param' /** * header页头配置文件格式定义 @@ -15,93 +19,76 @@ import { ParamConfig } from '../../interface' */ export interface HeaderConfig extends StepConfig { type: 'header' - fields: FieldConfigs[], - breadcrumb: { - enable: boolean - separator: string - items: breadcrumbConfig[] + breadcrumb?: { + enable?: boolean + separator?: string + items?: breadcrumbConfig[] }, - title?: Title, - subtitle?: Title - back: { - enable: boolean + title?: StatementConfig, + subTitle?: StatementConfig + back?: { + enable?: boolean }, - mainContent: MainContent - extraContent: extraContent + mainContent?: plainContentConfig | markdownContentConfig | htmlContentConfig | detailContentConfig | statisticContentConfig + extraContent?: statisticContentConfig | imageContentConfig } /** * 面包屑内容 */ export interface breadcrumbConfig { - label: string - type: 'normal' | 'bold' - action: TableCCMSOperationConfig + label?: string + type?: 'normal' | 'bold' + action?: TableCCMSOperationConfig } -/** - * 标题内容 - */ -export interface Title { - statement: string - params: { field: string, data: ParamConfig }[] +interface basicContentConfig { + enable?: boolean } -/** - * 主内容 - * - enable: 启用 - * - type: 类型 - * ** plain: 纯文本 - * ** markdown: Markdown格式文本 - * ** html: HTML格式文本 - * ** detail: 详情内容 - * ** statistic: 统计内容 - * - content: 文本内容 仅当type为plain、markdown、html时生效 - * - params: 文本内容参数 仅当type为plain、markdown、html时生效 - * - detailContent: 文本内容参数 仅当type为plain、markdown、html时生效 - */ -export interface MainContent { - enable: boolean - type: 'plain' | 'markdown' | 'html' | 'detail' | 'statistic' - content: string - params: { field: string, data: ParamConfig }[] - detailContent: any - statistics: statistics[] - extraContent: extraContent +export interface plainContentConfig extends basicContentConfig { + type: 'plain' + content?: string + params?: { field: string, data: ParamConfig }[] +} +export interface markdownContentConfig extends basicContentConfig { + type: 'markdown' + content?: string + params?: { field: string, data: ParamConfig }[] +} +export interface htmlContentConfig extends basicContentConfig { + type: 'html' + content?: string + params?: { field: string, data: ParamConfig }[] +} +export interface detailContentConfig extends basicContentConfig { + type: 'detail' +} +export interface statisticContentConfig extends basicContentConfig { + type: 'statistic' + statistics?: (valueStatisticConfig | enumerationStatisticConfig)[] } -/** - * 统计内容 - * - label: 统计的标题 - * - type: 统计的类型 - * - value: 统计的值 - * - options: 统计的枚举选项 - */ -export interface statistics { - label: string - type: 'value' | 'enum' - value: ParamConfig - options: any - // ManualOptionsConfig | InterfaceOptionsConfig + +interface basicStatisticConfig { + label?: string + value?: ParamConfig } -/** - * 扩展内容 - * - enable: 启用 - * - type: 类型 - * - image: 图片 - * -- maxWidth: 图片最大宽度 - * -- maxHeight: 图片最大高度 - * -- src: 图片地址 - */ -export interface extraContent { - enable: boolean - type: 'statistic' | 'image' - statistics?: statistics[] +export interface valueStatisticConfig extends basicStatisticConfig { + type: 'value' +} + +export interface enumerationStatisticConfig extends basicStatisticConfig { + type: 'enumeration' + options?: ManualOptionsConfig | InterfaceOptionsConfig +} +export interface imageContentConfig extends basicContentConfig { + type: 'image' image?: { - maxWidth: string - maxHeight: string - src: string + maxWidth?: string + maxHeight?: string + src?: string } } @@ -113,7 +100,7 @@ export interface extraContent { * -- onClick: 点击事件 * - separator: 分割符 */ -export interface IBreadcurmbConfig { +export interface IBreadcurmbProps { items: Array<{ label: string type: 'normal' | 'bold' @@ -127,9 +114,9 @@ export interface IBreadcurmbConfig { * - label: 统计标题 * - value: 统计数值 */ -export interface IStatisticConfig { +export interface IStatisticProps { label: string - type: string | number + value: string | number } /** @@ -141,31 +128,34 @@ export interface IStatisticConfig { * - mainContent: 主内容 * - extraContent: 扩展内容 */ -export interface IHeaderConfig { - breadcrumb: ReactNode | undefined - title: string | undefined - subTitle: string | undefined - onBack: () => void | undefined - mainContent: ReactNode - extraContent: ReactNode -} - -export interface TableCCMSOperationConfig { - type: 'ccms' - page: any - target: 'current' | 'page' | 'open' | 'handle' - targetURL: string - data: { [key: string]: ParamConfig } - callback?: boolean +export interface IHeaderProps { + breadcrumb?: ReactNode + title?: string + subTitle?: string + onBack?: () => void + mainContent?: ReactNode + extraContent?: ReactNode } export default class HeaderStep extends Step { + stepPush = async () => { + // 表单初始化结束,展示表单界面。 + if (this.props.onMount) { + this.props.onMount() + } + setTimeout(() => { + if (this.props.onSubmit) { + this.props.onSubmit({}, false) + } + }, 100) + } + /** * 用于展示面包屑 * @param props * @returns */ - renderBreadcurmbComponent = (props: IBreadcurmbConfig) => { + renderBreadcurmbComponent = (props: IBreadcurmbProps) => { return 您当前使用的UI版本没有实现HeaderStep组件的renderBreadcurmbComponent方法。 @@ -176,22 +166,124 @@ export default class HeaderStep extends Step { * @param props * @returns */ - renderStatisticComponent = (props: IStatisticConfig) => { + renderStatisticComponent = (props: IStatisticProps) => { return 您当前使用的UI版本没有实现HeaderStep组件的renderStatisticComponent方法。 } - renderComponent = (props: IHeaderConfig) => { + renderComponent = (props: IHeaderProps) => { return 您当前使用的UI版本没有实现HeaderStep组件。 } + handlePlainContent = (config: plainContentConfig) => { + return StatementHelper({ statement: config.content || '', params: config.params || [] }, { data: this.props.data, step: this.props.step }) + } + + handleMarkdownContent = (config: markdownContentConfig) => { + const content = StatementHelper({ statement: config.content || '', params: config.params || [] }, { data: this.props.data, step: this.props.step }) + return
+ } + + handleHTMLContent = (config: htmlContentConfig) => { + const content = StatementHelper({ statement: config.content || '', params: config.params || [] }, { data: this.props.data, step: this.props.step }) + return
+ } + + handleStatisticContent = (config: statisticContentConfig) => { + return (config.statistics || []).map((statistic) => { + const value = statistic.value ? ParamHelper(statistic.value, { data: this.props.data, step: this.props.step }) : undefined + switch (statistic.type) { + case 'value': + return this.renderStatisticComponent({ + label: statistic.label || '', + value + }) + case 'enumeration': + // TODO + return null + default: + return null + } + }) + } + + handleImageContent = (config: imageContentConfig) => { + if (config.image && config.image.src) { + return + } else { + return null + } + } + render () { + const props: IHeaderProps = {} + + if (this.props.config.breadcrumb && this.props.config.breadcrumb.enable) { + const breadcrumbConfig = this.props.config.breadcrumb + props.breadcrumb = this.renderBreadcurmbComponent({ + items: (breadcrumbConfig.items || []).map((breadcrumbItem) => ({ + label: breadcrumbItem.label || '', + type: breadcrumbItem.type || 'normal', + onClick: () => {} // TODO + })), + separator: breadcrumbConfig.separator || '>' + }) + } + + if (this.props.config.title) { + props.title = StatementHelper(this.props.config.title, { data: this.props.data, step: this.props.step }) + } + + if (this.props.config.subTitle) { + props.subTitle = StatementHelper(this.props.config.subTitle, { data: this.props.data, step: this.props.step }) + } + + if (this.props.config.back && this.props.config.back.enable) { + props.onBack = () => { this.props.onUnmount() } + } + + if (this.props.config.mainContent && this.props.config.mainContent.enable) { + const mainContent = this.props.config.mainContent + switch (mainContent.type) { + case 'plain': + props.mainContent = this.handlePlainContent(mainContent) + break; + case 'markdown': + props.mainContent = this.handleMarkdownContent(mainContent) + break; + case 'html': + props.mainContent = this.handleHTMLContent(mainContent) + break; + case 'detail': + // TODO + break; + case 'statistic': + props.mainContent = this.handleStatisticContent(mainContent) + default: + break; + } + } + + if (this.props.config.extraContent && this.props.config.extraContent.enable) { + const extraContent = this.props.config.extraContent + switch (extraContent.type) { + case 'statistic': + props.extraContent = this.handleStatisticContent(extraContent) + break; + case 'image': + props.extraContent = this.handleImageContent(extraContent) + break; + default: + break; + } + } + return ( - {/* {this.renderComponent({})} */} + {this.renderComponent(props)} ) } diff --git a/src/steps/index.tsx b/src/steps/index.tsx index 63fc5ea..7da3e3e 100644 --- a/src/steps/index.tsx +++ b/src/steps/index.tsx @@ -1,15 +1,17 @@ import FetchStep, { FetchConfig } from './fetch' import FilterStep, { FilterConfig } from './filter' import FormStep, { FormConfig } from './form' +import HeaderStep, { HeaderConfig } from './header' import SkipStep, { SkipConfig } from './skip' import TableStep, { TableConfig } from './table' -export type StepConfigs = FetchConfig | FormConfig | SkipConfig | TableConfig | FilterConfig +export type StepConfigs = FetchConfig | FormConfig | SkipConfig | TableConfig | FilterConfig | HeaderConfig export default { fetch: FetchStep, form: FormStep, skip: SkipStep, table: TableStep, - filter: FilterStep + filter: FilterStep, + header: HeaderStep } diff --git a/src/util/statement.ts b/src/util/statement.ts new file mode 100644 index 0000000..81ea1e5 --- /dev/null +++ b/src/util/statement.ts @@ -0,0 +1,36 @@ +import { set, cloneDeep, template } from "lodash" +import { ParamConfig } from "../interface"; +import ParamHelper from "./param"; + +export interface StatementConfig { + statement: string + params: { field: string, data: ParamConfig }[] +} + +export default function StatementHelper(config: StatementConfig | undefined, datas: { record?: object, data: object[], step: number }): string { + if (config === undefined || config.statement === undefined || config.statement === '') { + return '' + } else { + const statementTemplate = template(config.statement) + let statementParams = {} + if (config.params) { + config.params.forEach((param) => { + if (param.field !== undefined && param.data !== undefined) { + if (param.field === '') { + statementParams = ParamHelper(param.data, cloneDeep(datas)) + } else { + set(statementParams, param.field, ParamHelper(param.data, cloneDeep(datas))) + } + } + }) + } + + try { + const statement = statementTemplate(statementParams) + return statement + } catch (e) { + console.error('模板字符串处理失败。', config.statement) + return '' + } + } +} \ No newline at end of file -- Gitee From da8e9ce5ac2c1571fad3e955cb5bc5d417fd90de Mon Sep 17 00:00:00 2001 From: niuxiaoguang Date: Mon, 8 Nov 2021 18:34:40 +0800 Subject: [PATCH 4/7] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E9=A1=B5?= =?UTF-8?q?=E5=A4=B4=E6=AD=A5=E9=AA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/steps/header/index.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/steps/header/index.tsx b/src/steps/header/index.tsx index 8983f8b..a2dcac4 100644 --- a/src/steps/header/index.tsx +++ b/src/steps/header/index.tsx @@ -143,11 +143,10 @@ export default class HeaderStep extends Step { if (this.props.onMount) { this.props.onMount() } - setTimeout(() => { - if (this.props.onSubmit) { - this.props.onSubmit({}, false) - } - }, 100) + console.log('this.props.onSubmit') + if (this.props.onSubmit) { + this.props.onSubmit({}) + } } /** -- Gitee From 537e7804f5bbbf182589712a1482b11f0972f439 Mon Sep 17 00:00:00 2001 From: niuxiaoguang Date: Wed, 17 Nov 2021 17:32:25 +0800 Subject: [PATCH 5/7] =?UTF-8?q?feat:=20=E6=8A=BD=E7=A6=BB=E6=9E=9A?= =?UTF-8?q?=E4=B8=BE=E7=B1=BB=E5=9E=8B=E5=85=AC=E5=85=B1=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/steps/header/index.tsx | 56 +++++++++++++++++++-------- src/util/enumeration.ts | 77 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 15 deletions(-) create mode 100644 src/util/enumeration.ts diff --git a/src/steps/header/index.tsx b/src/steps/header/index.tsx index a2dcac4..26b1ea2 100644 --- a/src/steps/header/index.tsx +++ b/src/steps/header/index.tsx @@ -6,6 +6,8 @@ import { InterfaceOptionsConfig, ManualOptionsConfig } from '../../components/fo import { TableCCMSOperationConfig } from '../table' import marked from 'marked' import ParamHelper from '../../util/param' +import EnumerationHelper, { EnumerationOptionsConfig } from '../../util/enumeration' +import { InterfaceHelper } from '../..' /** * header页头配置文件格式定义 @@ -81,7 +83,7 @@ export interface valueStatisticConfig extends basicStatisticConfig { export interface enumerationStatisticConfig extends basicStatisticConfig { type: 'enumeration' - options?: ManualOptionsConfig | InterfaceOptionsConfig + options?: EnumerationOptionsConfig } export interface imageContentConfig extends basicContentConfig { type: 'image' @@ -138,6 +140,8 @@ export interface IHeaderProps { } export default class HeaderStep extends Step { + interfaceHelper = new InterfaceHelper() + stepPush = async () => { // 表单初始化结束,展示表单界面。 if (this.props.onMount) { @@ -177,22 +181,22 @@ export default class HeaderStep extends Step { } - handlePlainContent = (config: plainContentConfig) => { + handlePlainContent = (config: plainContentConfig, _position: string) => { return StatementHelper({ statement: config.content || '', params: config.params || [] }, { data: this.props.data, step: this.props.step }) } - handleMarkdownContent = (config: markdownContentConfig) => { + handleMarkdownContent = (config: markdownContentConfig, _position: string) => { const content = StatementHelper({ statement: config.content || '', params: config.params || [] }, { data: this.props.data, step: this.props.step }) return
} - handleHTMLContent = (config: htmlContentConfig) => { + handleHTMLContent = (config: htmlContentConfig, _position: string) => { const content = StatementHelper({ statement: config.content || '', params: config.params || [] }, { data: this.props.data, step: this.props.step }) return
} - handleStatisticContent = (config: statisticContentConfig) => { - return (config.statistics || []).map((statistic) => { + handleStatisticContent = (config: statisticContentConfig, _position: string) => { + return (config.statistics || []).map((statistic, index) => { const value = statistic.value ? ParamHelper(statistic.value, { data: this.props.data, step: this.props.step }) : undefined switch (statistic.type) { case 'value': @@ -201,15 +205,37 @@ export default class HeaderStep extends Step { value }) case 'enumeration': - // TODO - return null + if (statistic.options) { + EnumerationHelper.options(statistic.options, (config, source) => this.interfaceHelper.request(config, source, { data: this.props.data, step: this.props.step }, { loadDomain: this.props.loadDomain })).then((options) => { + if (!this.state || JSON.stringify(this.state[`statistic_options_${_position}_${index}`]) !== JSON.stringify(options)) { + this.setState({ + [`statistic_options_${_position}_${index}`]: options + }) + } + }) + + const options: { value: any, label: any }[] = this.state && this.state[`statistic_options_${_position}_${index}`] + if (options) { + const option = options.find((option) => option.value === value) + if (option) { + return this.renderStatisticComponent({ + label: statistic.label || '', + value: option.label + }) + } + } + } + return this.renderStatisticComponent({ + label: statistic.label || '', + value + }) default: return null } }) } - handleImageContent = (config: imageContentConfig) => { + handleImageContent = (config: imageContentConfig, _position: string) => { if (config.image && config.image.src) { return } else { @@ -248,19 +274,19 @@ export default class HeaderStep extends Step { const mainContent = this.props.config.mainContent switch (mainContent.type) { case 'plain': - props.mainContent = this.handlePlainContent(mainContent) + props.mainContent = this.handlePlainContent(mainContent, 'main') break; case 'markdown': - props.mainContent = this.handleMarkdownContent(mainContent) + props.mainContent = this.handleMarkdownContent(mainContent, 'main') break; case 'html': - props.mainContent = this.handleHTMLContent(mainContent) + props.mainContent = this.handleHTMLContent(mainContent, 'main') break; case 'detail': // TODO break; case 'statistic': - props.mainContent = this.handleStatisticContent(mainContent) + props.mainContent = this.handleStatisticContent(mainContent, 'main') default: break; } @@ -270,10 +296,10 @@ export default class HeaderStep extends Step { const extraContent = this.props.config.extraContent switch (extraContent.type) { case 'statistic': - props.extraContent = this.handleStatisticContent(extraContent) + props.extraContent = this.handleStatisticContent(extraContent, 'extra') break; case 'image': - props.extraContent = this.handleImageContent(extraContent) + props.extraContent = this.handleImageContent(extraContent, 'extra') break; default: break; diff --git a/src/util/enumeration.ts b/src/util/enumeration.ts new file mode 100644 index 0000000..0b3c41d --- /dev/null +++ b/src/util/enumeration.ts @@ -0,0 +1,77 @@ +import { InterfaceConfig } from "./interface"; +import { getValue } from "./value"; + +export type EnumerationOptionsConfig = ManualEnumerationOptionsConfig | InterfaceEnumerationOptionsConfig + +interface ManualEnumerationOptionsConfig { + from: 'manual' + data?: Array<{ + value: string | number | boolean + label: string + [extra: string]: any + }> +} + +interface InterfaceEnumerationOptionsConfig { + from: 'interface' + interface?: InterfaceConfig + format?: InterfaceEnumerationOptionsKVConfig | InterfaceEnumerationOptionsListConfig +} + +interface InterfaceEnumerationOptionsKVConfig { + type: 'kv' +} + +interface InterfaceEnumerationOptionsListConfig { + type: 'list' + keyField: string + labelField: string +} + +export default class EnumerationHelper { + static _instance: EnumerationHelper + + public async options (config: EnumerationOptionsConfig, interfaceRequire: (config: InterfaceConfig, source: any) => Promise) { + if (config) { + if (config.from === 'manual') { + if (config.data) { + return config.data.map((option) => { + return { + value: option.value, + label: option.label + } + }) + } + } else if (config.from === 'interface') { + if (config.interface) { + const data = await interfaceRequire(config.interface, {}) + if (config.format) { + if (config.format.type === 'kv') { + return Object.keys(data).map((key) => ({ + value: key, + label: data[key] + })) + } else if (config.format.type === 'list') { + return data.map((item: any) => { + if (config.format && config.format.type === 'list') { + return ({ + value: getValue(item, config.format.keyField), + label: getValue(item, config.format.labelField) + }) + } + }) + } + } + } + } + } + return [] + } + + static async options (config: EnumerationOptionsConfig, interfaceRequire: (config: InterfaceConfig, source: any) => Promise) { + if (!EnumerationHelper._instance) { + EnumerationHelper._instance = new EnumerationHelper() + } + return await EnumerationHelper._instance.options(config, interfaceRequire) + } +} \ No newline at end of file -- Gitee From d31fa0234e4185b00c42386ca387c16d2fcbfba9 Mon Sep 17 00:00:00 2001 From: niuxiaoguang Date: Fri, 19 Nov 2021 16:47:41 +0800 Subject: [PATCH 6/7] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E5=85=AC=E5=85=B1=E6=A8=A1=E5=9D=97=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.tsx | 4 +- src/steps/header/index.tsx | 64 +++++++++---- src/util/operation.tsx | 187 +++++++++++++++++++++++++++++++++++++ 3 files changed, 237 insertions(+), 18 deletions(-) create mode 100644 src/util/operation.tsx diff --git a/src/index.tsx b/src/index.tsx index 7a3e926..3b3c986 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -41,4 +41,6 @@ export { default as FetchStep } from './steps/fetch' export { default as HeaderStep } from './steps/header' -export { default as InterfaceHelper } from "./util/interface" \ No newline at end of file +export { default as InterfaceHelper } from "./util/interface" + +export { default as OperationHelper } from "./util/operation" \ No newline at end of file diff --git a/src/steps/header/index.tsx b/src/steps/header/index.tsx index 26b1ea2..f138449 100644 --- a/src/steps/header/index.tsx +++ b/src/steps/header/index.tsx @@ -2,12 +2,11 @@ import React, { ReactNode } from 'react' import Step, { StepConfig } from '../common' import { ParamConfig } from '../../interface' import StatementHelper, { StatementConfig } from '../../util/statement' -import { InterfaceOptionsConfig, ManualOptionsConfig } from '../../components/formFields/select/common' -import { TableCCMSOperationConfig } from '../table' import marked from 'marked' import ParamHelper from '../../util/param' import EnumerationHelper, { EnumerationOptionsConfig } from '../../util/enumeration' import { InterfaceHelper } from '../..' +import OperationHelper, { OperationConfig } from '../../util/operation' /** * header页头配置文件格式定义 @@ -41,7 +40,7 @@ export interface HeaderConfig extends StepConfig { export interface breadcrumbConfig { label?: string type?: 'normal' | 'bold' - action?: TableCCMSOperationConfig + action?: OperationConfig } interface basicContentConfig { @@ -94,20 +93,25 @@ export interface imageContentConfig extends basicContentConfig { } } +/** + * 面包屑元素config + * - label: 文案 + * - type: 展示形式 + * - onClick: 点击事件 + */ +export interface IBreadcurmbItemProps { + label: string + type: 'normal' | 'bold' + onClick: () => void +} + /** * 面包屑内容config * - items: 面包屑内容 - * -- label: 文案 - * -- type: 展示形式 - * -- onClick: 点击事件 * - separator: 分割符 */ export interface IBreadcurmbProps { - items: Array<{ - label: string - type: 'normal' | 'bold' - onClick: () => void - }> + items: Array separator: string } @@ -141,18 +145,29 @@ export interface IHeaderProps { export default class HeaderStep extends Step { interfaceHelper = new InterfaceHelper() + OperationHelper = OperationHelper stepPush = async () => { // 表单初始化结束,展示表单界面。 if (this.props.onMount) { this.props.onMount() } - console.log('this.props.onSubmit') if (this.props.onSubmit) { this.props.onSubmit({}) } } + /** + * 用于展示面包屑元素 + * @param props + * @returns + */ + renderBreadcurmbItemComponent = (props: IBreadcurmbItemProps) => { + return + 您当前使用的UI版本没有实现HeaderStep组件的renderBreadcurmbItemComponent方法。 + + } + /** * 用于展示面包屑 * @param props @@ -249,11 +264,26 @@ export default class HeaderStep extends Step { if (this.props.config.breadcrumb && this.props.config.breadcrumb.enable) { const breadcrumbConfig = this.props.config.breadcrumb props.breadcrumb = this.renderBreadcurmbComponent({ - items: (breadcrumbConfig.items || []).map((breadcrumbItem) => ({ - label: breadcrumbItem.label || '', - type: breadcrumbItem.type || 'normal', - onClick: () => {} // TODO - })), + items: (breadcrumbConfig.items || []).map((breadcrumbItem) => ( + + {(onClick) => ( + this.renderBreadcurmbItemComponent({ + label: breadcrumbItem.label || '', + type: breadcrumbItem.type || 'normal', + onClick + }) + )} + + )), separator: breadcrumbConfig.separator || '>' }) } diff --git a/src/util/operation.tsx b/src/util/operation.tsx new file mode 100644 index 0000000..675f4d7 --- /dev/null +++ b/src/util/operation.tsx @@ -0,0 +1,187 @@ +import React from 'react'; +import queryString from 'query-string'; +import { set } from "lodash"; +import { ParamConfig } from "../interface"; +import { CCMSConfig, CCMSProps } from "../main"; +import { getParam } from "./value"; + +export type OperationConfig = CCMSOperationConfig + +export interface IOperationModal { + title: string + content: React.ReactNode + onClose: () => void +} + +/** CCMS内部操作 */ +interface _CCMSOperationConfig { + /** 操作类型:CCMS内部操作 */ + type: 'ccms' + + /** 目标资源 */ + page: any + + /** 参数 */ + data: { [key: string]: ParamConfig } +} + +/** CCMS模态窗口操作 */ +interface CCMSPopupOperationConfig extends _CCMSOperationConfig { + mode: 'popup' + label: string +} + +/** CCMS重定向操作 */ +interface CCMSRedirectOperationConfig extends _CCMSOperationConfig { + mode: 'redirect' +} + +/** CCMS新标签页操作 */ +interface CCMSWindowOperationConfig extends _CCMSOperationConfig { + mode: 'window' +} + +/** CCMS无界面操作 */ +interface CCMSInvisibleOperationConfig extends _CCMSOperationConfig { + mode: 'invisible' +} + +type CCMSOperationConfig = CCMSPopupOperationConfig | CCMSRedirectOperationConfig | CCMSWindowOperationConfig | CCMSInvisibleOperationConfig + +interface OperationHelperProps { + config?: OperationConfig, + datas: { record?: object, data: object[], step: number }, + checkPageAuth: (pageID: any) => Promise, + loadPageURL: (pageID: any) => Promise, + loadPageFrameURL: (pageID: any) => Promise, + loadPageConfig: (pageID: any) => Promise, + baseRoute: string, + loadDomain: (domain: string) => Promise + + children?: (handleOperation: () => void) => React.ReactNode + callback?: () => void +} + +interface OperationHelperState { + operationConfig: CCMSConfig | null + sourceData?: any +} + +export default class OperationHelper extends React.Component { + constructor (props: OperationHelperProps) { + super(props) + + this.state = { + operationConfig: null + } + } + + protected renderModal (props: IOperationModal) { + return + 您当前使用的UI版本没有实现OpertionHelper组件。 + + } + + protected renderCCMS (props: CCMSProps) { + return + 您当前使用的UI版本没有实现OpertionHelper组件。 + + } + + private handleCCMS (config: CCMSOperationConfig) { + const { + datas, + loadPageURL, + loadPageFrameURL, + loadPageConfig, + } = this.props + return async () => { + if (config.type === 'ccms') { + const sourceData = {} + for (const [field, param] of Object.entries(config.data || {})) { + set(sourceData, field, getParam(param, datas)) + } + if (config.mode === 'popup' || config.mode === 'invisible') { + const operationConfig = await loadPageConfig(config.page) + this.setState({ + operationConfig, + sourceData + }) + } else if (config.mode === 'redirect') { + const sourceURL = await loadPageURL(config.page) + const { url, query } = queryString.parseUrl(sourceURL, { arrayFormat: 'bracket' }) + window.location.href = queryString.stringifyUrl({ url, query: { ...query, ...sourceData } }, { arrayFormat: 'bracket' }) || '' + } else if (config.mode === 'window') { + const sourceURL = await loadPageFrameURL(config.page) + const { url, query } = queryString.parseUrl(sourceURL, { arrayFormat: 'bracket' }) + window.open(queryString.stringifyUrl({ url, query: { ...query, ...sourceData } }, { arrayFormat: 'bracket' }) || '') + } + } + } + } + + + render () { + if (this.props.config) { + return ( + + {this.props.children && this.props.children(this.handleCCMS(this.props.config))} + {this.state.operationConfig !== null && this.props.config.mode === 'popup' && ( + this.renderModal({ + title: this.props.config.label, + content: this.renderCCMS({ + config: this.state.operationConfig, + sourceData: this.state.sourceData, + baseRoute: this.props.baseRoute, + checkPageAuth: this.props.checkPageAuth, + loadPageURL: this.props.loadPageURL, + loadPageFrameURL: this.props.loadPageFrameURL, + loadPageConfig: this.props.loadPageConfig, + loadDomain: this.props.loadDomain, + callback: () => { + this.setState({ + operationConfig: null, + sourceData: null + }) + this.props.callback && this.props.callback() + } + }), + onClose: () => { + this.setState({ + operationConfig: null, + sourceData: null + }) + this.props.callback && this.props.callback() + } + }) + )} + {this.state.operationConfig !== null && this.props.config.mode === 'invisible' && ( + this.renderCCMS({ + config: this.state.operationConfig, + sourceData: this.state.sourceData, + baseRoute: this.props.baseRoute, + checkPageAuth: this.props.checkPageAuth, + loadPageURL: this.props.loadPageURL, + loadPageFrameURL: this.props.loadPageFrameURL, + loadPageConfig: this.props.loadPageConfig, + loadDomain: this.props.loadDomain, + callback: () => { + this.setState({ + operationConfig: null, + sourceData: null + }) + this.props.callback && this.props.callback() + } + }) + )} + + ) + } else { + return ( + + {this.props.children && this.props.children(() => {})} + + ) + } + } +} \ No newline at end of file -- Gitee From 99f894e63de3c657c3393f5b244814d41847ff1b Mon Sep 17 00:00:00 2001 From: niuxiaoguang Date: Wed, 24 Nov 2021 17:30:51 +0800 Subject: [PATCH 7/7] =?UTF-8?q?feat:=20=E5=9C=A8=E9=A1=B5=E5=A4=B4?= =?UTF-8?q?=E6=AD=A5=E9=AA=A4=E4=B8=AD=E5=BC=95=E7=94=A8=E8=AF=A6=E6=83=85?= =?UTF-8?q?=E6=AD=A5=E9=AA=A4=E5=86=85=E5=AE=B9=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/steps/header/index.tsx | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/steps/header/index.tsx b/src/steps/header/index.tsx index f138449..3bca8d0 100644 --- a/src/steps/header/index.tsx +++ b/src/steps/header/index.tsx @@ -7,6 +7,9 @@ import ParamHelper from '../../util/param' import EnumerationHelper, { EnumerationOptionsConfig } from '../../util/enumeration' import { InterfaceHelper } from '../..' import OperationHelper, { OperationConfig } from '../../util/operation' +import { DetailFieldConfigs } from '../../components/detail' +import DetailStep, { DetailConfig } from '../detail' +import { merge } from 'lodash' /** * header页头配置文件格式定义 @@ -64,6 +67,8 @@ export interface htmlContentConfig extends basicContentConfig { } export interface detailContentConfig extends basicContentConfig { type: 'detail' + fields?: DetailFieldConfigs[] + defaultValue?: ParamConfig } export interface statisticContentConfig extends basicContentConfig { type: 'statistic' @@ -146,6 +151,7 @@ export interface IHeaderProps { export default class HeaderStep extends Step { interfaceHelper = new InterfaceHelper() OperationHelper = OperationHelper + DetailStep = DetailStep stepPush = async () => { // 表单初始化结束,展示表单界面。 @@ -210,6 +216,30 @@ export default class HeaderStep extends Step { return
} + handleDetailContent = (config: detailContentConfig, _position: string) => { + const defaultConfig: DetailConfig = { + type: 'detail', + hiddenBack: true + } + return ( + | null) => { e && e.stepPush() }} + data={this.props.data} + step={this.props.step} + onSubmit={async (data, unmountView) => {}} + onMount={async () => {}} + onUnmount={async (reload = false, data) => {}} + config={merge(config, defaultConfig)} + baseRoute={this.props.baseRoute} + checkPageAuth={this.props.checkPageAuth} + loadPageURL={this.props.loadPageURL} + loadPageFrameURL={this.props.loadPageFrameURL} + loadPageConfig={this.props.loadPageConfig} + loadDomain={this.props.loadDomain} + /> + ) + } + handleStatisticContent = (config: statisticContentConfig, _position: string) => { return (config.statistics || []).map((statistic, index) => { const value = statistic.value ? ParamHelper(statistic.value, { data: this.props.data, step: this.props.step }) : undefined @@ -313,7 +343,7 @@ export default class HeaderStep extends Step { props.mainContent = this.handleHTMLContent(mainContent, 'main') break; case 'detail': - // TODO + props.mainContent = this.handleDetailContent(mainContent, 'main') break; case 'statistic': props.mainContent = this.handleStatisticContent(mainContent, 'main') -- Gitee