From b11aa3309fec378e2b1bc573cdb5ceeb59f9fd20 Mon Sep 17 00:00:00 2001 From: zhujiamin <1147570162@qq.com> Date: Thu, 25 May 2023 18:45:00 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=E5=AE=8C=E5=96=84=E5=90=84?= =?UTF-8?q?=E7=B1=BB=E7=BC=96=E8=BE=91=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/app-rawitem/app-rawitem.tsx | 13 +- src/common/index.ts | 6 +- src/common/rawitem/rawitem.tsx | 181 ++++++++++++++++++ .../autocomplete-editor.controller.ts | 92 ++++++--- .../ibiz-autocomplete/ibiz-autocomplete.tsx | 91 +++++---- .../ibiz-picker-dropdown.tsx | 23 ++- .../ibiz-picker-select-view.tsx | 21 +- .../data-picker/ibiz-picker/ibiz-picker.tsx | 23 ++- .../data-picker/picker-editor.controller.ts | 94 ++++++--- .../date-range-editor.controller.ts | 53 +++++ .../date-range/date-range-editor.provider.ts | 28 +++ .../ibiz-date-range-picker.scss | 5 + .../ibiz-date-range-picker.tsx | 149 ++++++++++++++ src/editor/date-range/index.ts | 3 + src/editor/index.ts | 18 ++ .../list-box-picker-editor.controller.ts | 54 +++--- .../ibiz-number-range-picker.scss | 8 + .../ibiz-number-range-picker.tsx | 151 +++++++++++++++ src/editor/number-range/index.ts | 3 + .../number-range-editor.controller.ts | 11 ++ .../number-range-editor.provider.ts | 28 +++ src/editor/raw/ibiz-raw/ibiz-raw.tsx | 4 +- src/editor/span/span-editor.controller.ts | 17 +- .../stepper/stepper-editor.controller.ts | 10 +- src/editor/upload/upload-editor.controller.ts | 26 ++- 25 files changed, 931 insertions(+), 181 deletions(-) create mode 100644 src/common/rawitem/rawitem.tsx create mode 100644 src/editor/date-range/date-range-editor.controller.ts create mode 100644 src/editor/date-range/date-range-editor.provider.ts create mode 100644 src/editor/date-range/ibiz-date-range-picker/ibiz-date-range-picker.scss create mode 100644 src/editor/date-range/ibiz-date-range-picker/ibiz-date-range-picker.tsx create mode 100644 src/editor/date-range/index.ts create mode 100644 src/editor/number-range/ibiz-number-range-picker/ibiz-number-range-picker.scss create mode 100644 src/editor/number-range/ibiz-number-range-picker/ibiz-number-range-picker.tsx create mode 100644 src/editor/number-range/index.ts create mode 100644 src/editor/number-range/number-range-editor.controller.ts create mode 100644 src/editor/number-range/number-range-editor.provider.ts diff --git a/src/common/app-rawitem/app-rawitem.tsx b/src/common/app-rawitem/app-rawitem.tsx index 356ce3076..f7e311dd7 100644 --- a/src/common/app-rawitem/app-rawitem.tsx +++ b/src/common/app-rawitem/app-rawitem.tsx @@ -57,18 +57,7 @@ export const AppRawItem = defineComponent({ ].includes(props.type) ) { if (props.content && typeof props.content === 'string') { - const items = props.content.match(/\{{(.+?)\}}/g); - if (items) { - items.forEach((item: string) => { - rawItemText.value = (props.content as string).replace( - /\{{(.+?)\}}/, - // eslint-disable-next-line no-eval - eval(item.substring(2, item.length - 2)), - ); - }); - } else { - rawItemText.value = props.content; - } + rawItemText.value = props.content; rawItemText.value = rawItemText.value.replaceAll('<', '<'); rawItemText.value = rawItemText.value.replaceAll('>', '>'); rawItemText.value = rawItemText.value.replaceAll('&nbsp;', ' '); diff --git a/src/common/index.ts b/src/common/index.ts index 27256c728..f46693211 100644 --- a/src/common/index.ts +++ b/src/common/index.ts @@ -8,7 +8,7 @@ import { IBizRow } from './row/row'; import { IBizControlBase } from './control-base/control-base'; import { IBizControlShell } from './control-shell/control-shell'; import { IBizViewShell } from './view-shell/view-shell'; -import { AppRawItem } from './app-rawitem/app-rawitem'; +import { IBizRawItem } from './rawitem/rawitem'; export * from './icon/icon'; export * from './keep-alive/keep-alive'; @@ -19,7 +19,7 @@ export * from './action-toolbar/action-toolbar'; export * from './control-base/control-base'; export * from './control-shell/control-shell'; export * from './view-shell/view-shell'; -export * from './app-rawitem/app-rawitem'; +export * from './rawitem/rawitem'; export const IBizCommonComponents = { install: (v: App) => { @@ -32,7 +32,7 @@ export const IBizCommonComponents = { v.component(IBizActionToolbar.name, IBizActionToolbar); v.component(IBizViewShell.name, IBizViewShell); v.component(IBizControlShell.name, IBizControlShell); - v.component(AppRawItem.name, AppRawItem); + v.component(IBizRawItem.name, IBizRawItem); }, }; diff --git a/src/common/rawitem/rawitem.tsx b/src/common/rawitem/rawitem.tsx new file mode 100644 index 000000000..235d05043 --- /dev/null +++ b/src/common/rawitem/rawitem.tsx @@ -0,0 +1,181 @@ +import { useNamespace } from '@ibiz-template/vue3-util'; +import { defineComponent, ref } from 'vue'; +import { createUUID } from 'qx-util'; + +export const IBizRawItem = defineComponent({ + name: 'IBizRawItem', + props: { + type: { + type: String, + required: true, + }, + content: { + type: [String, Object], + }, + }, + setup(props) { + const ns = useNamespace('rawitem'); + + // 视频类型内容参数 + const playerParams = ref({ + id: createUUID(), + path: '', + mute: true, + autoplay: true, + replay: false, + showcontrols: true, + }); + + // 分割线类型参数 + const dividerParams = ref({ + contentPosition: 'center', + html: '', + }); + + // 类型参数 + const alertParams = ref({ + type: 'info', + title: '', + closeabled: true, + showIcon: false, + }); + + // 文本类型显示值 + const rawItemText = ref(''); + + if ( + [ + 'TEXT', + 'HEADING1', + 'HEADING2', + 'HEADING3', + 'HEADING4', + 'HEADING5', + 'HEADING6', + 'PARAGRAPH', + 'HTML', + ].includes(props.type) + ) { + if (props.content && typeof props.content === 'string') { + rawItemText.value = props.content; + rawItemText.value = rawItemText.value.replaceAll('<', '<'); + rawItemText.value = rawItemText.value.replaceAll('>', '>'); + rawItemText.value = rawItemText.value.replaceAll('&nbsp;', ' '); + rawItemText.value = rawItemText.value.replaceAll(' ', ' '); + } + } + + if (['VIDEO', 'DIVIDER', 'INFO', 'WARNING', 'ERROR'].includes(props.type)) { + if (props.content) { + let rawConfig = {}; + try { + if (typeof props.content === 'string') { + // eslint-disable-next-line no-new-func + const func = new Function(`return (${props.content});`); + rawConfig = func(); + switch (props.type) { + case 'VIDEO': + Object.assign(playerParams.value, rawConfig); + break; + case 'DIVIDER': + Object.assign(dividerParams.value, rawConfig); + break; + case 'INFO': + case 'WARNING': + case 'ERROR': + alertParams.value.type = props.type.toLocaleLowerCase(); + Object.assign(alertParams.value, rawConfig); + break; + default: + break; + } + } + } catch { + ibiz.log.error(`${props.type}类型自定义参数配置错误`); + } + } + } + + return { ns, rawItemText, playerParams, dividerParams, alertParams }; + }, + render() { + if (this.type === 'IMAGE') { + return ( + + ); + } + if (this.type === 'TEXT') { + return {this.rawItemText}; + } + if (this.type === 'HEADING1') { + return

{this.rawItemText}

; + } + if (this.type === 'HEADING2') { + return

{this.rawItemText}

; + } + if (this.type === 'HEADING3') { + return

{this.rawItemText}

; + } + if (this.type === 'HEADING4') { + return

{this.rawItemText}

; + } + if (this.type === 'HEADING5') { + return
{this.rawItemText}
; + } + if (this.type === 'HEADING6') { + return
{this.rawItemText}
; + } + if (this.type === 'PARAGRAPH') { + return

{this.rawItemText}

; + } + if (this.type === 'HTML') { + return ( +
+ ); + } + if (this.type === 'VIDEO') { + return ( +
+ +
+ ); + } + if (this.type === 'DIVIDER') { + return ( + + + + ); + } + if ( + this.type === 'INFO' || + this.type === 'WARNING' || + this.type === 'ERROR' + ) { + return ( + + ); + } + if (['MARKDOWN', 'PLACEHOLDER'].includes(this.type)) { + return
{this.type}类型暂未支持
; + } + return null; + }, +}); diff --git a/src/editor/autocomplete/autocomplete-editor.controller.ts b/src/editor/autocomplete/autocomplete-editor.controller.ts index 1df93ef0a..945f9b92b 100644 --- a/src/editor/autocomplete/autocomplete-editor.controller.ts +++ b/src/editor/autocomplete/autocomplete-editor.controller.ts @@ -1,6 +1,11 @@ import { IHttpResponse, RuntimeModelError } from '@ibiz-template/core'; import { EditorController } from '@ibiz-template/runtime'; -import { IAppDataEntity, IAutoComplete } from '@ibiz/model-core'; +import { + IAppDataEntity, + IAppDEACMode, + IAutoComplete, + IDEACModeDataItem, +} from '@ibiz/model-core'; /** * 自动完成编辑器控制器 @@ -17,20 +22,15 @@ export class AutoCompleteEditorController extends EditorController { super.onInit(); - this.valueItem = this.parent.valueItemName?.toLowerCase() || ''; if (this.model.appDataEntityId) { this.appDataEntity = await ibiz.hub.getAppDataEntity( this.model.appDataEntityId, this.context.srfappid, )!; if (this.appDataEntity) { - this.keyName = this.appDataEntity?.keyAppDEFieldId || ''; - this.textName = this.appDataEntity?.majorAppDEFieldId || ''; + this.keyName = this.appDataEntity.keyAppDEFieldId!; + this.textName = this.appDataEntity.majorAppDEFieldId!; this.getAcParams(); this.sort = this.getAcSort(); } @@ -79,23 +88,34 @@ export class AutoCompleteEditorController extends EditorController { + if (dataItem.id !== 'value' && dataItem.id !== 'text') { + this.dataItems.push(dataItem); + } + }); + } + } } /** * 获取自填模式sort排序 */ public getAcSort() { - // if (this.model.deACMode) { - // const { sortField, sortDir } = this.model.deACMode; - // if (sortField && sortDir) { - // return `${sortField},${sortDir}`; - // } - // } + if (this.deACMode) { + const { minorSortAppDEFieldId, minorSortDir } = this.deACMode; + if (minorSortAppDEFieldId && minorSortDir) { + return `${minorSortAppDEFieldId.toLowerCase()},${minorSortDir.toLowerCase()}`; + } + } return undefined; } @@ -136,15 +156,31 @@ export class AutoCompleteEditorController extends EditorController>} + * @returns {*} {Promise>} */ async calcFillDataItems( - _data: IData, + data: IData, // eslint-disable-next-line @typescript-eslint/no-explicit-any - ): Promise> { - // if (this.model.deACMode) { - // return DEACModeUtil.calcFillDataItems(data, this.model.deACMode); - // } + ): Promise> { + if (this.deACMode) { + if (this.dataItems.length === 0) { + return []; + } + const result = await Promise.all( + this.dataItems.map(item => { + const value = data[item.appDEFieldId!]; + if (item.format) { + // todo 值格式化 + } else if (item.convertToCodeItemText && item.codeListId) { + // todo 代码表转换为文本值 + } else if (item.customCode) { + // todo 脚本代码 + } + return { id: item.id!, value }; + }), + ); + return result; + } return []; } } diff --git a/src/editor/autocomplete/ibiz-autocomplete/ibiz-autocomplete.tsx b/src/editor/autocomplete/ibiz-autocomplete/ibiz-autocomplete.tsx index d3ff1d4a8..ec77c44af 100644 --- a/src/editor/autocomplete/ibiz-autocomplete/ibiz-autocomplete.tsx +++ b/src/editor/autocomplete/ibiz-autocomplete/ibiz-autocomplete.tsx @@ -5,7 +5,7 @@ import { useNamespace, } from '@ibiz-template/vue3-util'; import './ibiz-autocomplete.scss'; -import { isEmpty } from 'ramda'; +import { debounce } from 'lodash-es'; import { AutoCompleteEditorController } from '../autocomplete-editor.controller'; export const IBizAutoComplete = defineComponent({ @@ -25,6 +25,18 @@ export const IBizAutoComplete = defineComponent({ // 实体数据集 const items: Ref = ref([]); + // 获取实体数据后,需要判断一次当前值是否在返回数据中 + watch(items, (newVal, oldVal) => { + if (oldVal.length === 0 && newVal.length > 0) { + const index = newVal.findIndex((item: IData) => + Object.is(item[c.keyName], props.value), + ); + if (index !== -1) { + curValue.value = newVal[index][c.textName]; + } + } + }); + // 是否显示所有数据 const isShowAll = ref(true); @@ -35,21 +47,16 @@ export const IBizAutoComplete = defineComponent({ () => props.value, newVal => { if (newVal || newVal === null) { - curValue.value = newVal; if (newVal === null) { curValue.value = ''; } - const value = props.data[c.valueItem]; const index = items.value.findIndex((item: IData) => - Object.is(item[c.keyName], value), + Object.is(item[c.keyName], newVal), ); if (index !== -1) { - return; - } - // items里匹配不到当前值项值时,生成自身的选项 - items.value = []; - if (!isEmpty(newVal) && !isEmpty(value)) { - items.value.push({ [c.textName]: newVal, [c.keyName]: value }); + curValue.value = items.value[index][c.textName]; + } else { + curValue.value = newVal; } } }, @@ -62,15 +69,12 @@ export const IBizAutoComplete = defineComponent({ const dataItems = await c.calcFillDataItems(data); if (dataItems.length) { dataItems.forEach(dataItem => { - emit('change', dataItem.value, dataItem.name); + emit('change', dataItem.value, dataItem.id); }); } - // 处理值项和本身的值 - if (c.valueItem) { - emit('change', data[c.keyName], c.valueItem); - } - emit('change', data[c.textName]); + // 处理本身的值 + emit('change', data[c.keyName]); }; // 往外抛值 @@ -92,21 +96,19 @@ export const IBizAutoComplete = defineComponent({ } } }; + // 开始时搜索一次拿items + onSearch(''); // 清除 const onClear = () => { - // zjm todo 实体自填模式相关 // 清空回填数据 - // const dataItems = c.model.deACMode?.dataItems; - // if (dataItems?.length) { - // dataItems.forEach(dataItem => { - // emit('change', null, dataItem.name); - // }); - // } - // if (c.valueItem) { - // emit('change', null, c.valueItem); - // } - // emit('change', null); + const dataItems = c.dataItems; + if (dataItems.length > 0) { + dataItems.forEach(dataItem => { + emit('change', null, dataItem.id); + }); + } + emit('change', null); }; // 聚焦 @@ -140,6 +142,29 @@ export const IBizAutoComplete = defineComponent({ ); }); + let isDebounce = false; + let blurCacheValue: string | undefined; + // 防抖值变更回调 + const debounceChange = debounce( + (val: string | number) => { + // 拦截掉blur触发后change + if (blurCacheValue !== val) { + emit('change', val); + } + blurCacheValue = undefined; + isDebounce = false; + }, + 300, + { leading: true }, + ); + // 输入完成后抛值 + const handleInput = (val: string | number) => { + if (editorType !== 'AC_FS' && editorType !== 'AC_FS_NOBUTTON') { + isDebounce = true; + debounceChange(val); + } + }; + return { ns, c, @@ -151,6 +176,9 @@ export const IBizAutoComplete = defineComponent({ onClear, onFocus, onACSelect, + items, + handleInput, + isDebounce, }; }, render() { @@ -167,16 +195,13 @@ export const IBizAutoComplete = defineComponent({ fetch-suggestions={this.onSearch} onClear={this.onClear} disabled={this.disabled || this.readonly} + onSelect={this.onACSelect} + onInput={this.handleInput} > {{ default: ({ item }: { item: IData }) => { return ( -
{ - this.onACSelect(item); - }} - > +
{item[this.c.textName]}
); diff --git a/src/editor/data-picker/ibiz-picker-dropdown/ibiz-picker-dropdown.tsx b/src/editor/data-picker/ibiz-picker-dropdown/ibiz-picker-dropdown.tsx index 4de698eca..7eee183c0 100644 --- a/src/editor/data-picker/ibiz-picker-dropdown/ibiz-picker-dropdown.tsx +++ b/src/editor/data-picker/ibiz-picker-dropdown/ibiz-picker-dropdown.tsx @@ -71,7 +71,7 @@ export const IBizPickerDropDown = defineComponent({ const dataItems = await c.calcFillDataItems(item); if (dataItems.length) { dataItems.forEach(dataItem => { - emit('change', dataItem.value, dataItem.name); + emit('change', dataItem.value, dataItem.id); }); } @@ -129,18 +129,17 @@ export const IBizPickerDropDown = defineComponent({ // 清除 const onClear = () => { - // zjm todo 实体自填模式相关 // 清空回填数据 - // const dataItems = c.model.deACMode?.dataItems; - // if (dataItems?.length) { - // dataItems.forEach(dataItem => { - // emit('change', null, dataItem.name); - // }); - // } - // if (c.valueItem) { - // emit('change', null, c.valueItem); - // } - // emit('change', null); + const dataItems = c.dataItems; + if (dataItems?.length) { + dataItems.forEach(dataItem => { + emit('change', null, dataItem.id); + }); + } + if (c.valueItem) { + emit('change', null, c.valueItem); + } + emit('change', null); }; return { ns, diff --git a/src/editor/data-picker/ibiz-picker-select-view/ibiz-picker-select-view.tsx b/src/editor/data-picker/ibiz-picker-select-view/ibiz-picker-select-view.tsx index ad121378d..a84fb2c6b 100644 --- a/src/editor/data-picker/ibiz-picker-select-view/ibiz-picker-select-view.tsx +++ b/src/editor/data-picker/ibiz-picker-select-view/ibiz-picker-select-view.tsx @@ -143,18 +143,17 @@ export const IBizPickerSelectView = defineComponent({ // 清除 const onClear = () => { - // zjm todo 实体自填模式相关 // 清空回填数据 - // const dataItems = c.model.deACMode?.dataItems; - // if (dataItems?.length) { - // dataItems.forEach(dataItem => { - // emit('change', null, dataItem.name); - // }); - // } - // if (c.valueItem) { - // emit('change', null, c.valueItem); - // } - // emit('change', null); + const dataItems = c.dataItems; + if (dataItems?.length) { + dataItems.forEach(dataItem => { + emit('change', null, dataItem.id); + }); + } + if (c.valueItem) { + emit('change', null, c.valueItem); + } + emit('change', null); }; // 视图数据改变 diff --git a/src/editor/data-picker/ibiz-picker/ibiz-picker.tsx b/src/editor/data-picker/ibiz-picker/ibiz-picker.tsx index a5e5e0e6a..99a396498 100644 --- a/src/editor/data-picker/ibiz-picker/ibiz-picker.tsx +++ b/src/editor/data-picker/ibiz-picker/ibiz-picker.tsx @@ -60,7 +60,7 @@ export const IBizPicker = defineComponent({ const dataItems = await c.calcFillDataItems(data); if (dataItems.length) { dataItems.forEach(dataItem => { - emit('change', dataItem.value, dataItem.name); + emit('change', dataItem.value, dataItem.id); }); } @@ -111,18 +111,17 @@ export const IBizPicker = defineComponent({ // 清除 const onClear = () => { - // zjm todo 实体自填模式相关 // 清空回填数据 - // const dataItems = c.model.deACMode?.dataItems; - // if (dataItems?.length) { - // dataItems.forEach(dataItem => { - // emit('change', null, dataItem.name); - // }); - // } - // if (c.valueItem) { - // emit('change', null, c.valueItem); - // } - // emit('change', null); + const dataItems = c.dataItems; + if (dataItems?.length) { + dataItems.forEach(dataItem => { + emit('change', null, dataItem.id); + }); + } + if (c.valueItem) { + emit('change', null, c.valueItem); + } + emit('change', null); }; // 聚焦 diff --git a/src/editor/data-picker/picker-editor.controller.ts b/src/editor/data-picker/picker-editor.controller.ts index cdaa2b5fc..62203de71 100644 --- a/src/editor/data-picker/picker-editor.controller.ts +++ b/src/editor/data-picker/picker-editor.controller.ts @@ -1,6 +1,12 @@ import { IHttpResponse, RuntimeModelError } from '@ibiz-template/core'; import { EditorController, OpenAppViewCommand } from '@ibiz-template/runtime'; -import { IAppDataEntity, IAppView, IPicker } from '@ibiz/model-core'; +import { + IAppDataEntity, + IAppDEACMode, + IAppView, + IDEACModeDataItem, + IPicker, +} from '@ibiz/model-core'; /** * 数据选择编辑器控制器 @@ -37,12 +43,12 @@ export class PickerEditorController extends EditorController { /** * 主键属性名称 */ - public keyName: string = ''; + public keyName: string = 'srfkey'; /** * 主文本属性名称 */ - public textName: string = ''; + public textName: string = 'srfmajortext'; /** * 实体codeName @@ -74,19 +80,28 @@ export class PickerEditorController extends EditorController { */ public appDataEntity: IAppDataEntity | null = null; + /** + * 实体自填模式模型 + */ + public deACMode: IAppDEACMode | null = null; + + /** + * 自填数据项集合(已排除了value和text) + */ + public dataItems: IDEACModeDataItem[] = []; + protected async onInit(): Promise { super.onInit(); this.initParams(); - // zjm todo 值项名称父模型没有valueItemName - this.valueItem = this.parent.valueItemName?.toLowerCase() || ''; + this.valueItem = this.model.valueItemName?.toLowerCase() || ''; if (this.model.appDataEntityId) { this.appDataEntity = await ibiz.hub.getAppDataEntity( this.model.appDataEntityId, this.context.srfappid, )!; if (this.appDataEntity) { - this.keyName = this.appDataEntity?.keyAppDEFieldId || ''; - this.textName = this.appDataEntity?.majorAppDEFieldId || ''; + this.keyName = this.appDataEntity.keyAppDEFieldId!; + this.textName = this.appDataEntity.majorAppDEFieldId!; this.getAcParams(); this.sort = this.getAcSort(); } @@ -141,23 +156,34 @@ export class PickerEditorController extends EditorController { if (this.model.appDEDataSetId) { this.interfaceName = this.model.appDEDataSetId; } - // zjm todo 实体自填模式模型 - // if (this.model.deACMode) { - // this.textName = this.model.deACMode.textFieldName || this.textName; - // this.keyName = this.model.deACMode.valueFieldName || this.keyName; - // } + if (this.appDataEntity?.appDEACModes) { + this.deACMode = this.appDataEntity.appDEACModes[0]; + if (this.deACMode.textAppDEFieldId) { + this.textName = this.deACMode.textAppDEFieldId; + } + if (this.deACMode.valueAppDEFieldId) { + this.keyName = this.deACMode.valueAppDEFieldId; + } + if (this.deACMode.deacmodeDataItems) { + this.deACMode.deacmodeDataItems.forEach(dataItem => { + if (dataItem.id !== 'value' && dataItem.id !== 'text') { + this.dataItems.push(dataItem); + } + }); + } + } } /** * 获取自填模式sort排序 */ public getAcSort() { - // if (this.model.deACMode) { - // const { sortField, sortDir } = this.model.deACMode; - // if (sortField && sortDir) { - // return `${sortField},${sortDir}`; - // } - // } + if (this.deACMode) { + const { minorSortAppDEFieldId, minorSortDir } = this.deACMode; + if (minorSortAppDEFieldId && minorSortDir) { + return `${minorSortAppDEFieldId.toLowerCase()},${minorSortDir.toLowerCase()}`; + } + } return undefined; } @@ -232,7 +258,9 @@ export class PickerEditorController extends EditorController { this.context, this.params, ); - context.srfkey = data[this.valueItem]; + if (data[this.valueItem]) { + context.srfkey = data[this.valueItem]; + } const { linkAppViewId } = this.model; if (!linkAppViewId) { throw new RuntimeModelError(this.model, '请配置数据链接视图'); @@ -251,15 +279,31 @@ export class PickerEditorController extends EditorController { * @author lxm * @date 2022-10-24 16:10:24 * @param {IData} data 选中数据 - * @returns {*} {Promise>} + * @returns {*} {Promise>} */ async calcFillDataItems( - _data: IData, + data: IData, // eslint-disable-next-line @typescript-eslint/no-explicit-any - ): Promise> { - // if (this.model.deACMode) { - // return DEACModeUtil.calcFillDataItems(data, this.model.deACMode); - // } + ): Promise> { + if (this.deACMode) { + if (this.dataItems.length === 0) { + return []; + } + const result = await Promise.all( + this.dataItems.map(item => { + const value = data[item.appDEFieldId!]; + if (item.format) { + // todo 值格式化 + } else if (item.convertToCodeItemText && item.codeListId) { + // todo 代码表转换为文本值 + } else if (item.customCode) { + // todo 脚本代码 + } + return { id: item.id!, value }; + }), + ); + return result; + } return []; } } diff --git a/src/editor/date-range/date-range-editor.controller.ts b/src/editor/date-range/date-range-editor.controller.ts new file mode 100644 index 000000000..03f0bface --- /dev/null +++ b/src/editor/date-range/date-range-editor.controller.ts @@ -0,0 +1,53 @@ +import { EditorController } from '@ibiz-template/runtime'; +import { IDateRange } from '@ibiz/model-core'; + +/** + * 时间范围编辑器控制器 + * + * @export + * @class DateRangeEditorController + * @extends {EditorController} + */ +export class DateRangeEditorController extends EditorController { + /** + * 占位 + * @return {*} + * @author: zhujiamin + * @Date: 2022-08-25 14:33:14 + */ + public placeHolder = '请选择日期'; + + /** + * 根据编辑器类型获取格式化 + * + * @author lxm + * @date 2022-11-03 16:11:21 + * @public + * @returns {*} {string} + */ + public getFormatByType(): string { + switch (this.model.editorType) { + // 时间范围选择器 + case 'DATERANGE': + return 'YYYY-MM-DD HH:mm:ss'; + // 时间范围选择器(YYYY-MM-DD) + case 'DATERANGE_NOTIME': + return 'YYYY-MM-DD'; + default: + return 'YYYY-MM-DD HH:mm:ss'; + } + } + + /** + * 值格式化 + * @return {*} + * @author: zhujiamin + * @Date: 2022-08-25 14:33:14 + */ + public valueFormat: string | undefined; + + protected async onInit(): Promise { + super.onInit(); + this.valueFormat = this.getFormatByType(); + } +} diff --git a/src/editor/date-range/date-range-editor.provider.ts b/src/editor/date-range/date-range-editor.provider.ts new file mode 100644 index 000000000..11a252a3f --- /dev/null +++ b/src/editor/date-range/date-range-editor.provider.ts @@ -0,0 +1,28 @@ +import { + IEditorContainerController, + IEditorProvider, +} from '@ibiz-template/runtime'; +import { IDateRange } from '@ibiz/model-core'; +import { DateRangeEditorController } from './date-range-editor.controller'; + +/** + * 数值范围编辑器适配器 + * + * @export + * @class DateRangeEditorProvider + * @implements {EditorProvider} + */ +export class DateRangeEditorProvider implements IEditorProvider { + formEditor: string = 'IBizDateRangePicker'; + + gridEditor: string = 'IBizDateRangePicker'; + + async createController( + editorModel: IDateRange, + parentController: IEditorContainerController, + ): Promise { + const c = new DateRangeEditorController(editorModel, parentController); + await c.init(); + return c; + } +} diff --git a/src/editor/date-range/ibiz-date-range-picker/ibiz-date-range-picker.scss b/src/editor/date-range/ibiz-date-range-picker/ibiz-date-range-picker.scss new file mode 100644 index 000000000..c709f7d67 --- /dev/null +++ b/src/editor/date-range/ibiz-date-range-picker/ibiz-date-range-picker.scss @@ -0,0 +1,5 @@ +@include b(date-range-picker) { + .el-date-editor { + width: 100%; + } +} diff --git a/src/editor/date-range/ibiz-date-range-picker/ibiz-date-range-picker.tsx b/src/editor/date-range/ibiz-date-range-picker/ibiz-date-range-picker.tsx new file mode 100644 index 000000000..4f48650eb --- /dev/null +++ b/src/editor/date-range/ibiz-date-range-picker/ibiz-date-range-picker.tsx @@ -0,0 +1,149 @@ +import { computed, defineComponent, Ref, ref } from 'vue'; +import { + getEditorEmits, + getDateRangeProps, + useNamespace, +} from '@ibiz-template/vue3-util'; +import './ibiz-date-range-picker.scss'; +import { DateRangeEditorController } from '../date-range-editor.controller'; + +export const IBizDateRangePicker = defineComponent({ + name: 'IBizDateRangePicker', + props: getDateRangeProps(), + emits: getEditorEmits(), + setup(props, { emit }) { + const ns = useNamespace('date-range-picker'); + + const c = props.controller; + + const editorModel = c.model; + + // 值分割符 + let valueSeparator = '-'; + // 在范围选择器里取消两个日期面板之间的联动 + let unlinkPanels = false; + // 开始占位提示 + let startPlaceHolder = '开始时间'; + // 结束占位提示 + let endPlaceHolder = '结束时间'; + // 选择范围时的分隔符 + let rangeSeparator = '至'; + if (editorModel.editorParams) { + if (editorModel.editorParams.valueseparator) { + valueSeparator = editorModel.editorParams.valueseparator; + } + if (editorModel.editorParams.startplaceholder) { + startPlaceHolder = editorModel.editorParams.startplaceholder; + } + if (editorModel.editorParams.endplaceholder) { + endPlaceHolder = editorModel.editorParams.endplaceholder; + } + if (editorModel.editorParams.rangeseparator) { + rangeSeparator = editorModel.editorParams.rangeseparator; + } + if (editorModel.editorParams.unlinkpanels) { + unlinkPanels = c.handleStringToBoolean( + editorModel.editorParams.unlinkpanels, + ); + } + } + + // 类型 + const type = ref('daterange'); + switch (editorModel.editorType) { + case 'DATERANGE': + type.value = 'datetimerange'; + break; + case 'DATERANGE_NOTIME': + type.value = 'daterange'; + break; + default: + type.value = 'datetimerange'; + } + + // 格式 + const format = ref('YYYY-MM-DD'); + // 值格式化 + const valueFormat = c!.valueFormat; + if (valueFormat) { + format.value = valueFormat; + } + + // 关系表单项集合 + const refFormItem: Ref = ref([]); + const editorItems = editorModel.editorItems; + if (editorItems && editorItems.length > 0) { + const editorItemNames: string[] = editorItems.map( + (item: IData) => item.id, + ); + refFormItem.value = editorItemNames; + } + + // 当前值 + const curValue = computed({ + get() { + let value: string[] = []; + if (refFormItem.value) { + refFormItem.value.forEach((name: string) => { + if (props.data[name]) { + value.push(props.data[name]); + } + }); + } else if (props.value && typeof props.value === 'string') { + value = props.value.split(valueSeparator); + } + return value; + }, + set(dates: string[]) { + if (dates && dates.length > 0) { + emit('change', dates.join(valueSeparator)); + if (refFormItem.value) { + dates.forEach((date: string, index: number) => { + emit('change', date, refFormItem.value[index]); + }); + } + } else { + emit('change', null); + if (refFormItem.value) { + refFormItem.value.forEach((date: string, index: number) => { + emit('change', null, refFormItem.value[index]); + }); + } + } + }, + }); + + return { + ns, + c, + refFormItem, + curValue, + type, + format, + valueSeparator, + startPlaceHolder, + endPlaceHolder, + rangeSeparator, + unlinkPanels, + }; + }, + render() { + return ( +
+ +
+ ); + }, +}); diff --git a/src/editor/date-range/index.ts b/src/editor/date-range/index.ts new file mode 100644 index 000000000..313dfa995 --- /dev/null +++ b/src/editor/date-range/index.ts @@ -0,0 +1,3 @@ +export { IBizDateRangePicker } from './ibiz-date-range-picker/ibiz-date-range-picker'; +export * from './date-range-editor.controller'; +export * from './date-range-editor.provider'; diff --git a/src/editor/index.ts b/src/editor/index.ts index 6503166dc..a9ebb02c3 100644 --- a/src/editor/index.ts +++ b/src/editor/index.ts @@ -53,6 +53,11 @@ import { IBizPickerSelectView, DataPickerEditorProvider, } from './data-picker'; +import { + IBizNumberRangePicker, + NumberRangeEditorProvider, +} from './number-range'; +import { IBizDateRangePicker, DateRangeEditorProvider } from './date-range'; export const IBizEditor = { install: (v: App) => { @@ -90,6 +95,8 @@ export const IBizEditor = { v.component(IBizPickerLink.name, IBizPickerLink); v.component(IBizPickerEmbedView.name, IBizPickerEmbedView); v.component(IBizPickerSelectView.name, IBizPickerSelectView); + v.component(IBizNumberRangePicker.name, IBizNumberRangePicker); + v.component(IBizDateRangePicker.name, IBizDateRangePicker); // 标签 registerEditorProvider('SPAN', () => new SpanEditorProvider()); @@ -237,6 +244,17 @@ export const IBizEditor = { 'PICKUPVIEW', () => new DataPickerEditorProvider('PICKUPVIEW'), ); + // 数值范围 + registerEditorProvider( + 'NUMBERRANGE', + () => new NumberRangeEditorProvider(), + ); + // 时间范围 + registerEditorProvider('DATERANGE', () => new DateRangeEditorProvider()); + registerEditorProvider( + 'DATERANGE_NOTIME', + () => new DateRangeEditorProvider(), + ); }, }; diff --git a/src/editor/list-box/list-box-picker-editor.controller.ts b/src/editor/list-box/list-box-picker-editor.controller.ts index 31eb524e8..e030c0ed9 100644 --- a/src/editor/list-box/list-box-picker-editor.controller.ts +++ b/src/editor/list-box/list-box-picker-editor.controller.ts @@ -1,4 +1,4 @@ -import { IHttpResponse } from '@ibiz-template/core'; +import { IHttpResponse, RuntimeModelError } from '@ibiz-template/core'; import { EditorController } from '@ibiz-template/runtime'; import { IAppDataEntity, IListBoxPicker } from '@ibiz/model-core'; @@ -12,12 +12,12 @@ export class ListBoxPickerEditorController extends EditorController { super.onInit(); if (this.model.editorType === 'LISTBOXPICKUP') { - // zjm todo 列表框选择模型缺少实体请求相关的,如appDataEntityId - // this.appDataEntity = await ibiz.hub.getAppDataEntity( - // this.model.appDataEntityId!, - // this.context.srfappid, - // )!; - + this.appDataEntity = await ibiz.hub.getAppDataEntity( + this.model.appDataEntityId!, + this.context.srfappid, + ); if (this.appDataEntity) { - this.keyName = this.appDataEntity?.keyAppDEFieldId || ''; - this.textName = this.appDataEntity?.majorAppDEFieldId || ''; + this.keyName = this.appDataEntity.keyAppDEFieldId!; + this.textName = this.appDataEntity.majorAppDEFieldId!; this.getAcParams(); } } @@ -58,9 +56,9 @@ export class ListBoxPickerEditorController extends EditorController>} * @memberof PickerEditorController */ - public async getServiceData(_data: IData): Promise> { - // const { context, params } = this.handlePublicParams( - // data, - // this.context, - // this.params, - // ); - // Object.assign(params, { size: 1000 }); - // if (this.serviceName && this.interfaceName) { - // const deService = await this.app.es.getService(this.serviceName); - // const res = await deService.exec(this.interfaceName, context, params); - // return res as IHttpResponse; - // } - // throw new DefectModelError(this.model.source, '请配置实体和实体数据集'); - return {} as IHttpResponse; + public async getServiceData(data: IData): Promise> { + const { context, params } = this.handlePublicParams( + data, + this.context, + this.params, + ); + Object.assign(params, { size: 1000 }); + if (this.serviceName && this.interfaceName) { + const app = ibiz.hub.getApp(this.appDataEntity!.appId); + const deService = await app.deService.getService(this.serviceName); + const res = await deService.exec(this.interfaceName, context, params); + return res as IHttpResponse; + } + throw new RuntimeModelError(this.model, '请配置实体和实体数据集'); } } diff --git a/src/editor/number-range/ibiz-number-range-picker/ibiz-number-range-picker.scss b/src/editor/number-range/ibiz-number-range-picker/ibiz-number-range-picker.scss new file mode 100644 index 000000000..354c292aa --- /dev/null +++ b/src/editor/number-range/ibiz-number-range-picker/ibiz-number-range-picker.scss @@ -0,0 +1,8 @@ +@include b(number-range-picker) { + width: 100%; + @include flex(row); + + .el-input-number { + flex: 1; + } +} diff --git a/src/editor/number-range/ibiz-number-range-picker/ibiz-number-range-picker.tsx b/src/editor/number-range/ibiz-number-range-picker/ibiz-number-range-picker.tsx new file mode 100644 index 000000000..311d2cf61 --- /dev/null +++ b/src/editor/number-range/ibiz-number-range-picker/ibiz-number-range-picker.tsx @@ -0,0 +1,151 @@ +import { defineComponent, Ref, ref, watch } from 'vue'; +import { + getEditorEmits, + getNumberRangeProps, + useNamespace, +} from '@ibiz-template/vue3-util'; +import './ibiz-number-range-picker.scss'; +import { NumberRangeEditorController } from '../number-range-editor.controller'; + +export const IBizNumberRangePicker = defineComponent({ + name: 'IBizNumberRangePicker', + props: getNumberRangeProps(), + emits: getEditorEmits(), + setup(props, { emit }) { + const ns = useNamespace('number-range-picker'); + + const c = props.controller; + + const editorModel = c.model; + + // 最大值 + let max = Infinity; + // 最小值 + let min = -Infinity; + // 数值精度 + let precision = 0; + // 值分割符 + let valueSeparator = '-'; + // 开始占位提示 + let startPlaceHolder = '请输入开始数字'; + // 结束占位提示 + let endPlaceHolder = '请输入结束数字'; + // 选择范围时的分隔符 + let rangeSeparator = '~'; + if (editorModel.editorParams) { + if (editorModel.editorParams.maxvalue) { + max = c.handleStringToNumber(editorModel.editorParams.maxvalue); + } + if (editorModel.editorParams.minvalue) { + min = c.handleStringToNumber(editorModel.editorParams.minvalue); + } + if (editorModel.editorParams.precision) { + precision = c.handleStringToNumber(editorModel.editorParams.precision); + } + if (editorModel.editorParams.valueseparator) { + valueSeparator = editorModel.editorParams.valueseparator; + } + if (editorModel.editorParams.startplaceholder) { + startPlaceHolder = editorModel.editorParams.startplaceholder; + } + if (editorModel.editorParams.endplaceholder) { + endPlaceHolder = editorModel.editorParams.endplaceholder; + } + if (editorModel.editorParams.rangeseparator) { + rangeSeparator = editorModel.editorParams.rangeseparator; + } + } + + // 数据 + const items: number[] = []; + + // 关系表单项集合 + const refFormItem: Ref = ref([]); + const editorItems = editorModel.editorItems; + if (editorItems && editorItems.length > 0) { + const editorItemNames: string[] = editorItems.map( + (item: IData) => item.id, + ); + refFormItem.value = editorItemNames; + } + + // 范围最小值 + const minValue = ref(null); + + // 范围最大值 + const maxValue = ref(null); + + watch( + () => props.value, + (newVal, oldVal) => { + if (newVal !== oldVal && typeof newVal === 'string') { + minValue.value = newVal.split(valueSeparator)[0] + ? Number(newVal.split(valueSeparator)[0]) + : null; + maxValue.value = newVal.split(valueSeparator)[1] + ? Number(newVal.split(valueSeparator)[1]) + : null; + } + }, + { immediate: true }, + ); + + // 处理值变化 + const handleChange = (value: number, index: number) => { + items[index] = value; + if (items.length === 2) { + emit('change', items.join(valueSeparator)); + } + if (refFormItem.value) { + const valueName = refFormItem.value[index]; + emit('change', value, valueName); + } + }; + + return { + ns, + c, + refFormItem, + minValue, + maxValue, + handleChange, + max, + min, + precision, + valueSeparator, + startPlaceHolder, + endPlaceHolder, + rangeSeparator, + }; + }, + render() { + return ( +
+ this.handleChange(val, 0)} + > +
{this.rangeSeparator}
+ this.handleChange(val, 1)} + > +
+ ); + }, +}); diff --git a/src/editor/number-range/index.ts b/src/editor/number-range/index.ts new file mode 100644 index 000000000..ce262868b --- /dev/null +++ b/src/editor/number-range/index.ts @@ -0,0 +1,3 @@ +export { IBizNumberRangePicker } from './ibiz-number-range-picker/ibiz-number-range-picker'; +export * from './number-range-editor.controller'; +export * from './number-range-editor.provider'; diff --git a/src/editor/number-range/number-range-editor.controller.ts b/src/editor/number-range/number-range-editor.controller.ts new file mode 100644 index 000000000..0f21ca6b9 --- /dev/null +++ b/src/editor/number-range/number-range-editor.controller.ts @@ -0,0 +1,11 @@ +import { EditorController } from '@ibiz-template/runtime'; +import { INumberRange } from '@ibiz/model-core'; + +/** + * 数值范围编辑器控制器 + * + * @export + * @class NumberRangeEditorController + * @extends {EditorController} + */ +export class NumberRangeEditorController extends EditorController {} diff --git a/src/editor/number-range/number-range-editor.provider.ts b/src/editor/number-range/number-range-editor.provider.ts new file mode 100644 index 000000000..02695c6c7 --- /dev/null +++ b/src/editor/number-range/number-range-editor.provider.ts @@ -0,0 +1,28 @@ +import { + IEditorContainerController, + IEditorProvider, +} from '@ibiz-template/runtime'; +import { INumberRange } from '@ibiz/model-core'; +import { NumberRangeEditorController } from './number-range-editor.controller'; + +/** + * 数值范围编辑器适配器 + * + * @export + * @class NumberRangeEditorProvider + * @implements {EditorProvider} + */ +export class NumberRangeEditorProvider implements IEditorProvider { + formEditor: string = 'IBizNumberRangePicker'; + + gridEditor: string = 'IBizNumberRangePicker'; + + async createController( + editorModel: INumberRange, + parentController: IEditorContainerController, + ): Promise { + const c = new NumberRangeEditorController(editorModel, parentController); + await c.init(); + return c; + } +} diff --git a/src/editor/raw/ibiz-raw/ibiz-raw.tsx b/src/editor/raw/ibiz-raw/ibiz-raw.tsx index 3f2c232b8..f96692164 100644 --- a/src/editor/raw/ibiz-raw/ibiz-raw.tsx +++ b/src/editor/raw/ibiz-raw/ibiz-raw.tsx @@ -39,11 +39,11 @@ export const IBizRaw = defineComponent({ this.readonly ? this.ns.m('readonly') : '', ]} > - + >
); }, diff --git a/src/editor/span/span-editor.controller.ts b/src/editor/span/span-editor.controller.ts index a7af2e7cb..b9aa1a9e9 100644 --- a/src/editor/span/span-editor.controller.ts +++ b/src/editor/span/span-editor.controller.ts @@ -1,4 +1,4 @@ -import { ISpan, IAppView, IAppCodeList } from '@ibiz/model-core'; +import { ISpan, IAppCodeList } from '@ibiz/model-core'; import { CodeListEditorController, OpenAppViewCommand, @@ -17,11 +17,6 @@ export class SpanEditorController extends CodeListEditorController { */ public valueItem = ''; - /** - *链接视图相关参数 - */ - public linkView: IAppView | null = null; - /** * 代码表模型 * @return {*} @@ -32,8 +27,10 @@ export class SpanEditorController extends CodeListEditorController { protected async onInit(): Promise { super.onInit(); - // zjm todo 值项名称父没有valueItemName - this.valueItem = this.parent.valueItemName?.toLowerCase() || ''; + // span-link临时用editorItems + if (this.model?.editorItems?.[0]) { + this.valueItem = this.model.editorItems[0].id!; + } // 初始化代码表 if (this.model.appCodeListId) { const app = await ibiz.hub.getApp(this.context.srfappid); @@ -50,7 +47,9 @@ export class SpanEditorController extends CodeListEditorController { this.context, this.params, ); - context.srfkey = data[this.valueItem]; + if (data[this.valueItem]) { + context.srfkey = data[this.valueItem]; + } const { linkAppViewId } = this.model; if (!linkAppViewId) { throw new RuntimeModelError(this.model, '请配置数据链接视图'); diff --git a/src/editor/stepper/stepper-editor.controller.ts b/src/editor/stepper/stepper-editor.controller.ts index 4ca70e331..be31f108a 100644 --- a/src/editor/stepper/stepper-editor.controller.ts +++ b/src/editor/stepper/stepper-editor.controller.ts @@ -8,4 +8,12 @@ import { IStepper } from '@ibiz/model-core'; * @class StepperEditorController * @extends {EditorController} */ -export class StepperEditorController extends EditorController {} +export class StepperEditorController extends EditorController { + /** + * 占位 + * @return {*} + * @author: zhujiamin + * @Date: 2022-08-25 14:33:14 + */ + public placeHolder = '请输入'; +} diff --git a/src/editor/upload/upload-editor.controller.ts b/src/editor/upload/upload-editor.controller.ts index 8098ef292..26a6b4a46 100644 --- a/src/editor/upload/upload-editor.controller.ts +++ b/src/editor/upload/upload-editor.controller.ts @@ -1,4 +1,8 @@ -import { downloadFileFromBlob, RuntimeError } from '@ibiz-template/core'; +import { + downloadFileFromBlob, + RuntimeError, + RuntimeModelError, +} from '@ibiz-template/core'; import { convertNavData, EditorController } from '@ibiz-template/runtime'; import { IFileUploader } from '@ibiz/model-core'; import qs from 'qs'; @@ -63,12 +67,24 @@ export class UploadEditorController extends EditorController { this.accept = accept; } if (uploadparams) { - // eslint-disable-next-line no-eval - this.uploadParams = eval(`(${uploadparams})`); + try { + this.uploadParams = JSON.parse(uploadparams); + } catch (error) { + throw new RuntimeModelError( + uploadparams, + `配置uploadparams没有按标准JSON格式`, + ); + } } if (exportparams) { - // eslint-disable-next-line no-eval - this.exportParams = eval(`(${exportparams})`); + try { + this.exportParams = JSON.parse(exportparams); + } catch (error) { + throw new RuntimeModelError( + exportparams, + `配置exportparams没有按标准JSON格式`, + ); + } } } } -- Gitee From a5541d90702a4ffb91e95aa99cfc66fbebdeb816 Mon Sep 17 00:00:00 2001 From: zhujiamin <1147570162@qq.com> Date: Fri, 26 May 2023 18:35:05 +0800 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E8=A1=A8?= =?UTF-8?q?=E5=8D=95=E5=A4=9A=E6=95=B0=E6=8D=AE=E9=83=A8=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../form/edit-form/edit-form.controller.ts | 2 +- .../form/edit-form/edit-form.service.ts | 34 ++--- src/control/form/edit-form/edit-form.tsx | 15 ++- .../form-mdctrl/form-mdctrl.controller.ts | 119 ++++++++++++++++++ .../form-mdctrl/form-mdctrl.provider.ts | 27 ++++ .../form-detail/form-mdctrl/form-mdctrl.scss | 29 +++++ .../form-mdctrl/form-mdctrl.state.ts | 16 +++ .../form-detail/form-mdctrl/form-mdctrl.tsx | 111 ++++++++++++++++ .../form/form-detail/form-mdctrl/index.ts | 17 +++ src/control/form/form-detail/index.ts | 1 + src/control/form/form/form.controller.ts | 14 ++- src/control/form/form/index.ts | 2 + 12 files changed, 368 insertions(+), 19 deletions(-) create mode 100644 src/control/form/form-detail/form-mdctrl/form-mdctrl.controller.ts create mode 100644 src/control/form/form-detail/form-mdctrl/form-mdctrl.provider.ts create mode 100644 src/control/form/form-detail/form-mdctrl/form-mdctrl.scss create mode 100644 src/control/form/form-detail/form-mdctrl/form-mdctrl.state.ts create mode 100644 src/control/form/form-detail/form-mdctrl/form-mdctrl.tsx create mode 100644 src/control/form/form-detail/form-mdctrl/index.ts diff --git a/src/control/form/edit-form/edit-form.controller.ts b/src/control/form/edit-form/edit-form.controller.ts index eb8f2d5e4..a046d2781 100644 --- a/src/control/form/edit-form/edit-form.controller.ts +++ b/src/control/form/edit-form/edit-form.controller.ts @@ -62,7 +62,7 @@ export class EditFormController * @author lxm * @date 2022-08-19 14:08:50 */ - async load(): Promise { + async load(): Promise { this.isNewData = !hasDeCodeName(this.context, this.model.appDataEntityId!); const queryParams = { ...this.params }; diff --git a/src/control/form/edit-form/edit-form.service.ts b/src/control/form/edit-form/edit-form.service.ts index e7a69ec06..cadeb06c1 100644 --- a/src/control/form/edit-form/edit-form.service.ts +++ b/src/control/form/edit-form/edit-form.service.ts @@ -87,17 +87,17 @@ export class EditFormService< * @author lxm * @date 2022-09-07 19:09:11 * @param {IParams} context 上下文 - * @param {ControlVO} data 数据 + * @param {IData} data 数据 * @returns {*} */ async create( context: IParams, - data: ControlVO, + data: IData, ): Promise> { let res = await this.exec( this.model.createControlAction!.appDEMethodId!, context, - data.getOrigin(), + data instanceof ControlVO ? data.getOrigin() : data, ); res = this.handleResponse(res); return res as IHttpResponse; @@ -109,17 +109,17 @@ export class EditFormService< * @author lxm * @date 2022-09-07 19:09:11 * @param {IParams} context 上下文 - * @param {ControlVO} data 数据 + * @param {IData} data 数据 * @returns {*} */ async update( context: IParams, - data: ControlVO, + data: IData, ): Promise> { let res = await this.exec( this.model.updateControlAction!.appDEMethodId!, context, - data.getOrigin(), + data instanceof ControlVO ? data.getOrigin() : data, ); res = this.handleResponse(res); return res as IHttpResponse; @@ -131,19 +131,23 @@ export class EditFormService< * @author lxm * @date 2022-09-07 19:09:11 * @param {IParams} context 上下文 - * @param {ControlVO} data 数据 + * @param {IData} data 数据 * @returns {*} */ async goBack( context: IParams, - data: ControlVO, + data: IData, ): Promise> { const wizardForm = this.model as IDEWizardEditForm; const methodName = wizardForm.goBackControlAction?.appDEMethodId; if (!methodName) { throw new RuntimeModelError(this.model, '缺少返回操作实体行为'); } - let res = await this.exec(methodName, context, data.getOrigin()); + let res = await this.exec( + methodName, + context, + data instanceof ControlVO ? data.getOrigin() : data, + ); res = this.handleResponse(res); return res as IHttpResponse; } @@ -174,14 +178,14 @@ export class EditFormService< * @author lxm * @date 2022-09-07 19:09:11 * @param {IParams} context 上下文 - * @param {ControlVO} data 数据 + * @param {IData} data 数据 * @param {IParams} [params={}] 视图参数 * @returns {*} */ async wfStart( context: IParams, params: IParams, - data: ControlVO, + data: IData, ): Promise> { const wfForm = this.model as IWFEditForm; const methodName = wfForm.wfstartControlAction?.appDEMethodId; @@ -192,7 +196,7 @@ export class EditFormService< methodName, context, params, - data.getOrigin(), + data instanceof ControlVO ? data.getOrigin() : data, ); } @@ -202,14 +206,14 @@ export class EditFormService< * @author lxm * @date 2022-09-07 19:09:11 * @param {IParams} context 上下文 - * @param {ControlVO} data 数据 + * @param {IData} data 数据 * @param {IParams} [params={}] 视图参数 * @returns {*} */ async wfSubmit( context: IParams, params: IParams, - data: ControlVO, + data: IData, ): Promise> { const wfForm = this.model as IWFEditForm; const methodName = wfForm.wfsubmitControlAction?.appDEMethodId; @@ -220,7 +224,7 @@ export class EditFormService< methodName, context, params, - data.getOrigin(), + data instanceof ControlVO ? data.getOrigin() : data, ); } diff --git a/src/control/form/edit-form/edit-form.tsx b/src/control/form/edit-form/edit-form.tsx index ce5860f25..61cc82f23 100644 --- a/src/control/form/edit-form/edit-form.tsx +++ b/src/control/form/edit-form/edit-form.tsx @@ -1,7 +1,7 @@ /* eslint-disable no-param-reassign */ import { useControlController, useNamespace } from '@ibiz-template/vue3-util'; import { IDEEditForm } from '@ibiz/model-core'; -import { defineComponent, PropType, reactive } from 'vue'; +import { defineComponent, PropType, reactive, watch } from 'vue'; import { EditFormController } from './edit-form.controller'; export const EditFormControl = defineComponent({ @@ -13,11 +13,24 @@ export const EditFormControl = defineComponent({ }, context: { type: Object as PropType, required: true }, params: { type: Object as PropType, default: () => ({}) }, + isSimple: { type: Boolean, required: false }, + data: { type: Object as PropType, required: false }, }, setup() { const c = useControlController( (...args) => new EditFormController(...args), ); + + watch( + () => c.state.data, + (newVal, oldVal) => { + if (newVal && newVal !== oldVal) { + c.state.isLoaded = true; + } + }, + { immediate: true }, + ); + const ns = useNamespace(`control-${c.model.controlType!.toLowerCase()}`); c.evt.on('onCreated', () => { diff --git a/src/control/form/form-detail/form-mdctrl/form-mdctrl.controller.ts b/src/control/form/form-detail/form-mdctrl/form-mdctrl.controller.ts new file mode 100644 index 000000000..cf3f86f3f --- /dev/null +++ b/src/control/form/form-detail/form-mdctrl/form-mdctrl.controller.ts @@ -0,0 +1,119 @@ +import { + EventBase, + getControlProvider, + IControlProvider, +} from '@ibiz-template/runtime'; +import { IControl, IDEFormMDCtrl } from '@ibiz/model-core'; +import { FormDetailController } from '../form-detail'; +import { FormMDCtrlState } from './form-mdctrl.state'; + +/** + * 表单多数据部件控制器 + * + * @author lxm + * @date 2022-09-04 15:09:52 + * @export + * @class FormMDCtrlController + * @extends {FormDetailController} + */ +export class FormMDCtrlController extends FormDetailController { + declare state: FormMDCtrlState; + + protected createState(): FormMDCtrlState { + return new FormMDCtrlState(this.parent?.state); + } + + /** + * 所有部件的适配器 + * + * @author lxm + * @date 2022-08-24 20:08:07 + * @type {{ [key: string]: IControlProvider }} + */ + providers: { [key: string]: IControlProvider } = {}; + + /** + * 嵌入表单模型 + * @return {*} + * @author: zhujiamin + * @Date: 2023-05-26 10:44:10 + */ + formModel: IControl | null = null; + + protected async onInit(): Promise { + await super.onInit(); + // 编辑表单适配器 + const mdCtrl = this.model.contentControl; + if (mdCtrl && this.model.contentType === 'FORM') { + this.formModel = mdCtrl; + const formProvider = await getControlProvider(this.formModel); + if (formProvider) { + this.providers[this.formModel.id!] = formProvider; + } + } + } + + /** + * 内部表单数据发生改变,同步contentCtrlData并设置外部表单值 + * @param {EventBase} arg + * @param {number} index + * @return {*} + * @author: zhujiamin + * @Date: 2023-05-26 14:38:42 + */ + onFormDataChange(arg: EventBase, index: number) { + this.state.contentCtrlData[index] = arg.data[0]; + this.setFormDataValue(); + } + + /** + * 手动通知外部表单值变更 + * @return {*} + * @author: zhujiamin + * @Date: 2023-05-26 14:49:39 + */ + setFormDataValue() { + if (this.model.appDEFieldId) { + this.form.setDataValue( + this.model.appDEFieldId, + this.state.contentCtrlData, + ); + } + } + + /** + * 加载数据,要在表单加载完成之后再去加载 + * @return {*} + * @author: zhujiamin + * @Date: 2023-05-06 14:50:11 + */ + async loadData() { + if (this.model.appDEFieldId) { + this.state.contentCtrlData = this.data[this.model.appDEFieldId] || []; + } + } + + /** + * 处理删除 + * @param {IData} args + * @param {number} index + * @return {*} + * @author: zhujiamin + * @Date: 2023-05-06 14:54:55 + */ + async handleRemove(args: IData, index: number) { + this.state.contentCtrlData.splice(index, 1); + this.setFormDataValue(); + } + + /** + * 处理添加 + * @return {*} + * @author: zhujiamin + * @Date: 2023-05-06 14:59:24 + */ + async handleAdd() { + this.state.contentCtrlData.push({}); + this.setFormDataValue(); + } +} diff --git a/src/control/form/form-detail/form-mdctrl/form-mdctrl.provider.ts b/src/control/form/form-detail/form-mdctrl/form-mdctrl.provider.ts new file mode 100644 index 000000000..f0b0150f8 --- /dev/null +++ b/src/control/form/form-detail/form-mdctrl/form-mdctrl.provider.ts @@ -0,0 +1,27 @@ +import { IFormDetailProvider } from '@ibiz-template/runtime'; +import { IDEFormMDCtrl } from '@ibiz/model-core'; +import { FormController } from '../../form/form.controller'; +import { FormGroupPanelController } from '../form-group-panel'; +import { FormMDCtrlController } from './form-mdctrl.controller'; +/** + * 表单多数据部件适配器 + * + * @author lxm + * @date 2022-09-19 22:09:03 + * @export + * @class FormMDCtrlProvider + * @implements {EditorProvider} + */ +export class FormMDCtrlProvider implements IFormDetailProvider { + component: string = 'IBizFormMDCtrl'; + + async createController( + detailModel: IDEFormMDCtrl, + form: FormController, + parent: FormGroupPanelController | undefined, + ): Promise { + const c = new FormMDCtrlController(detailModel, form, parent); + await c.init(); + return c; + } +} diff --git a/src/control/form/form-detail/form-mdctrl/form-mdctrl.scss b/src/control/form/form-detail/form-mdctrl/form-mdctrl.scss new file mode 100644 index 000000000..2751fae3d --- /dev/null +++ b/src/control/form/form-detail/form-mdctrl/form-mdctrl.scss @@ -0,0 +1,29 @@ +@include b(form-mdctrl) { + @include b(form-mdctrl-main) { + @include b(form-mdctrl-form-content) { + @include flex(row); + } + + @include b(form-mdctrl-btn) { + cursor: pointer; + @include flex(column, flex-start, center); + } + + @include b(form-mdctrl-title) { + @include flex(row, space-between, center); + } + + @include b(form-mdctrl-remove-btn) { + color: getCssVar('color', 'danger'); + text-align: right; + cursor: pointer; + box-shadow: none; + } + + @include b(form-mdctrl-add-btn) { + color: getCssVar('color', 'primary'); + cursor: pointer; + box-shadow: none; + } + } +} diff --git a/src/control/form/form-detail/form-mdctrl/form-mdctrl.state.ts b/src/control/form/form-detail/form-mdctrl/form-mdctrl.state.ts new file mode 100644 index 000000000..30613bc2b --- /dev/null +++ b/src/control/form/form-detail/form-mdctrl/form-mdctrl.state.ts @@ -0,0 +1,16 @@ +import { FormDetailState } from '../form-detail'; + +/** + * 表单多数据部件状态 + * @return {*} + * @author: zhujiamin + * @Date: 2023-01-04 10:26:34 + */ +export class FormMDCtrlState extends FormDetailState { + /** + * 多数据内容数据 + * + * @type {Array} + */ + contentCtrlData: Array = []; +} diff --git a/src/control/form/form-detail/form-mdctrl/form-mdctrl.tsx b/src/control/form/form-detail/form-mdctrl/form-mdctrl.tsx new file mode 100644 index 000000000..41ff9971c --- /dev/null +++ b/src/control/form/form-detail/form-mdctrl/form-mdctrl.tsx @@ -0,0 +1,111 @@ +/* eslint-disable prefer-const */ +import { defineComponent, h, PropType, resolveComponent, watch } from 'vue'; +import { useController, useNamespace } from '@ibiz-template/vue3-util'; +import './form-mdctrl.scss'; +import { IDEFormMDCtrl } from '@ibiz/model-core'; +import { EventBase } from '@ibiz-template/runtime'; +import { FormMDCtrlController } from './form-mdctrl.controller'; + +export const FormMDCtrl = defineComponent({ + name: 'IBizFormMDCtrl', + props: { + modelData: { + type: Object as PropType, + required: true, + }, + controller: { + type: FormMDCtrlController, + required: true, + }, + }, + setup(props) { + const ns = useNamespace('form-mdctrl'); + + useController(props.controller); + + const c = props.controller; + + watch( + () => c.form.state.isLoaded, + (n, o) => { + if (n !== o && n === true) { + c.loadData(); + } + }, + ); + + return { ns, c }; + }, + render() { + const renderFormContent = () => { + return ( + this.c.state.contentCtrlData.length > 0 && + this.c.state.contentCtrlData.map((data: IData, index: number) => { + let formComponent = null; + const { formModel } = this.c; + if (formModel && this.c.providers[formModel.id!]) { + const tempContext = this.c.form.context.clone(); + formComponent = h( + resolveComponent(this.c.providers[formModel.id!].component), + { + modelData: formModel, + context: tempContext, + params: this.c.form.params, + isSimple: true, + data, + onFormDataChange: (arg: EventBase) => + this.c.onFormDataChange(arg, index), + }, + ); + } + return ( +
+ {formComponent} +
+ this.c.handleRemove(data, index)} + > + {{ + reference: () => { + return ( + + 删除 + + ); + }, + }} + +
+
+ ); + }) + ); + }; + + const renderMainContent = () => { + return ( +
+ {[ +
+ {this.modelData.caption} + this.c.handleAdd()} + > + 添加 + +
, + renderFormContent(), + ]} +
+ ); + }; + + return
{renderMainContent()}
; + }, +}); + +export default FormMDCtrl; diff --git a/src/control/form/form-detail/form-mdctrl/index.ts b/src/control/form/form-detail/form-mdctrl/index.ts new file mode 100644 index 000000000..5ced077c0 --- /dev/null +++ b/src/control/form/form-detail/form-mdctrl/index.ts @@ -0,0 +1,17 @@ +import { registerFormDetailProvider } from '@ibiz-template/runtime'; +import { withInstall } from '@ibiz-template/vue3-util'; +import { App } from 'vue'; +import FormMDCtrl from './form-mdctrl'; +import { FormMDCtrlProvider } from './form-mdctrl.provider'; + +export * from './form-mdctrl.provider'; +export * from './form-mdctrl.state'; +export * from './form-mdctrl.controller'; + +export const IBizFormMDCtrl = withInstall(FormMDCtrl, function (v: App) { + v.component(FormMDCtrl.name, FormMDCtrl); + // 表单按钮 + registerFormDetailProvider('MDCTRL', () => new FormMDCtrlProvider()); +}); + +export default IBizFormMDCtrl; diff --git a/src/control/form/form-detail/index.ts b/src/control/form/form-detail/index.ts index 6f750b617..737e972a9 100644 --- a/src/control/form/form-detail/index.ts +++ b/src/control/form/form-detail/index.ts @@ -4,3 +4,4 @@ export * from './form-item/index'; export * from './form-page/index'; export * from './form-button/index'; export * from './form-druipart/index'; +export * from './form-mdctrl/index'; diff --git a/src/control/form/form/form.controller.ts b/src/control/form/form/form.controller.ts index 1fe55b953..a3a74d799 100644 --- a/src/control/form/form/form.controller.ts +++ b/src/control/form/form/form.controller.ts @@ -2,6 +2,7 @@ import { RuntimeError, debounceAndAsyncMerge } from '@ibiz-template/core'; import { ControlController, + ControllerEvent, ControlVO, FormNotifyState, getFormDetailProvider, @@ -33,6 +34,10 @@ export abstract class FormController< extends ControlController implements IFormController { + protected get _evt(): ControllerEvent { + return this.evt; + } + /** * 所有表单项成员的控制器 * @@ -66,9 +71,9 @@ export abstract class FormController< * @author chitanda * @date 2023-01-04 10:01:46 * @readonly - * @type {ControlVO} + * @type {IData} */ - get data(): ControlVO { + get data(): IData { return this.state.data; } @@ -233,6 +238,11 @@ export abstract class FormController< // 设置正在处理状态 this.state.processing = true; + + // 如果是简易模式需要直接抛出去 + if (this.state.isSimple) { + await this._evt.emit('onFormDataChange', undefined); + } try { await this.dataChangeNotify([name]); } finally { diff --git a/src/control/form/form/index.ts b/src/control/form/form/index.ts index cdf0265ad..a08726135 100644 --- a/src/control/form/form/index.ts +++ b/src/control/form/form/index.ts @@ -7,6 +7,7 @@ import { IBizFormGroupPanel, IBizFormItem, IBizFormPage, + IBizFormMDCtrl, } from '../form-detail'; export * from './form.controller'; @@ -18,6 +19,7 @@ export const IBizFormControl = withInstall(FormControl, function (v: App) { v.use(IBizFormGroupPanel); v.use(IBizFormButton); v.use(IBizFormDRUIPart); + v.use(IBizFormMDCtrl); // 表单直接内容 // registerFormDetailProvider('RAWITEM', new FormRawItemProvider()); -- Gitee From 34e70b4493fd03e67ff041af4ea17783f96d89e0 Mon Sep 17 00:00:00 2001 From: zhujiamin <1147570162@qq.com> Date: Tue, 30 May 2023 18:08:19 +0800 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20=E8=A7=A3=E5=86=B3=E7=BC=96?= =?UTF-8?q?=E8=BE=91=E5=99=A8=E4=B8=80=E7=B3=BB=E5=88=97=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E4=BB=A5=E5=8F=8A=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/app-rawitem/app-rawitem.tsx | 181 ------------------ .../form-item-container.scss | 15 +- .../ibiz-autocomplete/ibiz-autocomplete.scss | 4 + .../ibiz-autocomplete/ibiz-autocomplete.tsx | 1 + .../ibiz-picker-embed-view.tsx | 2 +- .../ibiz-picker-select-view.tsx | 2 +- .../data-picker/ibiz-picker/ibiz-picker.tsx | 9 +- .../data-picker/picker-editor.controller.ts | 3 +- .../list-box/ibiz-list-box/ibiz-list-box.scss | 2 + src/editor/slider/ibiz-slider/ibiz-slider.tsx | 8 +- 10 files changed, 25 insertions(+), 202 deletions(-) delete mode 100644 src/common/app-rawitem/app-rawitem.tsx diff --git a/src/common/app-rawitem/app-rawitem.tsx b/src/common/app-rawitem/app-rawitem.tsx deleted file mode 100644 index f7e311dd7..000000000 --- a/src/common/app-rawitem/app-rawitem.tsx +++ /dev/null @@ -1,181 +0,0 @@ -import { useNamespace } from '@ibiz-template/vue3-util'; -import { defineComponent, ref } from 'vue'; -import { createUUID } from 'qx-util'; - -export const AppRawItem = defineComponent({ - name: 'AppRawItem', - props: { - type: { - type: String, - required: true, - }, - content: { - type: [String, Object], - }, - }, - setup(props) { - const ns = useNamespace('rawitem'); - - // 视频类型内容参数 - const playerParams = ref({ - id: createUUID(), - path: '', - mute: true, - autoplay: true, - replay: false, - showcontrols: true, - }); - - // 分割线类型参数 - const dividerParams = ref({ - contentPosition: 'center', - html: '', - }); - - // 类型参数 - const alertParams = ref({ - type: 'info', - title: '', - closeabled: true, - showIcon: false, - }); - - // 文本类型显示值 - const rawItemText = ref(''); - - if ( - [ - 'TEXT', - 'HEADING1', - 'HEADING2', - 'HEADING3', - 'HEADING4', - 'HEADING5', - 'HEADING6', - 'PARAGRAPH', - 'HTML', - ].includes(props.type) - ) { - if (props.content && typeof props.content === 'string') { - rawItemText.value = props.content; - rawItemText.value = rawItemText.value.replaceAll('<', '<'); - rawItemText.value = rawItemText.value.replaceAll('>', '>'); - rawItemText.value = rawItemText.value.replaceAll('&nbsp;', ' '); - rawItemText.value = rawItemText.value.replaceAll(' ', ' '); - } - } - - if (['VIDEO', 'DIVIDER', 'INFO', 'WARNING', 'ERROR'].includes(props.type)) { - if (props.content) { - let rawConfig = {}; - try { - if (typeof props.content === 'string') { - // eslint-disable-next-line no-new-func - const func = new Function(`return (${props.content});`); - rawConfig = func(); - switch (props.type) { - case 'VIDEO': - Object.assign(playerParams.value, rawConfig); - break; - case 'DIVIDER': - Object.assign(dividerParams.value, rawConfig); - break; - case 'INFO': - case 'WARNING': - case 'ERROR': - alertParams.value.type = props.type.toLocaleLowerCase(); - Object.assign(alertParams.value, rawConfig); - break; - default: - break; - } - } - } catch { - ibiz.log.error(`${props.type}类型自定义参数配置错误`); - } - } - } - - return { ns, rawItemText, playerParams, dividerParams, alertParams }; - }, - render() { - if (this.type === 'IMAGE') { - return ( - - ); - } - if (this.type === 'TEXT') { - return {this.rawItemText}; - } - if (this.type === 'HEADING1') { - return

{this.rawItemText}

; - } - if (this.type === 'HEADING2') { - return

{this.rawItemText}

; - } - if (this.type === 'HEADING3') { - return

{this.rawItemText}

; - } - if (this.type === 'HEADING4') { - return

{this.rawItemText}

; - } - if (this.type === 'HEADING5') { - return
{this.rawItemText}
; - } - if (this.type === 'HEADING6') { - return
{this.rawItemText}
; - } - if (this.type === 'PARAGRAPH') { - return

{this.rawItemText}

; - } - if (this.type === 'HTML') { - return ( -
- ); - } - if (this.type === 'VIDEO') { - return ( -
- -
- ); - } - if (this.type === 'DIVIDER') { - return ( - - - - ); - } - if ( - this.type === 'INFO' || - this.type === 'WARNING' || - this.type === 'ERROR' - ) { - return ( - - ); - } - if (['MARKDOWN', 'PLACEHOLDER'].includes(this.type)) { - return
{this.type}类型暂未支持
; - } - return null; - }, -}); diff --git a/src/control/form/form-detail/form-item/form-item-container/form-item-container.scss b/src/control/form/form-detail/form-item/form-item-container/form-item-container.scss index 3ddbf9fc8..fbd76afa8 100644 --- a/src/control/form/form-detail/form-item/form-item-container/form-item-container.scss +++ b/src/control/form/form-detail/form-item/form-item-container/form-item-container.scss @@ -10,18 +10,14 @@ padding-top: calc( ( - getCssVar('form-item-container', 'line-height') - getCssVar( - 'form-item', - 'font-size' - ) + getCssVar('form-item-container', 'line-height') - + getCssVar('form-item', 'font-size') ) / 2 ); padding-bottom: calc( ( - getCssVar('form-item-container', 'line-height') - getCssVar( - 'form-item', - 'font-size' - ) + getCssVar('form-item-container', 'line-height') - + getCssVar('form-item', 'font-size') ) / 2 ); line-height: getCssVar('form-item', 'font-size'); @@ -40,6 +36,7 @@ } @include e(editor) { + position: relative; flex-grow: 1; } } @@ -78,6 +75,8 @@ .#{bem('form-item-container', '', 'right')} { .#{bem('form-item-container-content')} { @include flex; + + height: 100%; } } diff --git a/src/editor/autocomplete/ibiz-autocomplete/ibiz-autocomplete.scss b/src/editor/autocomplete/ibiz-autocomplete/ibiz-autocomplete.scss index 94bb482ab..f283e9308 100644 --- a/src/editor/autocomplete/ibiz-autocomplete/ibiz-autocomplete.scss +++ b/src/editor/autocomplete/ibiz-autocomplete/ibiz-autocomplete.scss @@ -1,3 +1,7 @@ @include b(autocomplete) { width: 100%; + + @include e(transfer) { + width: 100%; + } } diff --git a/src/editor/autocomplete/ibiz-autocomplete/ibiz-autocomplete.tsx b/src/editor/autocomplete/ibiz-autocomplete/ibiz-autocomplete.tsx index ec77c44af..e838f0482 100644 --- a/src/editor/autocomplete/ibiz-autocomplete/ibiz-autocomplete.tsx +++ b/src/editor/autocomplete/ibiz-autocomplete/ibiz-autocomplete.tsx @@ -192,6 +192,7 @@ export const IBizAutoComplete = defineComponent({ placement='bottom' clearable={this.autoCompleteClearable} popper-class={this.ns.e('transfer')} + teleported={false} fetch-suggestions={this.onSearch} onClear={this.onClear} disabled={this.disabled || this.readonly} diff --git a/src/editor/data-picker/ibiz-picker-embed-view/ibiz-picker-embed-view.tsx b/src/editor/data-picker/ibiz-picker-embed-view/ibiz-picker-embed-view.tsx index af2c0bb15..1f08b7c4c 100644 --- a/src/editor/data-picker/ibiz-picker-embed-view/ibiz-picker-embed-view.tsx +++ b/src/editor/data-picker/ibiz-picker-embed-view/ibiz-picker-embed-view.tsx @@ -75,7 +75,7 @@ export const IBizPickerEmbedView = defineComponent({ const viewShell = resolveComponent('ViewShell'); return (
- {this.c.pickupView ? ( + {this.c.model.pickupAppViewId ? ( [
{h(viewShell, { diff --git a/src/editor/data-picker/ibiz-picker-select-view/ibiz-picker-select-view.tsx b/src/editor/data-picker/ibiz-picker-select-view/ibiz-picker-select-view.tsx index a84fb2c6b..6e4f91900 100644 --- a/src/editor/data-picker/ibiz-picker-select-view/ibiz-picker-select-view.tsx +++ b/src/editor/data-picker/ibiz-picker-select-view/ibiz-picker-select-view.tsx @@ -305,7 +305,7 @@ export const IBizPickerSelectView = defineComponent({ name='clear' > ), - this.c.linkView && ( + this.c.model.linkAppViewId && ( ) : null, - this.c.linkView ? ( + this.c.model.linkAppViewId ? ( {{ @@ -242,13 +241,13 @@ export const IBizPicker = defineComponent({ return; } return [ - this.c.pickupView ? ( + this.c.model.pickupAppViewId ? ( ) : null, - this.c.linkView ? ( + this.c.model.linkAppViewId ? ( { this.sort = this.getAcSort(); } } - await this.initPickupViewParams(); - await this.initLinkViewParams(); } /** @@ -231,6 +229,7 @@ export class PickerEditorController extends EditorController { data: IData, selectedData?: string, ): Promise { + await this.initPickupViewParams(); const { context, params } = this.handlePublicParams( data, this.context, diff --git a/src/editor/list-box/ibiz-list-box/ibiz-list-box.scss b/src/editor/list-box/ibiz-list-box/ibiz-list-box.scss index 050f0af53..7cef0d32d 100644 --- a/src/editor/list-box/ibiz-list-box/ibiz-list-box.scss +++ b/src/editor/list-box/ibiz-list-box/ibiz-list-box.scss @@ -1,4 +1,6 @@ @include b(list-box) { + height: 100%; + overflow: auto; @include b(list-box-radio) { @include flex(column, flex-start, flex-start); } diff --git a/src/editor/slider/ibiz-slider/ibiz-slider.tsx b/src/editor/slider/ibiz-slider/ibiz-slider.tsx index 834a411d4..73432686c 100644 --- a/src/editor/slider/ibiz-slider/ibiz-slider.tsx +++ b/src/editor/slider/ibiz-slider/ibiz-slider.tsx @@ -18,9 +18,9 @@ export const IBizSlider = defineComponent({ // 步长 let step = 1; // 设置滑动输入条允许的最大值 - let max = Infinity; + let max = 100; // 设置滑动输入条允许的最小值 - let min = -Infinity; + let min = 0; // 是否显示间断点 let showStops = false; // 是否开启选择范围 @@ -54,7 +54,7 @@ export const IBizSlider = defineComponent({ () => props.value, (newVal, oldVal) => { if (newVal !== oldVal) { - if (!newVal) { + if (newVal === null || newVal === undefined) { // 如果是范围给数组 if (range) { currentVal.value = [0, 1]; @@ -67,7 +67,7 @@ export const IBizSlider = defineComponent({ if (range) { currentVal.value = JSON.parse(newVal as string); } else { - currentVal.value = newVal as number; + currentVal.value = Number(newVal) as number; } } } -- Gitee From cd5072828bdd2f9aa5d3adcedf8c2bb85be58b64 Mon Sep 17 00:00:00 2001 From: zhujiamin <1147570162@qq.com> Date: Wed, 31 May 2023 18:28:53 +0800 Subject: [PATCH 4/5] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E7=BC=96?= =?UTF-8?q?=E8=BE=91=E5=99=A8=EF=BC=8C=E5=A2=9E=E5=8A=A0focus=EF=BC=8Cblur?= =?UTF-8?q?=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../autocomplete-editor.controller.ts | 105 ++++++--------- .../ibiz-autocomplete/ibiz-autocomplete.tsx | 27 ++-- .../ibiz-grid-checkbox-list.tsx | 29 ---- src/editor/check-box-list/index.ts | 1 - .../check-box/ibiz-checkbox/ibiz-checkbox.tsx | 10 +- .../data-picker/ibiz-mpicker/ibiz-mpicker.tsx | 21 ++- .../ibiz-picker-dropdown.tsx | 18 ++- .../ibiz-picker-embed-view.tsx | 80 +++++++---- .../ibiz-picker-link/ibiz-picker-link.tsx | 15 ++- .../ibiz-picker-select-view.tsx | 29 ++-- .../data-picker/ibiz-picker/ibiz-picker.tsx | 2 +- .../data-picker/picker-editor.controller.ts | 125 ++++++++---------- .../date-picker-editor.provider.ts | 2 +- .../ibiz-date-picker/ibiz-date-picker.tsx | 20 ++- .../ibiz-grid-date-picker.tsx | 29 ---- src/editor/date-picker/index.ts | 1 - .../ibiz-date-range-picker.tsx | 14 ++ .../ibiz-grid-dropdown/ibiz-grid-dropdown.tsx | 29 ---- src/editor/dropdown-list/index.ts | 1 - src/editor/index.ts | 32 +---- .../list-box/ibiz-list-box/ibiz-list-box.tsx | 12 +- .../list-box-picker-editor.controller.ts | 46 ++----- .../ibiz-number-range-picker.tsx | 10 +- .../ibiz-grid-radio/ibiz-grid-radio.tsx | 29 ---- .../ibiz-radio/ibiz-radio.tsx | 9 ++ src/editor/radio-button-list/index.ts | 1 - .../radio-button-list.provider.ts | 2 +- src/editor/rate/ibiz-rate/ibiz-rate.tsx | 10 +- src/editor/raw/ibiz-raw/ibiz-raw.tsx | 25 +++- src/editor/slider/ibiz-slider/ibiz-slider.tsx | 10 +- src/editor/span/grid-span/grid-span.tsx | 25 ---- src/editor/span/index.ts | 1 - src/editor/span/span-editor.provider.ts | 2 +- src/editor/span/span-link/span-link.tsx | 17 ++- src/editor/span/span/span.tsx | 16 ++- .../stepper/ibiz-stepper/ibiz-stepper.tsx | 14 ++ src/editor/switch/ibiz-switch/ibiz-switch.tsx | 10 +- .../ibiz-grid-input-number.tsx | 29 ---- .../ibiz-grid-input/ibiz-grid-input.tsx | 29 ---- .../text-box/ibiz-input-ip/ibiz-input-ip.tsx | 2 + .../ibiz-input-number/ibiz-input-number.tsx | 14 ++ src/editor/text-box/index.ts | 2 - src/view-engine/pickup-view.engine.ts | 21 +-- 43 files changed, 419 insertions(+), 507 deletions(-) delete mode 100644 src/editor/check-box-list/ibiz-grid-checkbox-list/ibiz-grid-checkbox-list.tsx delete mode 100644 src/editor/date-picker/ibiz-grid-date-picker/ibiz-grid-date-picker.tsx delete mode 100644 src/editor/dropdown-list/ibiz-grid-dropdown/ibiz-grid-dropdown.tsx delete mode 100644 src/editor/radio-button-list/ibiz-grid-radio/ibiz-grid-radio.tsx delete mode 100644 src/editor/span/grid-span/grid-span.tsx delete mode 100644 src/editor/text-box/ibiz-grid-input-number/ibiz-grid-input-number.tsx delete mode 100644 src/editor/text-box/ibiz-grid-input/ibiz-grid-input.tsx diff --git a/src/editor/autocomplete/autocomplete-editor.controller.ts b/src/editor/autocomplete/autocomplete-editor.controller.ts index 945f9b92b..7e88cc17d 100644 --- a/src/editor/autocomplete/autocomplete-editor.controller.ts +++ b/src/editor/autocomplete/autocomplete-editor.controller.ts @@ -1,7 +1,6 @@ import { IHttpResponse, RuntimeModelError } from '@ibiz-template/core'; -import { EditorController } from '@ibiz-template/runtime'; +import { EditorController, getDeACMode } from '@ibiz-template/runtime'; import { - IAppDataEntity, IAppDEACMode, IAutoComplete, IDEACModeDataItem, @@ -32,11 +31,6 @@ export class AutoCompleteEditorController extends EditorController { super.onInit(); if (this.model.appDataEntityId) { - this.appDataEntity = await ibiz.hub.getAppDataEntity( - this.model.appDataEntityId, - this.context.srfappid, - )!; - if (this.appDataEntity) { - this.keyName = this.appDataEntity.keyAppDEFieldId!; - this.textName = this.appDataEntity.majorAppDEFieldId!; - this.getAcParams(); - this.sort = this.getAcSort(); - } - } - } - - /** - * 获取Ac参数 - */ - public getAcParams() { - if (this.appDataEntity?.codeName) { - this.serviceName = this.appDataEntity.codeName; - } - if (this.model.appDEDataSetId) { - this.interfaceName = this.model.appDEDataSetId; - } - if (this.appDataEntity?.appDEACModes) { - this.deACMode = this.appDataEntity.appDEACModes[0]; - if (this.deACMode.textAppDEFieldId) { - this.textName = this.deACMode.textAppDEFieldId; - } - if (this.deACMode.valueAppDEFieldId) { - this.keyName = this.deACMode.valueAppDEFieldId; + if (this.model.appDEDataSetId) { + this.interfaceName = this.model.appDEDataSetId; } - if (this.deACMode.deacmodeDataItems) { - this.deACMode.deacmodeDataItems.forEach(dataItem => { - if (dataItem.id !== 'value' && dataItem.id !== 'text') { - this.dataItems.push(dataItem); + if (this.model.appDEACModeId) { + this.deACMode = await getDeACMode( + this.model.appDEACModeId, + this.model.appDataEntityId, + this.context.srfappid, + ); + if (this.deACMode) { + // 自填模式相关 + const { minorSortAppDEFieldId, minorSortDir } = this.deACMode; + if (minorSortAppDEFieldId && minorSortDir) { + this.sort = `${minorSortAppDEFieldId.toLowerCase()},${minorSortDir.toLowerCase()}`; } - }); - } - } - } - - /** - * 获取自填模式sort排序 - */ - public getAcSort() { - if (this.deACMode) { - const { minorSortAppDEFieldId, minorSortDir } = this.deACMode; - if (minorSortAppDEFieldId && minorSortDir) { - return `${minorSortAppDEFieldId.toLowerCase()},${minorSortDir.toLowerCase()}`; + if (this.deACMode.textAppDEFieldId) { + this.textName = this.deACMode.textAppDEFieldId; + } + if (this.deACMode.valueAppDEFieldId) { + this.keyName = this.deACMode.valueAppDEFieldId; + } + if (this.deACMode.deacmodeDataItems) { + this.dataItems = []; + this.deACMode.deacmodeDataItems.forEach( + (dataItem: IDEACModeDataItem) => { + if (dataItem.id !== 'value' && dataItem.id !== 'text') { + this.dataItems.push(dataItem); + } + }, + ); + } + } } } - return undefined; } /** @@ -141,10 +112,14 @@ export class AutoCompleteEditorController extends EditorController; } throw new RuntimeModelError(this.model, '请配置实体和实体数据集'); diff --git a/src/editor/autocomplete/ibiz-autocomplete/ibiz-autocomplete.tsx b/src/editor/autocomplete/ibiz-autocomplete/ibiz-autocomplete.tsx index e838f0482..3ebaaa121 100644 --- a/src/editor/autocomplete/ibiz-autocomplete/ibiz-autocomplete.tsx +++ b/src/editor/autocomplete/ibiz-autocomplete/ibiz-autocomplete.tsx @@ -1,4 +1,4 @@ -import { computed, defineComponent, onMounted, Ref, ref, watch } from 'vue'; +import { computed, defineComponent, Ref, ref, watch } from 'vue'; import { getAutoCompleteProps, getEditorEmits, @@ -85,7 +85,7 @@ export const IBizAutoComplete = defineComponent({ // 搜索 const onSearch = async (query: string, cb?: Function) => { - if (c.appDataEntity) { + if (c.model.appDataEntityId) { const trimQuery = query.trim(); const res = await c.getServiceData(trimQuery, props.data); if (res) { @@ -112,22 +112,14 @@ export const IBizAutoComplete = defineComponent({ }; // 聚焦 - const onFocus = (e: IData) => { - const query = isShowAll.value ? '' : e.target.value; - onSearch(query); + const onFocus = () => { + emit('focus'); }; - onMounted(() => { - // 监听autocomplete的activated - watch( - () => autoCompleteRef.value?.activated, - newVal => { - if (typeof newVal === 'boolean') { - emit('operate', newVal); - } - }, - ); - }); + // 失焦 + const onBlur = () => { + emit('blur'); + }; // 输入框focus时是否显示建议 const triggerOnFocus = computed(() => { @@ -175,6 +167,7 @@ export const IBizAutoComplete = defineComponent({ onSearch, onClear, onFocus, + onBlur, onACSelect, items, handleInput, @@ -198,6 +191,8 @@ export const IBizAutoComplete = defineComponent({ disabled={this.disabled || this.readonly} onSelect={this.onACSelect} onInput={this.handleInput} + onFocus={this.onFocus} + onBlur={this.onBlur} > {{ default: ({ item }: { item: IData }) => { diff --git a/src/editor/check-box-list/ibiz-grid-checkbox-list/ibiz-grid-checkbox-list.tsx b/src/editor/check-box-list/ibiz-grid-checkbox-list/ibiz-grid-checkbox-list.tsx deleted file mode 100644 index ac2d3c957..000000000 --- a/src/editor/check-box-list/ibiz-grid-checkbox-list/ibiz-grid-checkbox-list.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { defineComponent, h, resolveComponent } from 'vue'; -import { - getGridEditorEmits, - getGridInputProps, - useNamespace, -} from '@ibiz-template/vue3-util'; -import { CheckBoxListEditorController } from '../checkbox-list-editor.controller'; - -export const IBizGridCheckboxList = defineComponent({ - name: 'IBizGridCheckboxList', - props: getGridInputProps(), - emits: getGridEditorEmits(), - setup() { - const ns = useNamespace('grid-checkbox-list'); - - return { - ns, - }; - }, - render() { - return ( -
- {h(resolveComponent('IBizCheckboxList'), { - ...this.$props, - })} -
- ); - }, -}); diff --git a/src/editor/check-box-list/index.ts b/src/editor/check-box-list/index.ts index 418a6ccd8..adc5fcf84 100644 --- a/src/editor/check-box-list/index.ts +++ b/src/editor/check-box-list/index.ts @@ -1,4 +1,3 @@ export { IBizCheckboxList } from './ibiz-checkbox-list/ibiz-checkbox-list'; -export { IBizGridCheckboxList } from './ibiz-grid-checkbox-list/ibiz-grid-checkbox-list'; export * from './checkbox-list-editor.controller'; export * from './checkbox-list-editor.provider'; diff --git a/src/editor/check-box/ibiz-checkbox/ibiz-checkbox.tsx b/src/editor/check-box/ibiz-checkbox/ibiz-checkbox.tsx index d60d2e853..26b27dd8f 100644 --- a/src/editor/check-box/ibiz-checkbox/ibiz-checkbox.tsx +++ b/src/editor/check-box/ibiz-checkbox/ibiz-checkbox.tsx @@ -2,6 +2,7 @@ import { computed, defineComponent } from 'vue'; import { getCheckboxProps, getEditorEmits, + useFocusAndBlur, useNamespace, } from '@ibiz-template/vue3-util'; import { CheckBoxEditorController } from '../check-box-editor.controller'; @@ -47,15 +48,22 @@ export const IBizCheckbox = defineComponent({ }, }); + // 聚焦失焦事件 + const { componentRef: editorRef } = useFocusAndBlur( + () => emit('focus'), + () => emit('blur'), + ); + return { ns, editorModel, currentVal, + editorRef, }; }, render() { return ( -
+
{ - if (c.appDataEntity) { + if (c.model.appDataEntityId) { loading.value = true; try { const trimQuery = query.trim(); @@ -141,7 +141,6 @@ export const IBizMPicker = defineComponent({ // 下拉打开 const onOpenChange = (flag: boolean) => { open.value = flag; - emit('operate', flag); if (open.value) { items.value = []; onSearch(''); @@ -156,6 +155,17 @@ export const IBizMPicker = defineComponent({ }) .join(','); }); + + // 聚焦 + const onFocus = () => { + emit('focus'); + }; + + // 失焦 + const onBlur = () => { + emit('blur'); + }; + return { ns, c, @@ -167,6 +177,8 @@ export const IBizMPicker = defineComponent({ onOpenChange, onSelect, openPickUpView, + onFocus, + onBlur, }; }, render() { @@ -177,6 +189,7 @@ export const IBizMPicker = defineComponent({ this.disabled ? this.ns.m('disabled') : '', this.readonly ? this.ns.m('readonly') : '', ]} + ref='editorRef' > {this.readonly && this.valueText} {!this.readonly && ( @@ -191,6 +204,8 @@ export const IBizMPicker = defineComponent({ onVisibleChange={this.onOpenChange} onChange={this.onSelect} disabled={this.disabled} + onFocus={this.onFocus} + onBlur={this.onBlur} > {this.items.map((item, index) => { return ( @@ -206,7 +221,7 @@ export const IBizMPicker = defineComponent({ {!this.readonly && (
- {this.c.pickupView ? ( + {this.c.model.pickupAppViewId ? ( { - if (c.appDataEntity && loading.value === false) { + if (c.model.appDataEntityId && loading.value === false) { loading.value = true; try { const trimQuery = query.trim(); @@ -120,7 +120,6 @@ export const IBizPickerDropDown = defineComponent({ // 下拉打开 const onOpenChange = (isOpen: boolean) => { - emit('operate', isOpen); if (isOpen) { items.value = []; onSearch(''); @@ -141,6 +140,17 @@ export const IBizPickerDropDown = defineComponent({ } emit('change', null); }; + + // 聚焦 + const onFocus = () => { + emit('focus'); + }; + + // 失焦 + const onBlur = () => { + emit('blur'); + }; + return { ns, c, @@ -151,6 +161,8 @@ export const IBizPickerDropDown = defineComponent({ onClear, onSelect, onSearch, + onFocus, + onBlur, }; }, render() { @@ -176,6 +188,8 @@ export const IBizPickerDropDown = defineComponent({ onChange={this.onSelect} onClear={this.onClear} disabled={this.disabled} + onFocus={this.onFocus} + onBlur={this.onBlur} > {this.items.map((item, index) => { return ( diff --git a/src/editor/data-picker/ibiz-picker-embed-view/ibiz-picker-embed-view.tsx b/src/editor/data-picker/ibiz-picker-embed-view/ibiz-picker-embed-view.tsx index 1f08b7c4c..5ffd71fa8 100644 --- a/src/editor/data-picker/ibiz-picker-embed-view/ibiz-picker-embed-view.tsx +++ b/src/editor/data-picker/ibiz-picker-embed-view/ibiz-picker-embed-view.tsx @@ -1,7 +1,15 @@ -import { defineComponent, ref, resolveComponent, watch, h } from 'vue'; +import { + defineComponent, + ref, + resolveComponent, + watch, + h, + computed, +} from 'vue'; import { getDataPickerProps, getEditorEmits, + useFocusAndBlur, useNamespace, } from '@ibiz-template/vue3-util'; import './ibiz-picker-embed-view.scss'; @@ -69,36 +77,52 @@ export const IBizPickerEmbedView = defineComponent({ onViewDataChange(event.data); }; - return { ns, c, context, params, onSelectionChange }; + // 聚焦失焦事件 + const { componentRef: editorRef } = useFocusAndBlur( + () => emit('focus'), + () => emit('blur'), + ); + + const pickupViewModel = computed(() => { + return c.pickupView; + }); + + return { + ns, + c, + context, + params, + onSelectionChange, + editorRef, + pickupViewModel, + }; }, render() { - const viewShell = resolveComponent('ViewShell'); + const viewShell = resolveComponent('IBizViewShell'); return ( -
- {this.c.model.pickupAppViewId ? ( - [ -
- {h(viewShell, { - context: this.context, - params: this.params, - modal: { mode: ViewMode.EMBED }, - modelData: this.c.pickupView, - onSelectionChange: this.onSelectionChange, - })} -
, -
- {this.$props.value ? ( - this.$props.value.split(',').map(item => { - return {item}; ; - }) - ) : ( - {this.c.placeHolder} - )} -
, - ] - ) : ( -
{this.c.placeHolder}
- )} +
+ {this.pickupViewModel + ? [ +
+ {h(viewShell, { + context: this.context, + params: this.params, + modal: { mode: ViewMode.EMBED }, + modelData: this.c.pickupView, + onSelectionChange: this.onSelectionChange, + })} +
, +
+ {this.$props.value ? ( + this.$props.value.split(',').map(item => { + return {item}; ; + }) + ) : ( + {this.c.placeHolder} + )} +
, + ] + : null}
); }, diff --git a/src/editor/data-picker/ibiz-picker-link/ibiz-picker-link.tsx b/src/editor/data-picker/ibiz-picker-link/ibiz-picker-link.tsx index b015134d4..0115f8121 100644 --- a/src/editor/data-picker/ibiz-picker-link/ibiz-picker-link.tsx +++ b/src/editor/data-picker/ibiz-picker-link/ibiz-picker-link.tsx @@ -2,6 +2,7 @@ import { defineComponent, ref, Ref, watch } from 'vue'; import { getDataPickerProps, getEditorEmits, + useFocusAndBlur, useNamespace, } from '@ibiz-template/vue3-util'; import './ibiz-picker-link.scss'; @@ -47,11 +48,21 @@ export const IBizPickerLink = defineComponent({ handleOpenViewClose(res); } }; - return { ns, openLinkView, curValue }; + + // 聚焦失焦事件 + const { componentRef: editorRef } = useFocusAndBlur( + () => emit('focus'), + () => emit('blur'), + ); + + return { ns, openLinkView, curValue, editorRef }; }, render() { return ( -
+ ); diff --git a/src/editor/data-picker/ibiz-picker-select-view/ibiz-picker-select-view.tsx b/src/editor/data-picker/ibiz-picker-select-view/ibiz-picker-select-view.tsx index 6e4f91900..757dcc636 100644 --- a/src/editor/data-picker/ibiz-picker-select-view/ibiz-picker-select-view.tsx +++ b/src/editor/data-picker/ibiz-picker-select-view/ibiz-picker-select-view.tsx @@ -10,6 +10,7 @@ import { import { getDataPickerProps, getEditorEmits, + useFocusAndBlur, useNamespace, } from '@ibiz-template/vue3-util'; import './ibiz-picker-select-view.scss'; @@ -256,6 +257,12 @@ export const IBizPickerSelectView = defineComponent({ onViewDataChange(event.data); }; + // 聚焦失焦事件 + const { componentRef: editorRef } = useFocusAndBlur( + () => emit('focus'), + () => emit('blur'), + ); + return { ns, c, @@ -276,11 +283,12 @@ export const IBizPickerSelectView = defineComponent({ onSelectChange, remoteMethod, onSelectionChange, + editorRef, }; }, render() { return ( -
+
{{ default: () => { @@ -342,17 +350,18 @@ export const IBizPickerSelectView = defineComponent({ ); }, dropdown: () => { - const viewShell = resolveComponent('ViewShell'); + const viewShell = resolveComponent('IBizViewShell'); return ( - {h(viewShell, { - context: this.context, - params: this.params, - modal: { mode: ViewMode.EMBED }, - modelData: this.c.pickupView, - style: { height: '100%', width: this.pickViewWidth }, - onSelectionChange: this.onSelectionChange, - })} + {this.c.pickupView && + h(viewShell, { + context: this.context, + params: this.params, + modal: { mode: ViewMode.EMBED }, + modelData: this.c.pickupView, + style: { height: '100%', width: this.pickViewWidth }, + onSelectionChange: this.onSelectionChange, + })} ); }, diff --git a/src/editor/data-picker/ibiz-picker/ibiz-picker.tsx b/src/editor/data-picker/ibiz-picker/ibiz-picker.tsx index d5a27770b..58d9809f1 100644 --- a/src/editor/data-picker/ibiz-picker/ibiz-picker.tsx +++ b/src/editor/data-picker/ibiz-picker/ibiz-picker.tsx @@ -97,7 +97,7 @@ export const IBizPicker = defineComponent({ // 搜索 const onSearch = async (query: string, cb?: Function) => { - if (c.appDataEntity) { + if (c.model.appDataEntityId) { const trimQuery = query.trim(); const res = await c.getServiceData(trimQuery, props.data); if (res) { diff --git a/src/editor/data-picker/picker-editor.controller.ts b/src/editor/data-picker/picker-editor.controller.ts index b62d69793..fbd026017 100644 --- a/src/editor/data-picker/picker-editor.controller.ts +++ b/src/editor/data-picker/picker-editor.controller.ts @@ -1,7 +1,10 @@ import { IHttpResponse, RuntimeModelError } from '@ibiz-template/core'; -import { EditorController, OpenAppViewCommand } from '@ibiz-template/runtime'; import { - IAppDataEntity, + EditorController, + OpenAppViewCommand, + getDeACMode, +} from '@ibiz-template/runtime'; +import { IAppDEACMode, IAppView, IDEACModeDataItem, @@ -50,11 +53,6 @@ export class PickerEditorController extends EditorController { */ public textName: string = 'srfmajortext'; - /** - * 实体codeName - */ - public serviceName: string = ''; - /** * 数据集codeName */ @@ -75,15 +73,10 @@ export class PickerEditorController extends EditorController { */ public noButton: boolean = false; - /** - * 编辑器实体 - */ - public appDataEntity: IAppDataEntity | null = null; - /** * 实体自填模式模型 */ - public deACMode: IAppDEACMode | null = null; + public deACMode: IAppDEACMode | undefined = undefined; /** * 自填数据项集合(已排除了value和text) @@ -95,17 +88,52 @@ export class PickerEditorController extends EditorController { this.initParams(); this.valueItem = this.model.valueItemName?.toLowerCase() || ''; if (this.model.appDataEntityId) { - this.appDataEntity = await ibiz.hub.getAppDataEntity( - this.model.appDataEntityId, - this.context.srfappid, - )!; - if (this.appDataEntity) { - this.keyName = this.appDataEntity.keyAppDEFieldId!; - this.textName = this.appDataEntity.majorAppDEFieldId!; - this.getAcParams(); - this.sort = this.getAcSort(); + if (this.model.appDEDataSetId) { + this.interfaceName = this.model.appDEDataSetId; + } + if (this.model.appDEACModeId) { + this.deACMode = await getDeACMode( + this.model.appDEACModeId, + this.model.appDataEntityId, + this.context.srfappid, + ); + if (this.deACMode) { + // 自填模式相关 + const { minorSortAppDEFieldId, minorSortDir } = this.deACMode; + if (minorSortAppDEFieldId && minorSortDir) { + this.sort = `${minorSortAppDEFieldId.toLowerCase()},${minorSortDir.toLowerCase()}`; + } + if (this.deACMode.textAppDEFieldId) { + this.textName = this.deACMode.textAppDEFieldId; + } + if (this.deACMode.valueAppDEFieldId) { + this.keyName = this.deACMode.valueAppDEFieldId; + } + if (this.deACMode.deacmodeDataItems) { + this.dataItems = []; + this.deACMode.deacmodeDataItems.forEach( + (dataItem: IDEACModeDataItem) => { + if (dataItem.id !== 'value' && dataItem.id !== 'text') { + this.dataItems.push(dataItem); + } + }, + ); + } + } } } + // 这三种嵌入选择视图的需要预先加载视图模型用于绘制 + const embedViewEditors = [ + 'PICKEREX_DROPDOWNVIEW', + 'PICKEREX_DROPDOWNVIEW_LINK', + 'PICKUPVIEW', + ]; + if ( + this.model.editorType && + embedViewEditors.includes(this.model.editorType) + ) { + this.initPickupViewParams(); + } } /** @@ -144,47 +172,6 @@ export class PickerEditorController extends EditorController { } } - /** - * 获取Ac参数 - */ - public getAcParams() { - if (this.appDataEntity?.codeName) { - this.serviceName = this.appDataEntity.codeName; - } - if (this.model.appDEDataSetId) { - this.interfaceName = this.model.appDEDataSetId; - } - if (this.appDataEntity?.appDEACModes) { - this.deACMode = this.appDataEntity.appDEACModes[0]; - if (this.deACMode.textAppDEFieldId) { - this.textName = this.deACMode.textAppDEFieldId; - } - if (this.deACMode.valueAppDEFieldId) { - this.keyName = this.deACMode.valueAppDEFieldId; - } - if (this.deACMode.deacmodeDataItems) { - this.deACMode.deacmodeDataItems.forEach(dataItem => { - if (dataItem.id !== 'value' && dataItem.id !== 'text') { - this.dataItems.push(dataItem); - } - }); - } - } - } - - /** - * 获取自填模式sort排序 - */ - public getAcSort() { - if (this.deACMode) { - const { minorSortAppDEFieldId, minorSortDir } = this.deACMode; - if (minorSortAppDEFieldId && minorSortDir) { - return `${minorSortAppDEFieldId.toLowerCase()},${minorSortDir.toLowerCase()}`; - } - } - return undefined; - } - /** * 加载实体数据集数据 * @@ -208,10 +195,14 @@ export class PickerEditorController extends EditorController { this.context, tempParams, ); - if (this.serviceName && this.interfaceName) { - const app = ibiz.hub.getApp(this.appDataEntity!.appId); - const deService = await app.deService.getService(this.serviceName); - const res = await deService.exec(this.interfaceName, context, params); + if (this.interfaceName) { + const app = ibiz.hub.getApp(this.context.srfappid); + const res = await app.deService.exec( + this.model.appDataEntityId!, + this.interfaceName, + context, + params, + ); return res as IHttpResponse; } throw new RuntimeModelError(this.model, '请配置实体和实体数据集'); diff --git a/src/editor/date-picker/date-picker-editor.provider.ts b/src/editor/date-picker/date-picker-editor.provider.ts index c03c9eca4..f46456852 100644 --- a/src/editor/date-picker/date-picker-editor.provider.ts +++ b/src/editor/date-picker/date-picker-editor.provider.ts @@ -18,7 +18,7 @@ import { DatePickerEditorController } from './date-picker-editor.controller'; export class DatePickerEditorProvider implements IEditorProvider { formEditor: string = 'IBizDatePicker'; - gridEditor: string = 'IBizGridDatePicker'; + gridEditor: string = 'IBizDatePicker'; async createController( editorModel: IDatePicker, diff --git a/src/editor/date-picker/ibiz-date-picker/ibiz-date-picker.tsx b/src/editor/date-picker/ibiz-date-picker/ibiz-date-picker.tsx index ff0bc69c8..a27b4f1a8 100644 --- a/src/editor/date-picker/ibiz-date-picker/ibiz-date-picker.tsx +++ b/src/editor/date-picker/ibiz-date-picker/ibiz-date-picker.tsx @@ -70,9 +70,7 @@ export const IBizDatePicker = defineComponent({ emit('change', date); }; - const onOpenChange = (isOpen: boolean) => { - emit('operate', isOpen); - }; + const onOpenChange = (_isOpen: boolean) => {}; const inputRef = ref(); @@ -85,6 +83,16 @@ export const IBizDatePicker = defineComponent({ }); } + // 聚焦 + const onFocus = () => { + emit('focus'); + }; + + // 失焦 + const onBlur = () => { + emit('blur'); + }; + return { ns, c, @@ -96,6 +104,8 @@ export const IBizDatePicker = defineComponent({ onOpenChange, inputRef, isTimePicker, + onFocus, + onBlur, }; }, render() { @@ -120,6 +130,8 @@ export const IBizDatePicker = defineComponent({ onVisibleChange={this.onOpenChange} onChange={this.handleChange} disabled={this.disabled} + onFocus={this.onFocus} + onBlur={this.onBlur} > ) : ( )}
diff --git a/src/editor/date-picker/ibiz-grid-date-picker/ibiz-grid-date-picker.tsx b/src/editor/date-picker/ibiz-grid-date-picker/ibiz-grid-date-picker.tsx deleted file mode 100644 index 707c356a2..000000000 --- a/src/editor/date-picker/ibiz-grid-date-picker/ibiz-grid-date-picker.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { defineComponent, h, resolveComponent } from 'vue'; -import { - getGridDatePickerProps, - getGridEditorEmits, - useNamespace, -} from '@ibiz-template/vue3-util'; -import { DatePickerEditorController } from '../date-picker-editor.controller'; - -export const IBizGridDatePicker = defineComponent({ - name: 'IBizGridDatePicker', - props: getGridDatePickerProps(), - emits: getGridEditorEmits(), - setup() { - const ns = useNamespace('grid-date-picker'); - - return { - ns, - }; - }, - render() { - return ( -
- {h(resolveComponent('IBizDatePicker'), { - ...this.$props, - })} -
- ); - }, -}); diff --git a/src/editor/date-picker/index.ts b/src/editor/date-picker/index.ts index c66815835..d22c70857 100644 --- a/src/editor/date-picker/index.ts +++ b/src/editor/date-picker/index.ts @@ -1,4 +1,3 @@ export { IBizDatePicker } from './ibiz-date-picker/ibiz-date-picker'; -export { IBizGridDatePicker } from './ibiz-grid-date-picker/ibiz-grid-date-picker'; export * from './date-picker-editor.controller'; export * from './date-picker-editor.provider'; diff --git a/src/editor/date-range/ibiz-date-range-picker/ibiz-date-range-picker.tsx b/src/editor/date-range/ibiz-date-range-picker/ibiz-date-range-picker.tsx index 4f48650eb..02abd419d 100644 --- a/src/editor/date-range/ibiz-date-range-picker/ibiz-date-range-picker.tsx +++ b/src/editor/date-range/ibiz-date-range-picker/ibiz-date-range-picker.tsx @@ -113,6 +113,16 @@ export const IBizDateRangePicker = defineComponent({ }, }); + // 聚焦 + const onFocus = () => { + emit('focus'); + }; + + // 失焦 + const onBlur = () => { + emit('blur'); + }; + return { ns, c, @@ -125,6 +135,8 @@ export const IBizDateRangePicker = defineComponent({ endPlaceHolder, rangeSeparator, unlinkPanels, + onFocus, + onBlur, }; }, render() { @@ -142,6 +154,8 @@ export const IBizDateRangePicker = defineComponent({ start-placeholder={this.startPlaceHolder} end-placeholder={this.endPlaceHolder} unlink-panels={this.unlinkPanels} + onFocus={this.onFocus} + onBlur={this.onBlur} >
); diff --git a/src/editor/dropdown-list/ibiz-grid-dropdown/ibiz-grid-dropdown.tsx b/src/editor/dropdown-list/ibiz-grid-dropdown/ibiz-grid-dropdown.tsx deleted file mode 100644 index eb6b61e2a..000000000 --- a/src/editor/dropdown-list/ibiz-grid-dropdown/ibiz-grid-dropdown.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { defineComponent, h, resolveComponent } from 'vue'; -import { - getGridDropdownProps, - getGridEditorEmits, - useNamespace, -} from '@ibiz-template/vue3-util'; -import { DropDownListEditorController } from '../dropdown-list-editor.controller'; - -export const IBizGridDropdown = defineComponent({ - name: 'IBizGridDropdown', - props: getGridDropdownProps(), - emits: getGridEditorEmits(), - setup() { - const ns = useNamespace('grid-dropdown'); - - return { - ns, - }; - }, - render() { - return ( -
- {h(resolveComponent('IBizDropdown'), { - ...this.$props, - })} -
- ); - }, -}); diff --git a/src/editor/dropdown-list/index.ts b/src/editor/dropdown-list/index.ts index 9229b9c62..6d962698d 100644 --- a/src/editor/dropdown-list/index.ts +++ b/src/editor/dropdown-list/index.ts @@ -1,4 +1,3 @@ export { IBizDropdown } from './ibiz-dropdown/ibiz-dropdown'; -export { IBizGridDropdown } from './ibiz-grid-dropdown/ibiz-grid-dropdown'; export * from './dropdown-list-editor.controller'; export * from './dropdown-list-editor.provider'; diff --git a/src/editor/index.ts b/src/editor/index.ts index a9ebb02c3..5f885397b 100644 --- a/src/editor/index.ts +++ b/src/editor/index.ts @@ -6,31 +6,13 @@ import { IBizInput, IBizInputNumber, IBizInputIP, - IBizGridInput, - IBizGridInputNumber, TextBoxEditorProvider, } from './text-box'; -import { - IBizDropdown, - IBizGridDropdown, - DropDownListEditorProvider, -} from './dropdown-list'; +import { IBizDropdown, DropDownListEditorProvider } from './dropdown-list'; import { IBizCheckbox, CheckBoxEditorProvider } from './check-box'; -import { - IBizCheckboxList, - IBizGridCheckboxList, - CheckBoxListEditorProvider, -} from './check-box-list'; -import { - IBizRadio, - IBizGridRadio, - RadioButtonListEditorProvider, -} from './radio-button-list'; -import { - IBizDatePicker, - IBizGridDatePicker, - DatePickerEditorProvider, -} from './date-picker'; +import { IBizCheckboxList, CheckBoxListEditorProvider } from './check-box-list'; +import { IBizRadio, RadioButtonListEditorProvider } from './radio-button-list'; +import { IBizDatePicker, DatePickerEditorProvider } from './date-picker'; import { IBizRaw, RawEditorProvider } from './raw'; import { IBizStepper, StepperEditorProvider } from './stepper'; import { IBizRate, RateEditorProvider } from './rate'; @@ -68,17 +50,11 @@ export const IBizEditor = { v.component(IBizInput.name, IBizInput); v.component(IBizInputNumber.name, IBizInputNumber); v.component(IBizInputIP.name, IBizInputIP); - v.component(IBizGridInput.name, IBizGridInput); - v.component(IBizGridInputNumber.name, IBizGridInputNumber); v.component(IBizDropdown.name, IBizDropdown); - v.component(IBizGridDropdown.name, IBizGridDropdown); v.component(IBizCheckbox.name, IBizCheckbox); v.component(IBizCheckboxList.name, IBizCheckboxList); - v.component(IBizGridCheckboxList.name, IBizGridCheckboxList); v.component(IBizRadio.name, IBizRadio); - v.component(IBizGridRadio.name, IBizGridRadio); v.component(IBizDatePicker.name, IBizDatePicker); - v.component(IBizGridDatePicker.name, IBizGridDatePicker); v.component(IBizRaw.name, IBizRaw); v.component(IBizStepper.name, IBizStepper); v.component(IBizRate.name, IBizRate); diff --git a/src/editor/list-box/ibiz-list-box/ibiz-list-box.tsx b/src/editor/list-box/ibiz-list-box/ibiz-list-box.tsx index c8de0ab35..edd51544b 100644 --- a/src/editor/list-box/ibiz-list-box/ibiz-list-box.tsx +++ b/src/editor/list-box/ibiz-list-box/ibiz-list-box.tsx @@ -3,6 +3,7 @@ import { getListBoxProps, getEditorEmits, useNamespace, + useFocusAndBlur, } from '@ibiz-template/vue3-util'; import { isNil } from 'ramda'; import './ibiz-list-box.scss'; @@ -45,7 +46,7 @@ export const IBizListBox = defineComponent({ }); } else if (Object.is('LISTBOXPICKUP', editorType)) { const controller = c as ListBoxPickerEditorController; - if (controller.appDataEntity) { + if (controller.model.appDataEntityId) { const res = await controller.getServiceData(props.data); if (res) { items.value = res.data.map(item => ({ @@ -148,17 +149,24 @@ export const IBizListBox = defineComponent({ emit('change', _value); }; + // 聚焦失焦事件 + const { componentRef: editorRef } = useFocusAndBlur( + () => emit('focus'), + () => emit('blur'), + ); + return { ns, items, selectArray, onSelectArrayChange, multiple, + editorRef, }; }, render() { return ( -
+
{this.multiple ? ( { super.onInit(); if (this.model.editorType === 'LISTBOXPICKUP') { - this.appDataEntity = await ibiz.hub.getAppDataEntity( - this.model.appDataEntityId!, - this.context.srfappid, - ); - if (this.appDataEntity) { - this.keyName = this.appDataEntity.keyAppDEFieldId!; - this.textName = this.appDataEntity.majorAppDEFieldId!; - this.getAcParams(); + if (this.model.appDEDataSetId) { + this.interfaceName = this.model.appDEDataSetId; } } } - /** - * 获取Ac参数 - */ - public getAcParams() { - if (this.appDataEntity?.codeName) { - this.serviceName = this.appDataEntity.codeName; - } - if (this.model.appDEDataSetId) { - this.interfaceName = this.model.appDEDataSetId; - } - } - /** * 加载实体数据集数据 * @@ -76,10 +48,14 @@ export class ListBoxPickerEditorController extends EditorController; } throw new RuntimeModelError(this.model, '请配置实体和实体数据集'); diff --git a/src/editor/number-range/ibiz-number-range-picker/ibiz-number-range-picker.tsx b/src/editor/number-range/ibiz-number-range-picker/ibiz-number-range-picker.tsx index 311d2cf61..8a8e5031d 100644 --- a/src/editor/number-range/ibiz-number-range-picker/ibiz-number-range-picker.tsx +++ b/src/editor/number-range/ibiz-number-range-picker/ibiz-number-range-picker.tsx @@ -2,6 +2,7 @@ import { defineComponent, Ref, ref, watch } from 'vue'; import { getEditorEmits, getNumberRangeProps, + useFocusAndBlur, useNamespace, } from '@ibiz-template/vue3-util'; import './ibiz-number-range-picker.scss'; @@ -102,6 +103,12 @@ export const IBizNumberRangePicker = defineComponent({ } }; + // 聚焦失焦事件 + const { componentRef: editorRef } = useFocusAndBlur( + () => emit('focus'), + () => emit('blur'), + ); + return { ns, c, @@ -116,11 +123,12 @@ export const IBizNumberRangePicker = defineComponent({ startPlaceHolder, endPlaceHolder, rangeSeparator, + editorRef, }; }, render() { return ( -
+
(), - emits: getGridEditorEmits(), - setup() { - const ns = useNamespace('grid-radio'); - - return { - ns, - }; - }, - render() { - return ( -
- {h(resolveComponent('IBizRadio'), { - ...this.$props, - })} -
- ); - }, -}); diff --git a/src/editor/radio-button-list/ibiz-radio/ibiz-radio.tsx b/src/editor/radio-button-list/ibiz-radio/ibiz-radio.tsx index e05e059d4..2d6c1fccc 100644 --- a/src/editor/radio-button-list/ibiz-radio/ibiz-radio.tsx +++ b/src/editor/radio-button-list/ibiz-radio/ibiz-radio.tsx @@ -2,6 +2,7 @@ import { computed, defineComponent, ref, watch } from 'vue'; import { getEditorEmits, getRadioProps, + useFocusAndBlur, useNamespace, } from '@ibiz-template/vue3-util'; import './ibiz-radio.scss'; @@ -41,12 +42,19 @@ export const IBizRadio = defineComponent({ return items.value.find(item => item.value === props.value)?.text || ''; }); + // 聚焦失焦事件 + const { componentRef: editorRef } = useFocusAndBlur( + () => emit('focus'), + () => emit('blur'), + ); + return { ns, editorModel, items, valueText, onSelectValueChange, + editorRef, }; }, render() { @@ -57,6 +65,7 @@ export const IBizRadio = defineComponent({ this.disabled ? this.ns.m('disabled') : '', this.readonly ? this.ns.m('readonly') : '', ]} + ref='editorRef' > {this.readonly ? ( this.valueText diff --git a/src/editor/radio-button-list/index.ts b/src/editor/radio-button-list/index.ts index 03f19f896..1f78fb531 100644 --- a/src/editor/radio-button-list/index.ts +++ b/src/editor/radio-button-list/index.ts @@ -1,4 +1,3 @@ export { IBizRadio } from './ibiz-radio/ibiz-radio'; -export { IBizGridRadio } from './ibiz-grid-radio/ibiz-grid-radio'; export * from './radio-button-list.controller'; export * from './radio-button-list.provider'; diff --git a/src/editor/radio-button-list/radio-button-list.provider.ts b/src/editor/radio-button-list/radio-button-list.provider.ts index 9c7029066..2bcecbf00 100644 --- a/src/editor/radio-button-list/radio-button-list.provider.ts +++ b/src/editor/radio-button-list/radio-button-list.provider.ts @@ -18,7 +18,7 @@ import { RadioButtonListEditorController } from './radio-button-list.controller' export class RadioButtonListEditorProvider implements IEditorProvider { formEditor: string = 'IBizRadio'; - gridEditor: string = 'IBizGridRadio'; + gridEditor: string = 'IBizRadio'; async createController( editorModel: IRadioButtonList, diff --git a/src/editor/rate/ibiz-rate/ibiz-rate.tsx b/src/editor/rate/ibiz-rate/ibiz-rate.tsx index 9304eb83c..516474a7d 100644 --- a/src/editor/rate/ibiz-rate/ibiz-rate.tsx +++ b/src/editor/rate/ibiz-rate/ibiz-rate.tsx @@ -2,6 +2,7 @@ import { defineComponent, ref, watch } from 'vue'; import { getEditorEmits, getRateProps, + useFocusAndBlur, useNamespace, } from '@ibiz-template/vue3-util'; import { RateEditorController } from '../rate-editor.controller'; @@ -60,6 +61,12 @@ export const IBizRate = defineComponent({ emit('change', currentValue); }; + // 聚焦失焦事件 + const { componentRef: editorRef } = useFocusAndBlur( + () => emit('focus'), + () => emit('blur'), + ); + return { ns, currentVal, @@ -68,11 +75,12 @@ export const IBizRate = defineComponent({ showText, max, texts, + editorRef, }; }, render() { return ( -
+
= ref(''); + + watch( + () => props.value, + (newVal, oldVal) => { + if (newVal !== oldVal) { + content.value = newVal; + } + }, + ); // 类型 let type = 'TEXT'; @@ -39,11 +48,13 @@ export const IBizRaw = defineComponent({ this.readonly ? this.ns.m('readonly') : '', ]} > - + {this.content && ( + + )}
); }, diff --git a/src/editor/slider/ibiz-slider/ibiz-slider.tsx b/src/editor/slider/ibiz-slider/ibiz-slider.tsx index 73432686c..de40149cb 100644 --- a/src/editor/slider/ibiz-slider/ibiz-slider.tsx +++ b/src/editor/slider/ibiz-slider/ibiz-slider.tsx @@ -2,6 +2,7 @@ import { defineComponent, ref, watch } from 'vue'; import { getEditorEmits, getSliderProps, + useFocusAndBlur, useNamespace, } from '@ibiz-template/vue3-util'; import { SliderEditorController } from '../slider-editor.controller'; @@ -83,6 +84,12 @@ export const IBizSlider = defineComponent({ } }; + // 聚焦失焦事件 + const { componentRef: editorRef } = useFocusAndBlur( + () => emit('focus'), + () => emit('blur'), + ); + return { ns, currentVal, @@ -93,11 +100,12 @@ export const IBizSlider = defineComponent({ showStops, range, showInput, + editorRef, }; }, render() { return ( -
+
(), - setup() { - const ns = useNamespace('grid-span'); - return { ns }; - }, - render() { - return ( -
evt.stopPropagation()} - onClick={evt => evt.stopPropagation()} - > - {h(resolveComponent('IBizSpan'), { - ...this.$props, - })} -
- ); - }, -}); diff --git a/src/editor/span/index.ts b/src/editor/span/index.ts index e7a36a6e2..326161cef 100644 --- a/src/editor/span/index.ts +++ b/src/editor/span/index.ts @@ -1,5 +1,4 @@ export { IBizSpan } from './span/span'; -export { IBizGridSpan } from './grid-span/grid-span'; export { IBizSpanLink } from './span-link/span-link'; export * from './span-editor.controller'; export * from './span-editor.provider'; diff --git a/src/editor/span/span-editor.provider.ts b/src/editor/span/span-editor.provider.ts index e1cb9ba1b..b59384759 100644 --- a/src/editor/span/span-editor.provider.ts +++ b/src/editor/span/span-editor.provider.ts @@ -17,7 +17,7 @@ import { SpanEditorController } from './span-editor.controller'; export class SpanEditorProvider implements IEditorProvider { formEditor: string = 'IBizSpan'; - gridEditor: string = 'IBizGridSpan'; + gridEditor: string = 'IBizSpan'; constructor(editorType?: string) { if (editorType === 'SPAN_LINK') { diff --git a/src/editor/span/span-link/span-link.tsx b/src/editor/span/span-link/span-link.tsx index ce9eab912..11a6b3c03 100644 --- a/src/editor/span/span-link/span-link.tsx +++ b/src/editor/span/span-link/span-link.tsx @@ -3,6 +3,7 @@ import { getSpanProps, getEditorEmits, useNamespace, + useFocusAndBlur, } from '@ibiz-template/vue3-util'; import './span-link.scss'; import { SpanEditorController } from '../span-editor.controller'; @@ -11,7 +12,7 @@ export const IBizSpanLink = defineComponent({ name: 'IBizSpanLink', props: getSpanProps(), emits: getEditorEmits(), - setup(props) { + setup(props, { emit }) { const ns = useNamespace('span-link'); const c = props.controller!; @@ -32,11 +33,21 @@ export const IBizSpanLink = defineComponent({ const openLinkView = async () => { await c.openLinkView(props.data); }; - return { ns, openLinkView, curValue }; + + // 聚焦失焦事件 + const { componentRef: editorRef } = useFocusAndBlur( + () => emit('focus'), + () => emit('blur'), + ); + + return { ns, openLinkView, curValue, editorRef }; }, render() { return ( -
+ ); diff --git a/src/editor/span/span/span.tsx b/src/editor/span/span/span.tsx index e8e785270..d5d449dc6 100644 --- a/src/editor/span/span/span.tsx +++ b/src/editor/span/span/span.tsx @@ -1,5 +1,9 @@ import { ref, defineComponent, Ref, watch, computed } from 'vue'; -import { getSpanProps, useNamespace } from '@ibiz-template/vue3-util'; +import { + getSpanProps, + useFocusAndBlur, + useNamespace, +} from '@ibiz-template/vue3-util'; import dayjs from 'dayjs'; import './span.scss'; import { CodeListItem } from '@ibiz-template/runtime'; @@ -8,7 +12,7 @@ import { SpanEditorController } from '../span-editor.controller'; export const IBizSpan = defineComponent({ name: 'IBizSpan', props: getSpanProps(), - setup(props) { + setup(props, { emit }) { const ns = useNamespace('span'); const c = props.controller; @@ -77,10 +81,17 @@ export const IBizSpan = defineComponent({ return selects.map(item => item.text).join(valueSeparator); }); + // 聚焦失焦事件 + const { componentRef: editorRef } = useFocusAndBlur( + () => emit('focus'), + () => emit('blur'), + ); + return { ns, text, codeListText, + editorRef, }; }, render() { @@ -91,6 +102,7 @@ export const IBizSpan = defineComponent({ this.disabled ? this.ns.m('disabled') : '', this.readonly ? this.ns.m('readonly') : '', ]} + ref='editorRef' > {this.codeListText || this.text} diff --git a/src/editor/stepper/ibiz-stepper/ibiz-stepper.tsx b/src/editor/stepper/ibiz-stepper/ibiz-stepper.tsx index 538306c40..e39e02a84 100644 --- a/src/editor/stepper/ibiz-stepper/ibiz-stepper.tsx +++ b/src/editor/stepper/ibiz-stepper/ibiz-stepper.tsx @@ -59,6 +59,16 @@ export const IBizStepper = defineComponent({ const inputRef = ref(); + // 聚焦 + const onFocus = () => { + emit('focus'); + }; + + // 失焦 + const onBlur = () => { + emit('blur'); + }; + return { ns, c, @@ -69,6 +79,8 @@ export const IBizStepper = defineComponent({ precision, max, min, + onFocus, + onBlur, }; }, render() { @@ -89,6 +101,8 @@ export const IBizStepper = defineComponent({ step={this.step} disabled={this.disabled} onChange={this.handleChange} + onFocus={this.onFocus} + onBlur={this.onBlur} >, ]; } diff --git a/src/editor/switch/ibiz-switch/ibiz-switch.tsx b/src/editor/switch/ibiz-switch/ibiz-switch.tsx index f49bbede7..5912eb63a 100644 --- a/src/editor/switch/ibiz-switch/ibiz-switch.tsx +++ b/src/editor/switch/ibiz-switch/ibiz-switch.tsx @@ -2,6 +2,7 @@ import { defineComponent, ref, watch } from 'vue'; import { getEditorEmits, getSwitchProps, + useFocusAndBlur, useNamespace, } from '@ibiz-template/vue3-util'; import { SwitchEditorController } from '../switch-editor.controller'; @@ -67,6 +68,12 @@ export const IBizSwitch = defineComponent({ emit('change', emitValue); }; + // 聚焦失焦事件 + const { componentRef: editorRef } = useFocusAndBlur( + () => emit('focus'), + () => emit('blur'), + ); + return { ns, currentVal, @@ -74,11 +81,12 @@ export const IBizSwitch = defineComponent({ inactiveText, handleChange, dicData, + editorRef, }; }, render() { return ( -
+
(), - emits: getGridEditorEmits(), - setup() { - const ns = useNamespace('grid-input-number'); - - return { - ns, - }; - }, - render() { - return ( -
- {h(resolveComponent('IBizInputNumber'), { - ...this.$props, - })} -
- ); - }, -}); diff --git a/src/editor/text-box/ibiz-grid-input/ibiz-grid-input.tsx b/src/editor/text-box/ibiz-grid-input/ibiz-grid-input.tsx deleted file mode 100644 index ba3b834d5..000000000 --- a/src/editor/text-box/ibiz-grid-input/ibiz-grid-input.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { defineComponent, h, resolveComponent } from 'vue'; -import { - getGridEditorEmits, - getGridInputProps, - useNamespace, -} from '@ibiz-template/vue3-util'; -import { TextBoxEditorController } from '../text-box-editor.controller'; - -export const IBizGridInput = defineComponent({ - name: 'IBizGridInput', - props: getGridInputProps(), - emits: getGridEditorEmits(), - setup() { - const ns = useNamespace('grid-input'); - - return { - ns, - }; - }, - render() { - return ( -
- {h(resolveComponent('IBizInput'), { - ...this.$props, - })} -
- ); - }, -}); diff --git a/src/editor/text-box/ibiz-input-ip/ibiz-input-ip.tsx b/src/editor/text-box/ibiz-input-ip/ibiz-input-ip.tsx index c2f3d799f..dc274be3a 100644 --- a/src/editor/text-box/ibiz-input-ip/ibiz-input-ip.tsx +++ b/src/editor/text-box/ibiz-input-ip/ibiz-input-ip.tsx @@ -85,6 +85,7 @@ export const IBizInputIP = defineComponent({ activeElement.value = true; if (isAllBlur.value) { isAllBlur.value = false; + emit('focus'); } }; @@ -94,6 +95,7 @@ export const IBizInputIP = defineComponent({ setTimeout(() => { if (!activeElement.value) { isAllBlur.value = true; + emit('blur'); } }, 0); }; diff --git a/src/editor/text-box/ibiz-input-number/ibiz-input-number.tsx b/src/editor/text-box/ibiz-input-number/ibiz-input-number.tsx index 415977370..d998b4a4f 100644 --- a/src/editor/text-box/ibiz-input-number/ibiz-input-number.tsx +++ b/src/editor/text-box/ibiz-input-number/ibiz-input-number.tsx @@ -44,12 +44,24 @@ export const IBizInputNumber = defineComponent({ }); } + // 聚焦 + const onFocus = () => { + emit('focus'); + }; + + // 失焦 + const onBlur = () => { + emit('blur'); + }; + return { ns, c, currentVal, handleChange, inputRef, + onFocus, + onBlur, }; }, render() { @@ -73,6 +85,8 @@ export const IBizInputNumber = defineComponent({ precision={this.c.model.precision} disabled={this.disabled} onChange={this.handleChange} + onFocus={this.onFocus} + onBlur={this.onBlur} >, unitName && {unitName}, ]; diff --git a/src/editor/text-box/index.ts b/src/editor/text-box/index.ts index ab9b972ce..27d8a8fc9 100644 --- a/src/editor/text-box/index.ts +++ b/src/editor/text-box/index.ts @@ -1,7 +1,5 @@ export { IBizInput } from './input/input'; export { IBizInputNumber } from './ibiz-input-number/ibiz-input-number'; export { IBizInputIP } from './ibiz-input-ip/ibiz-input-ip'; -export { IBizGridInput } from './ibiz-grid-input/ibiz-grid-input'; -export { IBizGridInputNumber } from './ibiz-grid-input-number/ibiz-grid-input-number'; export * from './text-box-editor.controller'; export * from './text-box-editor.provider'; diff --git a/src/view-engine/pickup-view.engine.ts b/src/view-engine/pickup-view.engine.ts index 9d7a99e7b..77b579f39 100644 --- a/src/view-engine/pickup-view.engine.ts +++ b/src/view-engine/pickup-view.engine.ts @@ -63,7 +63,7 @@ export class PickupViewEngine extends ViewEngineBase { async doMounted(): Promise { this.pickupViewPanel.state.singleSelect = true; this.pickupViewPanel.evt.on('onSelectionChange', event => { - this.selectData = this.handleSelectData(event.data); + this.selectData = event.data; }); this.pickupViewPanel.evt.on('onDataActive', event => { this.pickupViewPanelDataActive(event.data); @@ -79,7 +79,7 @@ export class PickupViewEngine extends ViewEngineBase { * @memberof PickupViewEngine */ public pickupViewPanelDataActive(data: IData[]) { - this.selectData = this.handleSelectData(data); + this.selectData = data; this.view.closeView({ ok: true, data: this.selectData }); } @@ -96,23 +96,6 @@ export class PickupViewEngine extends ViewEngineBase { return super.call(key, args); } - /** - * 处理选中数据 - * - * @memberof PickupViewEngine - */ - handleSelectData(data: IData[]): IData[] { - const selectData: IData[] = []; - data.forEach((item: IData) => { - selectData.push({ - srfkey: item.srfkey, - srfmajortext: item.srfmajortext, - data: { ...item }, - }); - }); - return selectData; - } - /** * 确认 * -- Gitee From b268464aeb08aefc9a00e58c6c64c9d6bcf500a9 Mon Sep 17 00:00:00 2001 From: zhujiamin <1147570162@qq.com> Date: Thu, 1 Jun 2023 18:39:13 +0800 Subject: [PATCH 5/5] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E9=9D=A2?= =?UTF-8?q?=E6=9D=BFappTitle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/panel-component/index.ts | 3 ++ src/panel-component/panel-app-title/index.ts | 18 +++++++ .../panel-app-title.controller.ts | 48 +++++++++++++++++++ .../panel-app-title.provider.ts | 25 ++++++++++ .../panel-app-title/panel-app-title.scss | 15 ++++++ .../panel-app-title/panel-app-title.state.ts | 28 +++++++++++ .../panel-app-title/panel-app-title.tsx | 40 ++++++++++++++++ 7 files changed, 177 insertions(+) create mode 100644 src/panel-component/panel-app-title/index.ts create mode 100644 src/panel-component/panel-app-title/panel-app-title.controller.ts create mode 100644 src/panel-component/panel-app-title/panel-app-title.provider.ts create mode 100644 src/panel-component/panel-app-title/panel-app-title.scss create mode 100644 src/panel-component/panel-app-title/panel-app-title.state.ts create mode 100644 src/panel-component/panel-app-title/panel-app-title.tsx diff --git a/src/panel-component/index.ts b/src/panel-component/index.ts index e712148ae..1ed29ee54 100644 --- a/src/panel-component/index.ts +++ b/src/panel-component/index.ts @@ -7,6 +7,7 @@ import IBizPanelCtrlPos from './panel-ctrl-pos'; import IBizScrollContainer from './scroll-container'; import IBizPanelButton from './panel-button'; import IBizNavPos from './nav-pos'; +import IBizPanelAppTitle from './panel-app-title'; export * from './panel-container'; export * from './panel-ctrl-pos'; @@ -15,6 +16,7 @@ export * from './auth-userinfo'; export * from './nav-pos-index'; export * from './panel-button'; export * from './nav-pos'; +export * from './panel-app-title'; export const IBizPanelComponents = { install: (v: App) => { @@ -26,6 +28,7 @@ export const IBizPanelComponents = { v.use(IBizNavTabs); v.use(IBizPanelButton); v.use(IBizNavPos); + v.use(IBizPanelAppTitle); }, }; diff --git a/src/panel-component/panel-app-title/index.ts b/src/panel-component/panel-app-title/index.ts new file mode 100644 index 000000000..8e1e3fa02 --- /dev/null +++ b/src/panel-component/panel-app-title/index.ts @@ -0,0 +1,18 @@ +import { registerPanelItemProvider } from '@ibiz-template/runtime'; +import { withInstall } from '@ibiz-template/vue3-util'; +import { App } from 'vue'; +import PanelAppTitle from './panel-app-title'; +import { PanelAppTitleProvider } from './panel-app-title.provider'; + +export * from './panel-app-title.provider'; +export * from './panel-app-title.controller'; + +export const IBizPanelAppTitle = withInstall(PanelAppTitle, function (v: App) { + v.component(PanelAppTitle.name, PanelAppTitle); + registerPanelItemProvider( + 'RAWITEM_APP_APPTITLE', + () => new PanelAppTitleProvider(), + ); +}); + +export default IBizPanelAppTitle; diff --git a/src/panel-component/panel-app-title/panel-app-title.controller.ts b/src/panel-component/panel-app-title/panel-app-title.controller.ts new file mode 100644 index 000000000..9dbc5cd68 --- /dev/null +++ b/src/panel-component/panel-app-title/panel-app-title.controller.ts @@ -0,0 +1,48 @@ +import { IPanelField, IAppIndexView } from '@ibiz/model-core'; +import { PanelItemController, ViewLayoutPanelController } from '../../control'; +import { PanelAppTitleState } from './panel-app-title.state'; + +/** + * 面板应用标题控制器 + * + * @export + * @class PanelAppTitleController + * @extends {PanelItemController} + */ +export class PanelAppTitleController extends PanelItemController { + declare state: PanelAppTitleState; + + protected createState(): PanelAppTitleState { + return new PanelAppTitleState(this.parent?.state); + } + + /** + * 面板控制器 + * + * @type {ViewLayoutPanelController} + * @memberof PanelAppTitleController + */ + declare panel: ViewLayoutPanelController; + + /** + * 初始化 + * + * @return {*} {Promise} + * @memberof PanelAppTitleController + */ + async onInit(): Promise { + await super.onInit(); + const indexViewModel: IAppIndexView = this.panel.view.model; + // 抬头 + if (indexViewModel.title) { + this.state.title = indexViewModel.title; + document.title = indexViewModel.title; + } else if (ibiz.env.AppTitle) { + this.state.title = ibiz.env.AppTitle; + } + // 图标路径 + if (indexViewModel.appIconPath) { + this.state.imgUrl = indexViewModel.appIconPath; + } + } +} diff --git a/src/panel-component/panel-app-title/panel-app-title.provider.ts b/src/panel-component/panel-app-title/panel-app-title.provider.ts new file mode 100644 index 000000000..2f555c910 --- /dev/null +++ b/src/panel-component/panel-app-title/panel-app-title.provider.ts @@ -0,0 +1,25 @@ +import { IPanelItemProvider } from '@ibiz-template/runtime'; +import { IPanelItem } from '@ibiz/model-core'; +import { PanelController, PanelItemController } from '../../control'; +import { PanelAppTitleController } from './panel-app-title.controller'; + +/** + * 面板应用标题适配器 + * + * @export + * @class PanelAppTitleProvider + * @implements {IPanelItemProvider} + */ +export class PanelAppTitleProvider implements IPanelItemProvider { + component: string = 'IBizPanelAppTitle'; + + async createController( + panelItem: IPanelItem, + panel: PanelController, + parent: PanelItemController | undefined, + ): Promise { + const c = new PanelAppTitleController(panelItem, panel, parent); + await c.init(); + return c; + } +} diff --git a/src/panel-component/panel-app-title/panel-app-title.scss b/src/panel-component/panel-app-title/panel-app-title.scss new file mode 100644 index 000000000..fe448eec2 --- /dev/null +++ b/src/panel-component/panel-app-title/panel-app-title.scss @@ -0,0 +1,15 @@ +@include b(panel-app-title) { + display: flex; + align-items: center; + justify-content: center; + height: 100%; + @include e(logo) { + display: inline-block; + height: 80%; + margin-right: 10px; + + img { + height: 100%; + } + } +} diff --git a/src/panel-component/panel-app-title/panel-app-title.state.ts b/src/panel-component/panel-app-title/panel-app-title.state.ts new file mode 100644 index 000000000..53812b6ea --- /dev/null +++ b/src/panel-component/panel-app-title/panel-app-title.state.ts @@ -0,0 +1,28 @@ +import { PanelItemState } from '../../control/panel/panel/panel-item.state'; + +/** + * 面板应用标题状态 + * + * @author lxm + * @date 2023-02-07 06:04:27 + * @export + * @class PanelAppTitleState + * @extends {PanelItemState} + */ +export class PanelAppTitleState extends PanelItemState { + /** + * 应用标题 + * @return {*} + * @author: zhujiamin + * @Date: 2023-06-01 10:29:07 + */ + title: string = ''; + + /** + * 应用logo地址 + * @return {*} + * @author: zhujiamin + * @Date: 2023-06-01 10:29:07 + */ + imgUrl: string = ''; +} diff --git a/src/panel-component/panel-app-title/panel-app-title.tsx b/src/panel-component/panel-app-title/panel-app-title.tsx new file mode 100644 index 000000000..a06429a8a --- /dev/null +++ b/src/panel-component/panel-app-title/panel-app-title.tsx @@ -0,0 +1,40 @@ +import { useNamespace } from '@ibiz-template/vue3-util'; +import { IPanelField } from '@ibiz/model-core'; +import { defineComponent, PropType } from 'vue'; +import { PanelAppTitleController } from './panel-app-title.controller'; +import './panel-app-title.scss'; + +export const PanelAppTitle = defineComponent({ + name: 'IBizPanelAppTitle', + props: { + modelData: { + type: Object as PropType, + required: true, + }, + controller: { + type: PanelAppTitleController, + required: true, + }, + }, + setup(props) { + const ns = useNamespace('panel-app-title'); + + const c = props.controller; + + return { + ns, + c, + }; + }, + render() { + return ( +
+ + + + {this.c.state.title} +
+ ); + }, +}); +export default PanelAppTitle; -- Gitee