vxe-pc-ui
Version:
A vue based PC component library
283 lines (260 loc) • 8.79 kB
text/typescript
import { VNode, h, onMounted, ref, watch } from 'vue'
import { VxeUI, getIcon, getI18n } from '@vxe-ui/core'
import VxeFormItemComponent from '../../../form/src/form-item'
import VxeButtonComponent from '../../../button/src/button'
import VxeTextareaComponent from '../../../textarea/src/textarea'
import VxeTipComponent from '../../../tip/src/tip'
import type { VxeGlobalRendererHandles } from '../../../../types'
export interface WidgetDataSourceOptionSubObjVO {
value: string,
}
export interface WidgetDataSourceOptionObjVO {
value: string,
options?: WidgetDataSourceOptionSubObjVO[]
}
export function useWidgetPropDataSource (props: {
readonly renderOpts: VxeGlobalRendererHandles.RenderFormDesignWidgetFormViewOptions
readonly renderParams: VxeGlobalRendererHandles.RenderFormDesignWidgetFormViewParams<{
options: WidgetDataSourceOptionObjVO[]
}>
}, renderConfig?: {
isSubOption?: boolean
}) {
const renConf = Object.assign({}, renderConfig)
const isSubOption = renConf.isSubOption
const optionsContent = ref('')
const expandIndexList = ref<number[]>([])
const addOptionEvent = () => {
const { renderParams } = props
const { widget } = renderParams
const options = widget.options.options || []
options.push({
value: getI18n('vxe.formDesign.widgetProp.dataSource.defValue', [options.length + 1])
})
widget.options.options = [...options]
}
const subRE = /^(\s|\t)+/
const hasSubOption = (str: string) => {
return subRE.test(str)
}
const expandAllOption = () => {
const { renderParams } = props
const { widget } = renderParams
const options = widget.options.options || []
const indexList: number[] = []
options.forEach((group, gIndex) => {
const { options } = group
if (options && options.length) {
indexList.push(gIndex)
}
})
expandIndexList.value = indexList
}
const toggleExpandOption = (item: WidgetDataSourceOptionSubObjVO, gIndex: number) => {
if (expandIndexList.value.includes(gIndex)) {
expandIndexList.value = expandIndexList.value.filter(num => num !== gIndex)
} else {
expandIndexList.value.push(gIndex)
}
}
const removeOptionEvent = (item: WidgetDataSourceOptionSubObjVO, group: WidgetDataSourceOptionObjVO | null) => {
const { renderParams } = props
const { widget } = renderParams
const { options } = widget
if (group) {
if (group.options) {
group.options = group.options.filter(obj => obj !== item)
}
} else {
options.options = options.options.filter(obj => obj !== item)
}
}
const confirmBatchAddOptionEvent = () => {
const { renderParams } = props
const { widget } = renderParams
const optList: WidgetDataSourceOptionSubObjVO[] = []
const rowList = optionsContent.value.split('\n')
let prevGroup: Required<WidgetDataSourceOptionObjVO> | null = null
if (isSubOption) {
rowList.forEach((str, index) => {
const nextStr = rowList[index + 1]
const value = str.trim()
if (!value) {
return
}
const item: WidgetDataSourceOptionSubObjVO = {
value
}
if (prevGroup) {
if (hasSubOption(str)) {
prevGroup.options.push(item)
return
}
prevGroup = null
optList.push(item)
} else {
optList.push(item)
}
if (nextStr) {
if (hasSubOption(nextStr)) {
prevGroup = Object.assign(item, { options: [] })
}
}
})
} else {
rowList.forEach((str) => {
optList.push({
value: str.trim()
})
})
}
widget.options.options = optList
expandAllOption()
}
const openPopupEditEvent = () => {
const { renderParams } = props
const { widget } = renderParams
const contList: string[] = []
widget.options.options?.forEach(group => {
contList.push(group.value)
group.options?.forEach(item => {
contList.push(`\t${item.value}`)
})
})
optionsContent.value = contList.join('\n')
VxeUI.modal.open({
title: `${widget.title} - ${getI18n('vxe.formDesign.widgetProp.dataSource.batchEditOption')}`,
width: 500,
height: '50vh ',
resize: true,
showFooter: true,
showCancelButton: true,
showConfirmButton: true,
confirmButtonText: getI18n('vxe.formDesign.widgetProp.dataSource.buildOption'),
onConfirm: confirmBatchAddOptionEvent,
slots: {
default () {
return h('div', {
class: 'vxe-form-design--widget-form-item-data-source-popup'
}, [
h(VxeTipComponent, {
status: 'primary',
title: '',
content: getI18n(`vxe.formDesign.widgetProp.dataSource.${isSubOption ? 'batchEditSubTip' : 'batchEditTip'}`)
}),
h(VxeTextareaComponent, {
resize: 'none',
modelValue: optionsContent.value,
'onUpdate:modelValue' (val) {
optionsContent.value = val
}
})
])
}
}
})
}
const renderOption = (item: WidgetDataSourceOptionSubObjVO, group: WidgetDataSourceOptionObjVO | null, isExpand: boolean, gIndex: number, hasSub: boolean, isFirst: boolean, isLast: boolean) => {
const hasFirstLevel = !group
return h('div', {
class: ['vxe-form-design--widget-form-item-data-source-option', {
'is--first': isFirst,
'is--last': isLast
}]
}, [
h('div', {
class: 'vxe-form-design--widget-expand-btn'
}, hasFirstLevel && hasSub
? [
h('i', {
class: isExpand ? getIcon().FORM_DESIGN_WIDGET_OPTION_EXPAND_CLOSE : getIcon().FORM_DESIGN_WIDGET_OPTION_EXPAND_OPEN,
onClick () {
toggleExpandOption(item, gIndex)
}
})
]
: []),
h('input', {
class: 'vxe-default-input',
value: item.value,
onInput (evnt: InputEvent & { target: HTMLInputElement }) {
item.value = evnt.target.value
}
}),
h(VxeButtonComponent, {
status: 'danger',
mode: 'text',
icon: getIcon().FORM_DESIGN_WIDGET_DELETE,
onClick () {
removeOptionEvent(item, group)
}
})
])
}
const renderOptions = () => {
const { renderParams } = props
const { widget } = renderParams
const { options } = widget
const groups = options.options
const optVNs: VNode[] = []
if (groups) {
groups.forEach((group, gIndex) => {
const { options } = group
const isExpand = expandIndexList.value.includes(gIndex)
if (options && options.length) {
optVNs.push(renderOption(group, null, isExpand, gIndex, true, gIndex === 0, gIndex === groups.length - 1))
if (isExpand) {
optVNs.push(
h('div', {
class: 'vxe-form-design--widget-form-item-data-source-sub-option'
}, options.map(item => renderOption(item, group, isExpand, 0, false, false, false)))
)
}
} else {
optVNs.push(renderOption(group, null, isExpand, gIndex, false, gIndex === 0, gIndex === groups.length - 1))
}
})
}
return optVNs
}
watch(() => props.renderParams.widget, () => {
expandAllOption()
})
onMounted(() => {
expandAllOption()
})
const renderDataSourceFormItemContent = () => {
return [
h('div', {}, [
h(VxeButtonComponent, {
status: 'primary',
mode: 'text',
content: getI18n('vxe.formDesign.widgetProp.dataSource.addOption'),
onClick: addOptionEvent
}),
h(VxeButtonComponent, {
status: 'primary',
mode: 'text',
content: getI18n('vxe.formDesign.widgetProp.dataSource.batchEditOption'),
onClick: openPopupEditEvent
})
]),
h('div', {
class: 'vxe-form-design--widget-form-item-data-source-wrapper'
}, renderOptions())
]
}
return {
renderDataSourceFormItem () {
return h(VxeFormItemComponent, {
title: getI18n('vxe.formDesign.widgetProp.dataSource.name'),
field: 'options'
}, {
default () {
return renderDataSourceFormItemContent()
}
})
},
renderDataSourceFormItemContent
}
}