diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e9152a75b9a9302025c9ac5dcaf5626d93fd3a8..5948220855d1c1b0b6ce6010d1cf54d477f9568a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ### Added +- 新增数组编辑器 - 多数据、卡片支持simple模式 - 分页导航面板支持计数器、支持左侧、右侧、下方布局 - 新增注册多数据容器(仅数据)、传送占位组件 @@ -19,6 +20,7 @@ ### Change +- 更新视图头预置返回按钮将会视图参数srfmobshowpresetback和全局视图配置mobShowPresetBack共同决定显隐;返回顶部按钮将结合视图参数srfshowbacktop决定是否显示 - 更新所有编辑器在进行属性透传时,class和style属性不往下透传 - 卡片部件样式调整,高度撑满视图内容 - 数据关系分页布局激活样式适配主题颜色 diff --git a/src/common/preset-view-back/preset-view-back.tsx b/src/common/preset-view-back/preset-view-back.tsx index e6eb4cc57751ee0aa97429ce8a3bb7c69b8535e2..3732c503fa8eade07cec242a7e4785b829d4afb0 100644 --- a/src/common/preset-view-back/preset-view-back.tsx +++ b/src/common/preset-view-back/preset-view-back.tsx @@ -29,7 +29,11 @@ export const IBizPresetViewBack = defineComponent({ } }; - if (ibiz.config.view.mobShowPresetBack) { + if (Object.keys(props.view.params).includes('srfmobshowpresetback')) { + if (props.view.params.srfmobshowpresetback === true) { + initButtonVisible(); + } + } else if (ibiz.config.view.mobShowPresetBack) { initButtonVisible(); } diff --git a/src/editor/array/array-editor.controller.ts b/src/editor/array/array-editor.controller.ts new file mode 100644 index 0000000000000000000000000000000000000000..7d19f0bc073a4858c975e10b452966b9f0d8457a --- /dev/null +++ b/src/editor/array/array-editor.controller.ts @@ -0,0 +1,10 @@ +import { EditorController } from '@ibiz-template/runtime'; +import { IArray } from '@ibiz/model-core'; + +/** + * 数组编辑器控制器 + * @return {*} + * @author: zhujiamin + * @Date: 2022-08-25 10:57:58 + */ +export class ArrayEditorController extends EditorController {} diff --git a/src/editor/array/array-editor.provider.ts b/src/editor/array/array-editor.provider.ts new file mode 100644 index 0000000000000000000000000000000000000000..14f519cb565ec898acb42b283bebbba9c63442a4 --- /dev/null +++ b/src/editor/array/array-editor.provider.ts @@ -0,0 +1,31 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { + IEditorContainerController, + IEditorProvider, +} from '@ibiz-template/runtime'; +import { IArray } from '@ibiz/model-core'; +import { ArrayEditorController } from './array-editor.controller'; + +/** + * 数组编辑器适配器 + * + * @author lxm + * @date 2022-09-19 22:09:03 + * @export + * @class ArrayEditorProvider + * @implements {EditorProvider} + */ +export class ArrayEditorProvider implements IEditorProvider { + formEditor: string = 'IBizArray'; + + gridEditor: string = 'IBizArray'; + + async createController( + editorModel: IArray, + parentController: IEditorContainerController, + ): Promise { + const c = new ArrayEditorController(editorModel, parentController); + await c.init(); + return c; + } +} diff --git a/src/editor/array/ibiz-array/ibiz-array.scss b/src/editor/array/ibiz-array/ibiz-array.scss new file mode 100644 index 0000000000000000000000000000000000000000..b85e026930f699ef363b7d3220a368cf1f4597f9 --- /dev/null +++ b/src/editor/array/ibiz-array/ibiz-array.scss @@ -0,0 +1,11 @@ +@include b(array) { + height: 100%; + line-height: getCssVar(editor, default, line-height); + .van-field{ + line-height: getCssVar(editor, default, line-height); + } + + ion-icon { + cursor: pointer; + } +} diff --git a/src/editor/array/ibiz-array/ibiz-array.tsx b/src/editor/array/ibiz-array/ibiz-array.tsx new file mode 100644 index 0000000000000000000000000000000000000000..f4df74611527ea48e3a71b8bf2fd97b90f9d4e3c --- /dev/null +++ b/src/editor/array/ibiz-array/ibiz-array.tsx @@ -0,0 +1,223 @@ +import { computed, defineComponent, Ref, ref, watch } from 'vue'; +import { + getArrayProps, + getEditorEmits, + useNamespace, + useFilterAttribute, +} from '@ibiz-template/vue3-util'; +import { createUUID } from 'qx-util'; +import { toNumber } from 'lodash-es'; +import { ArrayEditorController } from '../array-editor.controller'; +import './ibiz-array.scss'; + +/** + * 数组数据编辑 + * + * @description 使用van-field组件封装,提供数组数据的输入能力,其呈现样式为多个携带自增自减按钮的输入框。支持编辑器类型包含:`数组编辑器` + * @primary + * @editorparams {"name":"size","parameterType":"'large' | 'normal'","defaultvalue":"'normal'","description":"van-field组件的size属性"} + * @editorparams {"name":"limit","parameterType":"number","defaultvalue":0,"description":"默认不限制输入项数量,若设置了非零的限制数,当输入项数量超出该限制时,自增按钮将隐藏"} + * @editorparams {"name":"maxlength","parameterType":"number","description":"设置单个输入框可输入内容的最大长度"} + * @editorparams {"name":"showwordlimit","parameterType":"boolean","defaultvalue":false,"description":"是否显示字数限制统计,仅在设置了maxlength属性时生效"} + * @editorparams {"name":"triggermode","parameterType":"'blur' |' input'","defaultvalue":"'blur'","description":"指定编辑器触发 `change` 值变更事件的模式,input: 输入框输入时触发事件,blur:输入框blur时触发事件"} + * @editorparams {"name":"readonly","parameterType":"boolean","defaultvalue":false,"description":"设置编辑器是否为只读态"} + * @ignoreprops autoFocus | overflowMode + * @ignoreemits infoTextChange + */ +export const IBizArray = defineComponent({ + name: 'IBizArray', + props: getArrayProps(), + emits: getEditorEmits(), + setup(props, { emit }) { + const ns = useNamespace('array'); + + const c = props.controller!; + + const editorModel = c.model; + + // 输入框大小 + let size = 'default'; + // 数组大小限制 + let limit = 0; + // 输入内容最长长度 + let maxLength; + // 是否显示输入内容长度 + let showWordLimit = false; + // 输入内容项集合 + const items: Ref = ref([]); + + if (editorModel.editorParams) { + if (editorModel.editorParams.size) { + size = editorModel.editorParams.size; + } + if (editorModel.editorParams.limit) { + limit = toNumber(editorModel.editorParams.limit); + } + if (editorModel.editorParams.maxLength) { + maxLength = toNumber(editorModel.editorParams.maxLength); + } + if (editorModel.editorParams.maxlength) { + maxLength = toNumber(editorModel.editorParams.maxlength); + } + if (editorModel.editorParams.showWordLimit) { + showWordLimit = c.toBoolean(editorModel.editorParams.showWordLimit); + } + if (editorModel.editorParams.showwordlimit) { + showWordLimit = c.toBoolean(editorModel.editorParams.showwordlimit); + } + } + + // 输入框类型 + const dataType = editorModel.dataType; + const type = + Object.is(dataType, 'NUMBER') || Object.is(dataType, 'INTEGER') + ? 'number' + : 'text'; + + // 是否显示表单默认内容 + const showFormDefaultContent = computed(() => { + if ( + props.controlParams && + props.controlParams.editmode === 'hover' && + !props.readonly + ) { + return true; + } + return false; + }); + + watch( + () => props.value, + (newVal, oldVal) => { + if (newVal && newVal !== oldVal) { + if (items.value.length === 0) { + const tempItems = newVal.map((value: string | number) => { + return { value, key: createUUID() }; + }); + items.value = tempItems; + } + } + }, + { immediate: true }, + ); + + // 抛值 + const onEmit = (eventName: string = 'blur'): void => { + const result = items.value.map(item => item.value); + if (eventName === c.triggerMode) { + emit('change', result); + } + }; + + // 新增项 + const addItem = (index?: number): void => { + if (props.disabled || props.readonly) { + return; + } + const tempLink = { + key: createUUID(), + value: null, + }; + if (index) { + items.value.splice(index, 0, tempLink); + } else { + items.value.push(tempLink); + } + onEmit(); + }; + + // 删除项 + const removeItem = (index: number): void => { + items.value.splice(index, 1); + onEmit(); + }; + + // 处理值改变 + const handleInput = (): void => { + onEmit('input'); + }; + + const onBlur = (e: IData): void => { + onEmit('blur'); + emit('blur', e); + }; + + const onFocus = (e: IData): void => { + emit('focus', e); + }; + + return { + ns, + c, + type, + size, + limit, + maxLength, + showWordLimit, + items, + addItem, + removeItem, + handleInput, + onBlur, + onFocus, + showFormDefaultContent, + }; + }, + render() { + return ( +
+ {this.items.length === 0 ? ( + + ) : ( + this.items.map((item: IData, index: number) => { + return ( +
+ this.handleInput()} + {...useFilterAttribute(this.$attrs)} + > + {!(this.disabled || this.readonly) && ( +
+ {(!this.limit || this.items.length < this.limit) && ( + this.addItem(index + 1)} + /> + )} + this.removeItem(index)} + /> +
+ )} +
+ ); + }) + )} +
+ ); + }, +}); diff --git a/src/editor/array/index.ts b/src/editor/array/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..8dfac96d5dca124003e115df1e2ab625391422bd --- /dev/null +++ b/src/editor/array/index.ts @@ -0,0 +1,3 @@ +export { IBizArray } from './ibiz-array/ibiz-array'; +export * from './array-editor.controller'; +export * from './array-editor.provider'; diff --git a/src/editor/index.ts b/src/editor/index.ts index 4999e3e2008108ae7dcd804cb15c59174e513994..e568c42ea7641300f66aaa1d7828e8f2a020938f 100644 --- a/src/editor/index.ts +++ b/src/editor/index.ts @@ -49,10 +49,12 @@ import { IBizDropdownList } from './dropdown-list/ibiz-dropdown-list/ibiz-dropdo import { IBizQrcode, QrcodeEditorProvider } from './qrcode'; import { IBizCheckbox, CheckBoxEditorProvider } from './check-box'; import { IBizMapPicker, MapPickerEditorProvider } from './map-picker'; +import { IBizArray, ArrayEditorProvider } from './array'; export const IBizEditor = { install: (v: App): void => { // 组件注册 + v.component(IBizArray.name, IBizArray); v.component(NotSupportedEditor.name, NotSupportedEditor); v.component(IBizInput.name, IBizInput); v.component(IBizInputNumber.name, IBizInputNumber); @@ -104,6 +106,10 @@ export const IBizEditor = { ), ); + // 数组编辑器 + registerEditorProvider('ARRAY', () => new ArrayEditorProvider()); + registerEditorProvider('MOBARRAY', () => new ArrayEditorProvider()); + // 标签 registerEditorProvider('SPAN', () => new SpanEditorProvider()); registerEditorProvider( diff --git a/src/panel-component/view-content-panel-container/view-content-panel-container.tsx b/src/panel-component/view-content-panel-container/view-content-panel-container.tsx index 9dd2fe394abc89d1d76cb724f7fbb9102a326160..c042a412368ee56f87eefb95d2b776811776f285 100644 --- a/src/panel-component/view-content-panel-container/view-content-panel-container.tsx +++ b/src/panel-component/view-content-panel-container/view-content-panel-container.tsx @@ -98,13 +98,14 @@ export const ViewContentPanelContainer: Component = defineComponent({ render() { // 内容区默认插槽处理,封装app-col const defaultSlots = this.$slots.default?.() || []; + const showBackTop = this.controller.params.srfshowbacktop !== false; const content = ( - {this.isScrollable && this.contentRef && ( + {this.isScrollable && this.contentRef && showBackTop && ( )} {defaultSlots.map((slot: { props: IData }) => {