20260824225422
This commit is contained in:
1 parent
97aea665f9
commit
7421019ef2
6 files changed
+2210
-401
No files matched your search
+22
-2
@@ -119,10 +119,21 @@ function onI18nSaved(key) {
|
||||
|
||||
<template>
|
||||
<div v-if="formData" class="mm-basic">
|
||||
<Form ref="formRef" :model="formData" :rules="formRules" layout="vertical" :columns="3" max-width="720px">
|
||||
<Form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
layout="vertical"
|
||||
:columns="3"
|
||||
max-width="720px"
|
||||
>
|
||||
<div class="mm-basic__section-title">标识与归属</div>
|
||||
<FormItem :label="isCategory ? '分类编码' : '模块编码'" name="b_code" required>
|
||||
<Input :model-value="formData.b_code" :disabled="loading" @update:model-value="onCodeInput" />
|
||||
<Input
|
||||
:model-value="formData.b_code"
|
||||
:disabled="loading"
|
||||
@update:model-value="onCodeInput"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="模块名称" name="b_name" required>
|
||||
<Input
|
||||
@@ -265,6 +276,15 @@ function onI18nSaved(key) {
|
||||
}
|
||||
}
|
||||
|
||||
/* 编辑方式等字段的说明文字 */
|
||||
.mm-basic__hint {
|
||||
grid-column: 1 / -1;
|
||||
margin: -4px 0 8px;
|
||||
color: var(--fms-text-secondary);
|
||||
font-size: 12px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.mm-basic__i18n-btn {
|
||||
flex: none;
|
||||
display: inline-flex;
|
||||
|
||||
+1457
-304
File diff suppressed because it is too large.
Load diff
@@ -419,6 +419,7 @@ async function addModule(parentId, moduleType) {
|
||||
b_keyfield: null,
|
||||
b_orderfield: null,
|
||||
b_delete_policy: moduleType === 'data' ? 'restrict' : null,
|
||||
b_edit_mode: moduleType === 'data' ? 'form' : null,
|
||||
b_canuse: 1,
|
||||
b_xh: 10,
|
||||
b_bz: null,
|
||||
@@ -715,7 +716,7 @@ const configGroups = computed(() => {
|
||||
const editLen = drafts.value?.editConfig?.length ?? 0
|
||||
uiItems.push({
|
||||
key: 'edit',
|
||||
label: '表单设计',
|
||||
label: editNavLabel.value,
|
||||
icon: Pencil,
|
||||
badge: editLen ? '已配置' : '',
|
||||
})
|
||||
@@ -778,6 +779,10 @@ const referencedGroupIds = computed(() => {
|
||||
return Array.from(ids)
|
||||
})
|
||||
|
||||
// 编辑方式(form 主表表单 / table 子表表格)决定「表单设计」面板的形态与导航标签
|
||||
const editMode = computed(() => drafts.value?.module?.b_edit_mode || 'form')
|
||||
const editNavLabel = computed(() => (editMode.value === 'table' ? '表格设计' : '表单设计'))
|
||||
|
||||
const finalI18nItems = computed(() => {
|
||||
const module = drafts.value?.module
|
||||
if (!module) return []
|
||||
@@ -1524,9 +1529,13 @@ loadMenuTree()
|
||||
:fields="drafts?.fields"
|
||||
:groups="drafts?.groups"
|
||||
:referenced-group-ids="referencedGroupIds"
|
||||
:edit-mode="editMode"
|
||||
:active="activeSection === 'edit'"
|
||||
:loading="busy"
|
||||
@update="(v) => onModuleUpdate('editConfig', v)"
|
||||
@update:edit-mode="
|
||||
(v) => onModuleUpdate('module', { ...(drafts?.module || {}), b_edit_mode: v })
|
||||
"
|
||||
@update-groups="(v) => onModuleUpdate('groups', v)"
|
||||
@groups-saved="onGroupsSaved"
|
||||
@sync-list="(v) => onModuleUpdate('listConfig', v)"
|
||||
|
||||
@@ -125,7 +125,11 @@ const panelStubs = {
|
||||
},
|
||||
ModuleFieldsPanel: { name: 'ModuleFieldsPanel', template: '<div class="stub-fields" />' },
|
||||
ModuleListConfigPanel: { name: 'ModuleListConfigPanel', template: '<div class="stub-list" />' },
|
||||
ModuleEditConfigPanel: { name: 'ModuleEditConfigPanel', template: '<div class="stub-edit" />' },
|
||||
ModuleEditConfigPanel: {
|
||||
name: 'ModuleEditConfigPanel',
|
||||
props: ['editMode'],
|
||||
template: '<div class="stub-edit" />',
|
||||
},
|
||||
ModuleQueryConfigPanel: {
|
||||
name: 'ModuleQueryConfigPanel',
|
||||
template: '<div class="stub-query" />',
|
||||
@@ -237,6 +241,33 @@ describe('模块管理页面(重构后)', () => {
|
||||
expect(active[0].text()).toContain('基本信息')
|
||||
})
|
||||
|
||||
it('编辑方式=table 的模块:导航显示「表格设计」并传递 edit-mode 给编辑面板', async () => {
|
||||
const impl = vi.mocked(loadDataApi).getMockImplementation()
|
||||
vi.mocked(loadDataApi).mockImplementation(async (table, where) => {
|
||||
if (table === 's_module') {
|
||||
const match = String(where || '').match(/b_id\s*=\s*(\d+)/)
|
||||
if (match) {
|
||||
const rows = deepCloneRows(moduleRows.filter((r) => String(r.b_id) === match[1]))
|
||||
if (rows.length) rows[0].b_edit_mode = 'table'
|
||||
return { data: rows }
|
||||
}
|
||||
return { data: deepCloneRows(moduleRows) }
|
||||
}
|
||||
return { data: [] }
|
||||
})
|
||||
try {
|
||||
const wrapper = await mountPage()
|
||||
await selectModule(wrapper, '订单')
|
||||
const labels = wrapper.findAll('.mm-config-nav__label').map((t) => t.text())
|
||||
expect(labels).toContain('表格设计')
|
||||
expect(labels).not.toContain('表单设计')
|
||||
const editPanel = wrapper.findComponent({ name: 'ModuleEditConfigPanel' })
|
||||
expect(editPanel.props('editMode')).toBe('table')
|
||||
} finally {
|
||||
vi.mocked(loadDataApi).mockImplementation(impl)
|
||||
}
|
||||
})
|
||||
|
||||
it('点击导航项切换内容面板', async () => {
|
||||
const wrapper = await mountPage()
|
||||
await selectModule(wrapper, '订单')
|
||||
@@ -826,7 +857,8 @@ describe('ModuleBasicPanel(基本信息面板)', () => {
|
||||
FormItem: {
|
||||
name: 'FormItem',
|
||||
props: ['label', 'name', 'span'],
|
||||
template: '<div class="stub-form-item"><slot /></div>',
|
||||
template:
|
||||
'<div class="stub-form-item"><span class="stub-form-label">{{ label }}</span><slot /></div>',
|
||||
},
|
||||
Input: {
|
||||
name: 'Input',
|
||||
@@ -835,7 +867,13 @@ describe('ModuleBasicPanel(基本信息面板)', () => {
|
||||
template:
|
||||
'<input class="stub-input" :value="modelValue" @input="$emit(\'update:modelValue\', $event.target.value)" />',
|
||||
},
|
||||
Select: { name: 'Select', props: ['modelValue'], template: '<div class="stub-select" />' },
|
||||
Select: {
|
||||
name: 'Select',
|
||||
props: ['modelValue', 'options'],
|
||||
emits: ['update:modelValue'],
|
||||
template:
|
||||
'<select class="stub-select" :value="modelValue" @change="$emit(\'update:modelValue\', $event.target.value)"><option v-for="opt in options" :key="String(opt.value)" :value="opt.value">{{ opt.label }}</option></select>',
|
||||
},
|
||||
Switch: { name: 'Switch', props: ['modelValue'], template: '<div class="stub-switch" />' },
|
||||
I18nQuickSetModal: true,
|
||||
}
|
||||
@@ -885,6 +923,13 @@ describe('ModuleBasicPanel(基本信息面板)', () => {
|
||||
expect(update).toBeTruthy()
|
||||
expect(update[0][0].b_name).toBe('新订单名')
|
||||
})
|
||||
|
||||
it('查询模块不显示「编辑方式」标签(编辑方式已移至表单设计面板)', async () => {
|
||||
const wrapper = mountBasic({ ...dataModule, b_module_type: 'query', b_savetable: null })
|
||||
await nextTick()
|
||||
const labels = wrapper.findAll('.stub-form-label').map((l) => l.text())
|
||||
expect(labels).not.toContain('编辑方式')
|
||||
})
|
||||
})
|
||||
|
||||
const mountMenu = (menu, activeSection = 'basic') =>
|
||||
@@ -1632,72 +1677,6 @@ describe('ModuleEditConfigPanel(表单设计视图)', () => {
|
||||
expect(last.map((r) => r.b_colspan)).toEqual([24, 24, 24]) // f3 独占上方新行,f1/f2 保持整行
|
||||
})
|
||||
|
||||
it('同行配对(两步选择):属性面板「同行配对」按钮,两字段合并同行各占一半', async () => {
|
||||
const rows = [
|
||||
{
|
||||
b_id: 'a1',
|
||||
b_module_id: '2',
|
||||
b_field_id: 'f1',
|
||||
b_group_id: 'g1',
|
||||
b_visible: 1,
|
||||
b_required: 1,
|
||||
b_readonly: 0,
|
||||
b_disabled: 0,
|
||||
b_colspan: 24,
|
||||
b_xh: 10,
|
||||
},
|
||||
{
|
||||
b_id: 'a2',
|
||||
b_module_id: '2',
|
||||
b_field_id: 'f2',
|
||||
b_group_id: 'g1',
|
||||
b_visible: 1,
|
||||
b_required: 0,
|
||||
b_readonly: 0,
|
||||
b_disabled: 0,
|
||||
b_colspan: 24,
|
||||
b_xh: 20,
|
||||
},
|
||||
{
|
||||
b_id: 'a3',
|
||||
b_module_id: '2',
|
||||
b_field_id: 'f3',
|
||||
b_group_id: 'g1',
|
||||
b_visible: 1,
|
||||
b_required: 0,
|
||||
b_readonly: 0,
|
||||
b_disabled: 0,
|
||||
b_colspan: 24,
|
||||
b_xh: 30,
|
||||
},
|
||||
]
|
||||
const wrapper = mountEdit({ editConfig: rows })
|
||||
await nextTick()
|
||||
|
||||
// 第一步:选中 f2 卡片,点属性面板「同行配对」
|
||||
await wrapper.find('[data-row-id="a2"]').trigger('click')
|
||||
await nextTick()
|
||||
await wrapper.find('.mm-fdesign__pair-btn').trigger('click')
|
||||
await nextTick()
|
||||
// 配对进行中:提示条出现、卡片高亮
|
||||
expect(wrapper.find('.mm-fdesign__pair-hint').exists()).toBe(true)
|
||||
expect(wrapper.find('[data-row-id="a2"]').classes()).toContain('is-pairing')
|
||||
|
||||
// 第二步:选中 f3 卡片,再点「同行配对」
|
||||
await wrapper.find('[data-row-id="a3"]').trigger('click')
|
||||
await nextTick()
|
||||
await wrapper.find('.mm-fdesign__pair-btn').trigger('click')
|
||||
await nextTick()
|
||||
|
||||
const updates = wrapper.emitted('update')
|
||||
const last = updates[updates.length - 1][0]
|
||||
expect(last.find((r) => r.b_field_id === 'f2').b_colspan).toBe(12)
|
||||
expect(last.find((r) => r.b_field_id === 'f3').b_colspan).toBe(12)
|
||||
expect(last.find((r) => r.b_field_id === 'f1').b_colspan).toBe(24)
|
||||
// 两字段移到相邻(保持原有先后顺序)
|
||||
expect(last.map((r) => r.b_field_id)).toEqual(['f1', 'f2', 'f3'])
|
||||
})
|
||||
|
||||
it('空分组可放置:拖入后归属新分组', async () => {
|
||||
const extraGroups = [...groups, { b_id: 'g2', b_title: '附加信息', b_xh: 20, b_canuse: 1 }]
|
||||
const extraFields = [
|
||||
@@ -1780,7 +1759,7 @@ describe('ModuleEditConfigPanel(表单设计视图)', () => {
|
||||
await wrapper.find('.mm-fdesign__field[data-field-id="f1"]').trigger('click')
|
||||
await nextTick()
|
||||
|
||||
const input = wrapper.find('input[aria-label="自定义栅格宽度"]')
|
||||
const input = wrapper.find('input[aria-label="栅格宽度"]')
|
||||
await input.setValue('16')
|
||||
await input.trigger('change')
|
||||
await nextTick()
|
||||
@@ -2186,7 +2165,7 @@ describe('ModuleEditConfigPanel(表单设计视图)', () => {
|
||||
await nextTick()
|
||||
await wrapper.find('.mm-fdesign__field[data-field-id="f1"]').trigger('click')
|
||||
await nextTick()
|
||||
const input = wrapper.find('input[aria-label="自定义栅格宽度"]')
|
||||
const input = wrapper.find('input[aria-label="栅格宽度"]')
|
||||
await input.setValue('12') // input 事件即时生效
|
||||
await nextTick()
|
||||
expect(wrapper.emitted('update').at(-1)[0].find((r) => r.b_field_id === 'f1').b_colspan).toBe(12)
|
||||
@@ -2288,32 +2267,19 @@ describe('ModuleEditConfigPanel(表单设计视图)', () => {
|
||||
expect(last.map((r) => r.b_field_id)).toEqual(['f2', 'f3', 'f4', 'f1'])
|
||||
})
|
||||
|
||||
it('栅格宽度步进按钮:+/- 调整并联动压缩同行', async () => {
|
||||
it('栅格宽度输入框:直接输入调整并联动压缩同行', async () => {
|
||||
const rows = [mkRow('a1', 'f1', 'g1', 12, 10), mkRow('a2', 'f2', 'g1', 12, 20)]
|
||||
const wrapper = mountEdit({ editConfig: rows })
|
||||
await nextTick()
|
||||
await wrapper.find('[data-row-id="a1"]').trigger('click')
|
||||
await nextTick()
|
||||
|
||||
await wrapper.find('button[aria-label="栅格宽度加一"]').trigger('click')
|
||||
const input = wrapper.find('input[aria-label="栅格宽度"]')
|
||||
await input.setValue('16')
|
||||
await nextTick()
|
||||
let last = wrapper.emitted('update').at(-1)[0]
|
||||
expect(last.find((r) => r.b_id === 'a1').b_colspan).toBe(13)
|
||||
expect(last.find((r) => r.b_id === 'a2').b_colspan).toBe(11) // 24-13 联动压缩
|
||||
|
||||
await wrapper.find('button[aria-label="栅格宽度减一"]').trigger('click')
|
||||
await nextTick()
|
||||
last = wrapper.emitted('update').at(-1)[0]
|
||||
expect(last.find((r) => r.b_id === 'a1').b_colspan).toBe(12)
|
||||
})
|
||||
|
||||
it('属性面板显示本行栅格占用合计', async () => {
|
||||
const rows = [mkRow('a1', 'f1', 'g1', 12, 10), mkRow('a2', 'f2', 'g1', 12, 20)]
|
||||
const wrapper = mountEdit({ editConfig: rows })
|
||||
await nextTick()
|
||||
await wrapper.find('[data-row-id="a1"]').trigger('click')
|
||||
await nextTick()
|
||||
expect(wrapper.find('.mm-fdesign__span-usage').text()).toBe('本行 24/24')
|
||||
const last = wrapper.emitted('update').at(-1)[0]
|
||||
expect(last.find((r) => r.b_id === 'a1').b_colspan).toBe(16)
|
||||
expect(last.find((r) => r.b_id === 'a2').b_colspan).toBe(8) // 24-16 联动压缩
|
||||
})
|
||||
|
||||
it('卡片标签快捷开关:点「必」「显」直接切换并 emit update', async () => {
|
||||
@@ -2332,18 +2298,21 @@ describe('ModuleEditConfigPanel(表单设计视图)', () => {
|
||||
expect(card.classes()).toContain('is-invisible')
|
||||
})
|
||||
|
||||
it('复制属性 / 粘贴属性:把 f1 的布局状态套用到 f2', async () => {
|
||||
it('Ctrl+C / Ctrl+V:复制选中字段属性,选中其它字段粘贴', async () => {
|
||||
const wrapper = mountEdit()
|
||||
await nextTick()
|
||||
await wrapper.find('.mm-fdesign__field[data-field-id="f1"]').trigger('click')
|
||||
await nextTick()
|
||||
await wrapper.find('.mm-fdesign__clip-btn').trigger('click') // 复制
|
||||
window.dispatchEvent(
|
||||
new KeyboardEvent('keydown', { key: 'c', ctrlKey: true, bubbles: true }),
|
||||
)
|
||||
await nextTick()
|
||||
expect(wrapper.find('.mm-fdesign__clip-hint').exists()).toBe(true)
|
||||
|
||||
await wrapper.find('.mm-fdesign__field[data-field-id="f2"]').trigger('click')
|
||||
await nextTick()
|
||||
await wrapper.findAll('.mm-fdesign__clip-btn')[1].trigger('click') // 粘贴
|
||||
window.dispatchEvent(
|
||||
new KeyboardEvent('keydown', { key: 'v', ctrlKey: true, bubbles: true }),
|
||||
)
|
||||
await nextTick()
|
||||
const last = wrapper.emitted('update').at(-1)[0]
|
||||
const f2 = last.find((r) => r.b_field_id === 'f2')
|
||||
@@ -2351,6 +2320,32 @@ describe('ModuleEditConfigPanel(表单设计视图)', () => {
|
||||
expect(f2.b_colspan).toBe(24)
|
||||
})
|
||||
|
||||
it('Ctrl+X 剪切:复制属性后直接删除当前卡片,可粘贴到其它字段', async () => {
|
||||
const wrapper = mountEdit()
|
||||
await nextTick()
|
||||
await wrapper.find('.mm-fdesign__field[data-field-id="f1"]').trigger('click')
|
||||
await nextTick()
|
||||
window.dispatchEvent(
|
||||
new KeyboardEvent('keydown', { key: 'x', ctrlKey: true, bubbles: true }),
|
||||
)
|
||||
await nextTick()
|
||||
// f1 已被删除
|
||||
let last = wrapper.emitted('update').at(-1)[0]
|
||||
expect(last.some((r) => r.b_field_id === 'f1')).toBe(false)
|
||||
|
||||
// 选中 f2 后 Ctrl+V 粘贴 f1 的属性
|
||||
await wrapper.find('.mm-fdesign__field[data-field-id="f2"]').trigger('click')
|
||||
await nextTick()
|
||||
window.dispatchEvent(
|
||||
new KeyboardEvent('keydown', { key: 'v', ctrlKey: true, bubbles: true }),
|
||||
)
|
||||
await nextTick()
|
||||
last = wrapper.emitted('update').at(-1)[0]
|
||||
const f2 = last.find((r) => r.b_field_id === 'f2')
|
||||
expect(f2.b_required).toBe(1) // f1 required=1 → 套用到 f2
|
||||
expect(f2.b_colspan).toBe(24)
|
||||
})
|
||||
|
||||
it('字段库按控件类型分组展示,字段顺序与总数不变', async () => {
|
||||
const extraFields = [
|
||||
...fields,
|
||||
@@ -2426,3 +2421,587 @@ describe('ModuleEditConfigPanel(表单设计视图)', () => {
|
||||
expect(wrapper.find('.mm-fdesign__inspector .mm-fdesign__subhead').text()).toContain('金额')
|
||||
})
|
||||
})
|
||||
|
||||
// 带一个分组(g1 金额信息)的子表挂载数据:前两列在组内,第三列未分组
|
||||
const groupFixture = (rows) => ({
|
||||
groups: [
|
||||
{
|
||||
b_id: 'g1',
|
||||
b_module_id: '2',
|
||||
b_parent_id: null,
|
||||
b_title: '金额信息',
|
||||
b_i18n: null,
|
||||
b_layout_direction: 'vertical',
|
||||
b_xh: 10,
|
||||
b_canuse: 1,
|
||||
},
|
||||
],
|
||||
editConfig: rows.map((r, i) => ({ ...r, b_group_id: i < 2 ? 'g1' : null })),
|
||||
})
|
||||
|
||||
// 列分区列表谓词:列表元素均为编辑行(含 b_field_id,与字段库的 b_field 区分)
|
||||
const isColumnList = (c) => {
|
||||
const l = c.props('list')
|
||||
return Array.isArray(l) && l.length > 0 && l.every((i) => i.b_field_id != null)
|
||||
}
|
||||
|
||||
describe('ModuleEditConfigPanel(子表表格设计)', () => {
|
||||
// 预览弹窗经 Modal Teleport 渲染到 body;测试结束后主动关闭,
|
||||
// 避免残留的旧弹窗手柄被后续测试的 document.body 查询命中
|
||||
afterEach(() => {
|
||||
document.body
|
||||
.querySelectorAll('button.fms-modal-header-btn[aria-label="关闭"]')
|
||||
.forEach((btn) => btn.click())
|
||||
})
|
||||
|
||||
const tableRows = [
|
||||
{
|
||||
b_id: 'e1',
|
||||
b_module_id: '2',
|
||||
b_field_id: 'f1',
|
||||
b_group_id: null,
|
||||
b_visible: 1,
|
||||
b_required: 1,
|
||||
b_readonly: 0,
|
||||
b_disabled: 0,
|
||||
b_width: 160,
|
||||
b_xh: 10,
|
||||
},
|
||||
{
|
||||
b_id: 'e2',
|
||||
b_module_id: '2',
|
||||
b_field_id: 'f2',
|
||||
b_group_id: null,
|
||||
b_visible: 1,
|
||||
b_required: 0,
|
||||
b_readonly: 0,
|
||||
b_disabled: 0,
|
||||
b_width: 140,
|
||||
b_xh: 20,
|
||||
},
|
||||
{
|
||||
b_id: 'e3',
|
||||
b_module_id: '2',
|
||||
b_field_id: 'f3',
|
||||
b_group_id: null,
|
||||
b_visible: 0,
|
||||
b_required: 0,
|
||||
b_readonly: 0,
|
||||
b_disabled: 1,
|
||||
b_width: 160,
|
||||
b_xh: 30,
|
||||
},
|
||||
]
|
||||
const fields = [
|
||||
{ b_id: 'f1', b_field: 'order_no', b_name: '订单编号', b_type: 'input', b_canuse: 1 },
|
||||
{ b_id: 'f2', b_field: 'amount', b_name: '订单金额', b_type: 'money', b_canuse: 1 },
|
||||
{ b_id: 'f3', b_field: 'status', b_name: '订单状态', b_type: 'select', b_canuse: 1 },
|
||||
{ b_id: 'f4', b_field: 'remark', b_name: '备注', b_type: 'textarea', b_canuse: 1 },
|
||||
]
|
||||
const mountTableEdit = (overrides = {}) =>
|
||||
mount(ModuleEditConfigPanel, {
|
||||
props: {
|
||||
moduleId: '2',
|
||||
editConfig: tableRows,
|
||||
listConfig: [],
|
||||
queryConfig: [],
|
||||
fields,
|
||||
groups: [],
|
||||
referencedGroupIds: [],
|
||||
editMode: 'table',
|
||||
loading: false,
|
||||
...overrides,
|
||||
},
|
||||
global: {
|
||||
stubs: {
|
||||
FmsTable: {
|
||||
name: 'FmsTable',
|
||||
props: ['columns'],
|
||||
template: '<div class="stub-fmstable" />',
|
||||
},
|
||||
FieldGroupManager: true,
|
||||
Draggable: stubDraggable,
|
||||
},
|
||||
},
|
||||
attachTo: document.body,
|
||||
})
|
||||
|
||||
// 列清单 draggable:列表元素均为编辑行(含 b_field_id,与字段库的 b_field 区分)
|
||||
function columnDraggableOf(wrapper) {
|
||||
return wrapper.findAllComponents(stubDraggable).find((c) => {
|
||||
const l = c.props('list')
|
||||
return Array.isArray(l) && l.length > 0 && l.every((i) => i.b_field_id != null)
|
||||
})
|
||||
}
|
||||
|
||||
it('表格模式:纵向列卡片列表按分区展示,隐藏表单画布 / 分组管理 / 容器/说明文字', async () => {
|
||||
const wrapper = mountTableEdit()
|
||||
await nextTick()
|
||||
expect(wrapper.find('.mm-tdesign__sheet').exists()).toBe(true)
|
||||
expect(wrapper.findAll('.mm-tdesign__col')).toHaveLength(3)
|
||||
// 表单画布分区不存在(类名 .mm-fdesign__section,与子表分区 .mm-tdesign__section 区分)
|
||||
expect(wrapper.find('.mm-fdesign__section').exists()).toBe(false)
|
||||
expect(wrapper.text()).not.toContain('分组管理')
|
||||
// 子表布局组件区只有「表头分组」,不包含「分组容器」「说明文字」
|
||||
expect(wrapper.text()).not.toContain('分组容器')
|
||||
expect(wrapper.text()).not.toContain('说明文字')
|
||||
// 默认无分组,列在未分组区
|
||||
expect(wrapper.find('.mm-tdesign__section.is-ungrouped').exists()).toBe(true)
|
||||
// 工具栏:列数统计 + 隐藏列提示 + 预览按钮
|
||||
const toolbar = wrapper.find('.mm-tdesign__toolbar')
|
||||
expect(toolbar.text()).toContain('3')
|
||||
expect(toolbar.text()).toContain('1 列隐藏')
|
||||
expect(toolbar.find('.mm-tdesign__preview-btn').exists()).toBe(true)
|
||||
// 卡片按 b_xh 顺序展示名称/类型/列宽/必填星号,隐藏列带角标
|
||||
const cards = wrapper.findAll('.mm-tdesign__col')
|
||||
expect(cards[0].text()).toContain('订单编号')
|
||||
expect(cards[1].text()).toContain('订单金额')
|
||||
expect(cards[2].text()).toContain('订单状态')
|
||||
expect(cards[0].text()).toContain('160px')
|
||||
expect(cards[0].text()).toContain('输入框')
|
||||
expect(cards[0].text()).toContain('*')
|
||||
expect(cards[2].classes()).toContain('is-invisible')
|
||||
expect(cards[2].text()).toContain('隐藏')
|
||||
})
|
||||
|
||||
it('点击列卡片:选中并显示属性,步进/输入修改列宽 emit update(b_width)', async () => {
|
||||
const wrapper = mountTableEdit()
|
||||
await nextTick()
|
||||
const col = wrapper.find('.mm-tdesign__col[data-field-id="f2"]')
|
||||
await col.trigger('click')
|
||||
await nextTick()
|
||||
expect(col.classes()).toContain('is-selected')
|
||||
expect(wrapper.find('.mm-fdesign__inspector').text()).toContain('订单金额')
|
||||
// 列宽下拉当前值为 140(头部编辑方式 Select 与列宽 Select 并存,按 id 定位)
|
||||
expect(wrapper.findComponent('#mm-tdesign-width').props('modelValue')).toBe('140')
|
||||
|
||||
// 步进 +10
|
||||
await wrapper.find('button[aria-label="列宽加 10"]').trigger('click')
|
||||
await nextTick()
|
||||
let last = wrapper.emitted('update').at(-1)[0]
|
||||
expect(last.find((r) => r.b_field_id === 'f2').b_width).toBe(150)
|
||||
|
||||
// 数字输入自定义列宽
|
||||
await wrapper.find('input[aria-label="自定义列宽"]').setValue('200')
|
||||
await nextTick()
|
||||
last = wrapper.emitted('update').at(-1)[0]
|
||||
expect(last.find((r) => r.b_field_id === 'f2').b_width).toBe(200)
|
||||
})
|
||||
|
||||
it('字段库点击添加列:默认列宽按字段类型生成并自动选中', async () => {
|
||||
const wrapper = mountTableEdit()
|
||||
await nextTick()
|
||||
const remark = wrapper
|
||||
.findAll('.mm-fdesign__lib-item')
|
||||
.find((el) => el.text().includes('备注'))
|
||||
await remark.trigger('click')
|
||||
await nextTick()
|
||||
const last = wrapper.emitted('update').at(-1)[0]
|
||||
const row = last.find((r) => r.b_field_id === 'f4')
|
||||
expect(row).toBeTruthy()
|
||||
expect(row.b_width).toBe(220) // textarea 默认列宽 220
|
||||
expect(row.b_visible).toBe(1)
|
||||
expect(wrapper.find('.mm-tdesign__col[data-field-id="f4"]').classes()).toContain('is-selected')
|
||||
})
|
||||
|
||||
it('预览子表弹窗:打开显示真实表格(冻结列 + 样例控件),可关闭', async () => {
|
||||
const wrapper = mountTableEdit()
|
||||
await nextTick()
|
||||
await wrapper.find('.mm-tdesign__preview-btn').trigger('click')
|
||||
await nextTick()
|
||||
// Modal 经 Teleport 渲染到 body
|
||||
const table = document.body.querySelector('.mm-tdesign__preview-wrap .mm-tdesign__table')
|
||||
expect(table).toBeTruthy()
|
||||
const heads = document.body.querySelectorAll('.mm-tdesign__head-cell')
|
||||
expect(heads).toHaveLength(3)
|
||||
expect(heads[0].textContent).toContain('订单编号')
|
||||
expect(heads[0].textContent).toContain('160')
|
||||
// 样例数据行:真实控件外观 + 冻结列(分组行 + 列名行 + 数据行,共 3 行 × 2 冻结列)
|
||||
expect(document.body.querySelectorAll('.mm-tdesign__cell')).toHaveLength(3)
|
||||
expect(document.body.querySelector('.mm-tdesign__sample.is-money').textContent).toContain('¥')
|
||||
expect(document.body.querySelectorAll('.mm-tdesign__frozen')).toHaveLength(6)
|
||||
// 无分组时第一级表头只有一个空标题分组格
|
||||
const groupCells = document.body.querySelectorAll('.mm-tdesign__group-cell')
|
||||
expect(groupCells).toHaveLength(1)
|
||||
expect(groupCells[0].classList.contains('is-unnamed')).toBe(true)
|
||||
// 关闭弹窗
|
||||
document.body.querySelector('button.fms-modal-header-btn[aria-label="关闭"]').click()
|
||||
await nextTick()
|
||||
expect(document.body.querySelector('.mm-tdesign__preview-wrap')).toBeFalsy()
|
||||
})
|
||||
|
||||
it('列清单拖拽排序:end 后重排 b_xh 并 emit update', async () => {
|
||||
const wrapper = mountTableEdit()
|
||||
await nextTick()
|
||||
const list = columnDraggableOf(wrapper)
|
||||
expect(list).toBeTruthy()
|
||||
list.vm.$emit('start', { item: itemEl('f1') })
|
||||
// 模拟 SortableJS 就地重排:把 e1 移到末尾
|
||||
const arr = list.props('list')
|
||||
const [moved] = arr.splice(0, 1)
|
||||
arr.push(moved)
|
||||
list.vm.$emit('end')
|
||||
await nextTick()
|
||||
const last = wrapper.emitted('update').at(-1)[0]
|
||||
expect(last.map((r) => r.b_field_id)).toEqual(['f2', 'f3', 'f1'])
|
||||
expect(last.map((r) => r.b_xh)).toEqual([10, 20, 30])
|
||||
})
|
||||
|
||||
it('字段库克隆 add 进列清单:重排序号并选中新列', async () => {
|
||||
const wrapper = mountTableEdit()
|
||||
await nextTick()
|
||||
const list = columnDraggableOf(wrapper)
|
||||
const arr = list.props('list')
|
||||
arr.push({
|
||||
b_id: 'e9',
|
||||
b_module_id: '2',
|
||||
b_field_id: 'f4',
|
||||
b_group_id: null,
|
||||
b_visible: 1,
|
||||
b_required: 0,
|
||||
b_readonly: 0,
|
||||
b_disabled: 0,
|
||||
b_width: 220,
|
||||
b_xh: 0,
|
||||
})
|
||||
// 模拟 SortableJS add 事件:from = 字段库列表,to = 列分组列表(未分组)
|
||||
list.vm.$emit('add', {
|
||||
newIndex: arr.length - 1,
|
||||
from: { classList: { contains: () => true } },
|
||||
to: { dataset: { groupId: 'ungrouped' }, classList: { contains: () => false } },
|
||||
})
|
||||
await nextTick()
|
||||
const last = wrapper.emitted('update').at(-1)[0]
|
||||
expect(last.map((r) => r.b_field_id)).toEqual(['f1', 'f2', 'f3', 'f4'])
|
||||
expect(last.find((r) => r.b_field_id === 'f4').b_xh).toBe(40)
|
||||
expect(wrapper.find('.mm-tdesign__col[data-field-id="f4"]').classes()).toContain('is-selected')
|
||||
})
|
||||
|
||||
it('字段库克隆 add 重复字段:警告并移除新行(不 emit update)', async () => {
|
||||
const wrapper = mountTableEdit()
|
||||
await nextTick()
|
||||
const list = columnDraggableOf(wrapper)
|
||||
const arr = list.props('list')
|
||||
arr.push({
|
||||
b_id: 'e9',
|
||||
b_module_id: '2',
|
||||
b_field_id: 'f2',
|
||||
b_group_id: null,
|
||||
b_visible: 1,
|
||||
b_required: 0,
|
||||
b_readonly: 0,
|
||||
b_disabled: 0,
|
||||
b_width: 140,
|
||||
b_xh: 0,
|
||||
})
|
||||
list.vm.$emit('add', {
|
||||
newIndex: arr.length - 1,
|
||||
from: { classList: { contains: () => true } },
|
||||
to: { dataset: { groupId: 'ungrouped' }, classList: { contains: () => false } },
|
||||
})
|
||||
await nextTick()
|
||||
expect(Message.warning).toHaveBeenCalled()
|
||||
// 重复行被移除,f2 仍只有一行;未提交变更(无 update 事件)
|
||||
expect(arr.filter((r) => r.b_field_id === 'f2')).toHaveLength(1)
|
||||
expect(arr).toHaveLength(3)
|
||||
expect(wrapper.emitted('update')).toBeUndefined()
|
||||
})
|
||||
|
||||
it('数据视图:表格模式隐藏分组/栅格/占位符列,显示列宽列', async () => {
|
||||
const wrapper = mountTableEdit()
|
||||
await nextTick()
|
||||
await wrapper.find('button[data-view="data"]').trigger('click')
|
||||
await nextTick()
|
||||
const table = wrapper.findComponent({ name: 'FmsTable' })
|
||||
const colKeys = table.props('columns').map((c) => c.dataIndex)
|
||||
expect(colKeys).toContain('b_width')
|
||||
expect(colKeys).not.toContain('b_group_id')
|
||||
expect(colKeys).not.toContain('b_colspan')
|
||||
expect(colKeys).not.toContain('b_placeholder')
|
||||
expect(colKeys).not.toContain('b_height')
|
||||
})
|
||||
|
||||
// 带一个分组(g1 金额信息)的挂载:f1/f2 在组内,f3 未分组
|
||||
|
||||
it('头部编辑方式下拉:显示表单设计/表格设计,切换 emit update:editMode', async () => {
|
||||
const wrapper = mountTableEdit()
|
||||
await nextTick()
|
||||
// 第一个 Select 为头部编辑方式(modelValue = props.editMode)
|
||||
const modeSelect = wrapper.findAllComponents({ name: 'Select' })[0]
|
||||
expect(modeSelect.props('modelValue')).toBe('table')
|
||||
modeSelect.vm.$emit('update:model-value', 'form')
|
||||
await nextTick()
|
||||
expect(wrapper.emitted('update:editMode').at(-1)[0]).toBe('form')
|
||||
})
|
||||
|
||||
it('拖拽中隐藏空分组提示(避免与拖拽占位重叠显示两行)', async () => {
|
||||
// 预置:空分组 g1 + 未分组列 f1
|
||||
const wrapper = mountTableEdit({
|
||||
groups: [
|
||||
{
|
||||
b_id: 'g1',
|
||||
b_module_id: '2',
|
||||
b_parent_id: null,
|
||||
b_title: '空组',
|
||||
b_i18n: null,
|
||||
b_layout_direction: 'vertical',
|
||||
b_xh: 10,
|
||||
b_canuse: 1,
|
||||
},
|
||||
],
|
||||
editConfig: [tableRows[0]],
|
||||
})
|
||||
await nextTick()
|
||||
// 拖拽前:空分组显示拖入提示
|
||||
expect(wrapper.find('.mm-tdesign__section-drop-hint').text()).toContain('空分组')
|
||||
// 模拟拖拽开始(dragPayload 置位)→ 提示隐藏
|
||||
const list = columnDraggableOf(wrapper)
|
||||
list.vm.$emit('start', { item: itemEl('f1') })
|
||||
await nextTick()
|
||||
expect(wrapper.find('.mm-tdesign__section-drop-hint').exists()).toBe(false)
|
||||
list.vm.$emit('end')
|
||||
await nextTick()
|
||||
})
|
||||
|
||||
it('字段库点击添加:自动滚动到新列位置', async () => {
|
||||
const scrollSpy = vi.spyOn(Element.prototype, 'scrollIntoView').mockImplementation(() => {})
|
||||
try {
|
||||
const wrapper = mountTableEdit()
|
||||
await nextTick()
|
||||
const remark = wrapper
|
||||
.findAll('.mm-fdesign__lib-item')
|
||||
.find((el) => el.text().includes('备注'))
|
||||
await remark.trigger('click')
|
||||
await nextTick()
|
||||
await nextTick()
|
||||
expect(scrollSpy).toHaveBeenCalled()
|
||||
// 滚动的目标为新列卡片
|
||||
const target = scrollSpy.mock.instances[scrollSpy.mock.instances.length - 1]
|
||||
expect(target.className).toContain('mm-tdesign__col')
|
||||
} finally {
|
||||
scrollSpy.mockRestore()
|
||||
}
|
||||
})
|
||||
|
||||
it('添加表头分组:emit updateGroups,新空分区出现', async () => {
|
||||
const wrapper = mountTableEdit()
|
||||
await nextTick()
|
||||
await wrapper.find('.mm-tdesign__add-group').trigger('click')
|
||||
await nextTick()
|
||||
const newGroups = wrapper.emitted('updateGroups').at(-1)[0]
|
||||
expect(newGroups).toHaveLength(1)
|
||||
expect(newGroups[0].b_title).toBe('新分组')
|
||||
// 父组件响应 updateGroups 后,画布渲染新分组(空分区拖入提示)
|
||||
await wrapper.setProps({ groups: newGroups })
|
||||
await nextTick()
|
||||
const titles = wrapper.findAll('.mm-tdesign__section-title').map((t) => t.text())
|
||||
expect(titles.some((t) => t.includes('新分组'))).toBe(true)
|
||||
expect(wrapper.find('.mm-tdesign__section-drop-hint').text()).toContain('空分组')
|
||||
})
|
||||
|
||||
it('字段库已添加字段标记 data-added(拖拽被 filter 拦截,已添加字段不可再拖)', async () => {
|
||||
const wrapper = mountTableEdit()
|
||||
await nextTick()
|
||||
// f2 已在列中 → data-added=true(filter 选择器命中,mousedown 不启动拖拽)
|
||||
expect(wrapper.find('.mm-fdesign__lib-item[data-field-id="f2"]').attributes('data-added')).toBe(
|
||||
'true',
|
||||
)
|
||||
// f4 未加入 → data-added=false
|
||||
expect(wrapper.find('.mm-fdesign__lib-item[data-field-id="f4"]').attributes('data-added')).toBe(
|
||||
'false',
|
||||
)
|
||||
})
|
||||
|
||||
it('字段库拖入已存在字段到其他分组:拒绝并移除克隆(防重查全部列,不只目标组)', async () => {
|
||||
// 预置:f2 在分组 g1,g2 为空分组,f1 未分组
|
||||
const wrapper = mountTableEdit({
|
||||
groups: [
|
||||
{
|
||||
b_id: 'g1',
|
||||
b_module_id: '2',
|
||||
b_parent_id: null,
|
||||
b_title: '金额信息',
|
||||
b_i18n: null,
|
||||
b_layout_direction: 'vertical',
|
||||
b_xh: 10,
|
||||
b_canuse: 1,
|
||||
},
|
||||
{
|
||||
b_id: 'g2',
|
||||
b_module_id: '2',
|
||||
b_parent_id: null,
|
||||
b_title: '空组',
|
||||
b_i18n: null,
|
||||
b_layout_direction: 'vertical',
|
||||
b_xh: 20,
|
||||
b_canuse: 1,
|
||||
},
|
||||
],
|
||||
editConfig: [
|
||||
{ ...tableRows[1], b_group_id: 'g1', b_xh: 10 }, // f2 在 g1
|
||||
{ ...tableRows[0], b_group_id: null, b_xh: 20 }, // f1 未分组
|
||||
],
|
||||
})
|
||||
await nextTick()
|
||||
// 空分组 g2 的 draggable(list 为空数组)
|
||||
const g2List = wrapper
|
||||
.findAllComponents(stubDraggable)
|
||||
.find((c) => Array.isArray(c.props('list')) && c.props('list').length === 0)
|
||||
expect(g2List).toBeTruthy()
|
||||
const arr = g2List.props('list')
|
||||
arr.push({
|
||||
b_id: 'e9',
|
||||
b_module_id: '2',
|
||||
b_field_id: 'f2', // 已在 g1 存在
|
||||
b_group_id: null,
|
||||
b_visible: 1,
|
||||
b_required: 0,
|
||||
b_readonly: 0,
|
||||
b_disabled: 0,
|
||||
b_width: 140,
|
||||
b_xh: 0,
|
||||
})
|
||||
g2List.vm.$emit('add', {
|
||||
newIndex: 0,
|
||||
from: { classList: { contains: () => true } },
|
||||
to: { dataset: { groupId: 'g2' }, classList: { contains: () => false } },
|
||||
})
|
||||
await nextTick()
|
||||
expect(Message.warning).toHaveBeenCalled()
|
||||
// 克隆被移除,未提交变更
|
||||
expect(arr).toHaveLength(0)
|
||||
expect(wrapper.emitted('update')).toBeUndefined()
|
||||
})
|
||||
|
||||
it('跨组拖拽:列拖入分组后 @end 同步 b_group_id 并按分组顺序重排', async () => {
|
||||
const wrapper = mountTableEdit(groupFixture(tableRows))
|
||||
await nextTick()
|
||||
// 定位分区列表:g1(2 列,均含 b_field_id)与未分组(1 列)
|
||||
const lists = wrapper.findAllComponents(stubDraggable).filter(isColumnList)
|
||||
const g1List = lists.find((c) => c.props('list').length === 2)
|
||||
const ungroupedList = lists.find((c) => c.props('list').length === 1)
|
||||
expect(g1List).toBeTruthy()
|
||||
expect(ungroupedList).toBeTruthy()
|
||||
// 模拟 SortableJS 跨组移动:f3 从未分组移入 g1 末尾
|
||||
const srcArr = ungroupedList.props('list')
|
||||
const [moved] = srcArr.splice(0, 1)
|
||||
const g1Arr = g1List.props('list')
|
||||
g1Arr.push(moved)
|
||||
g1List.vm.$emit('add', {
|
||||
newIndex: g1Arr.length - 1,
|
||||
from: { classList: { contains: () => false } },
|
||||
to: { dataset: { groupId: 'g1' }, classList: { contains: () => false } },
|
||||
})
|
||||
ungroupedList.vm.$emit('end')
|
||||
await nextTick()
|
||||
const last = wrapper.emitted('update').at(-1)[0]
|
||||
expect(last.map((r) => r.b_field_id)).toEqual(['f1', 'f2', 'f3'])
|
||||
expect(last.find((r) => r.b_field_id === 'f3').b_group_id).toBe('g1')
|
||||
expect(last.map((r) => r.b_xh)).toEqual([10, 20, 30])
|
||||
// 画布上 f3 已进入分组分区
|
||||
expect(g1List.props('list').map((r) => r.b_field_id)).toEqual(['f1', 'f2', 'f3'])
|
||||
})
|
||||
|
||||
it('预览弹窗:有分组时渲染两级表头(分组名跨列 = 组内列宽之和)', async () => {
|
||||
const wrapper = mountTableEdit(groupFixture(tableRows))
|
||||
await nextTick()
|
||||
await wrapper.find('.mm-tdesign__preview-btn').trigger('click')
|
||||
await nextTick()
|
||||
const groupCells = document.body.querySelectorAll('.mm-tdesign__group-cell')
|
||||
expect(groupCells).toHaveLength(2) // 金额信息 + 未分组列
|
||||
expect(groupCells[0].textContent).toContain('金额信息')
|
||||
expect(groupCells[0].style.width).toBe('300px') // 160 + 140
|
||||
expect(groupCells[1].classList.contains('is-unnamed')).toBe(true)
|
||||
expect(groupCells[1].style.width).toBe('160px')
|
||||
// 列名行仍在
|
||||
expect(document.body.querySelectorAll('.mm-tdesign__head-cell')).toHaveLength(3)
|
||||
document.body.querySelector('button.fms-modal-header-btn[aria-label="关闭"]').click()
|
||||
await nextTick()
|
||||
})
|
||||
|
||||
// 打开预览弹窗(表格经 Modal Teleport 渲染到 body),返回表格元素
|
||||
async function openPreview(wrapper) {
|
||||
await wrapper.find('.mm-tdesign__preview-btn').trigger('click')
|
||||
await nextTick()
|
||||
return document.body.querySelector('.mm-tdesign__preview-wrap .mm-tdesign__table')
|
||||
}
|
||||
|
||||
function previewHandle(fieldId) {
|
||||
return document.body.querySelector(`.mm-tdesign__resize-handle[data-field-id="${fieldId}"]`)
|
||||
}
|
||||
|
||||
it('预览弹窗拖拽调整列宽:实时更新表头,松手后 emit update(b_width)', async () => {
|
||||
const wrapper = mountTableEdit()
|
||||
await nextTick()
|
||||
await openPreview(wrapper)
|
||||
const handle = previewHandle('f2')
|
||||
expect(handle).toBeTruthy()
|
||||
handle.dispatchEvent(new MouseEvent('mousedown', { clientX: 100, bubbles: true }))
|
||||
// 拖拽中:仅本地实时改宽(表头列宽变化),不提交
|
||||
window.dispatchEvent(new MouseEvent('mousemove', { clientX: 160 }))
|
||||
await nextTick()
|
||||
expect(wrapper.emitted('update')).toBeUndefined()
|
||||
const resizingCol = document.body.querySelector('.mm-tdesign__head-cell.is-resizing-col')
|
||||
expect(resizingCol.attributes['style'].value).toContain('width: 200px')
|
||||
// 松手:提交新宽度并自动选中该列
|
||||
window.dispatchEvent(new MouseEvent('mouseup', { clientX: 160 }))
|
||||
await nextTick()
|
||||
const last = wrapper.emitted('update').at(-1)[0]
|
||||
expect(last.find((r) => r.b_field_id === 'f2').b_width).toBe(200)
|
||||
expect(wrapper.find('.mm-tdesign__col[data-field-id="f2"]').classes()).toContain('is-selected')
|
||||
})
|
||||
|
||||
it('预览弹窗列宽拖拽限制在 40–600px', async () => {
|
||||
const wrapper = mountTableEdit()
|
||||
await nextTick()
|
||||
await openPreview(wrapper)
|
||||
const handle = previewHandle('f1')
|
||||
// 向左拖到极限 → 40
|
||||
handle.dispatchEvent(new MouseEvent('mousedown', { clientX: 100, bubbles: true }))
|
||||
window.dispatchEvent(new MouseEvent('mousemove', { clientX: -99999 }))
|
||||
window.dispatchEvent(new MouseEvent('mouseup', { clientX: -99999 }))
|
||||
await nextTick()
|
||||
let last = wrapper.emitted('update').at(-1)[0]
|
||||
expect(last.find((r) => r.b_field_id === 'f1').b_width).toBe(40)
|
||||
// 向右拖到极限 → 600
|
||||
handle.dispatchEvent(new MouseEvent('mousedown', { clientX: 100, bubbles: true }))
|
||||
window.dispatchEvent(new MouseEvent('mousemove', { clientX: 99999 }))
|
||||
window.dispatchEvent(new MouseEvent('mouseup', { clientX: 99999 }))
|
||||
await nextTick()
|
||||
last = wrapper.emitted('update').at(-1)[0]
|
||||
expect(last.find((r) => r.b_field_id === 'f1').b_width).toBe(600)
|
||||
})
|
||||
|
||||
it('预览弹窗列宽手柄键盘左右键微调 ±10px', async () => {
|
||||
const wrapper = mountTableEdit()
|
||||
await nextTick()
|
||||
await openPreview(wrapper)
|
||||
const handle = previewHandle('f2')
|
||||
handle.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }))
|
||||
await nextTick()
|
||||
let last = wrapper.emitted('update').at(-1)[0]
|
||||
expect(last.find((r) => r.b_field_id === 'f2').b_width).toBe(150)
|
||||
handle.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft', bubbles: true }))
|
||||
await nextTick()
|
||||
last = wrapper.emitted('update').at(-1)[0]
|
||||
expect(last.find((r) => r.b_field_id === 'f2').b_width).toBe(140)
|
||||
})
|
||||
|
||||
it('预览弹窗双击列宽手柄:恢复字段类型默认列宽', async () => {
|
||||
const wrapper = mountTableEdit()
|
||||
await nextTick()
|
||||
await openPreview(wrapper)
|
||||
const handle = previewHandle('f2')
|
||||
// 先拖到 300
|
||||
handle.dispatchEvent(new MouseEvent('mousedown', { clientX: 100, bubbles: true }))
|
||||
window.dispatchEvent(new MouseEvent('mousemove', { clientX: 260 }))
|
||||
window.dispatchEvent(new MouseEvent('mouseup', { clientX: 260 }))
|
||||
await nextTick()
|
||||
expect(wrapper.emitted('update').at(-1)[0].find((r) => r.b_field_id === 'f2').b_width).toBe(300)
|
||||
// 双击恢复 money 默认 140
|
||||
previewHandle('f2').dispatchEvent(new MouseEvent('dblclick', { bubbles: true }))
|
||||
await nextTick()
|
||||
const last = wrapper.emitted('update').at(-1)[0]
|
||||
expect(last.find((r) => r.b_field_id === 'f2').b_width).toBe(140)
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user