fix(admin): 完善弹窗滚动与表单交互布局
This commit is contained in:
@@ -53,6 +53,42 @@ const attachment: TruckAttachmentReference = { id: 'attachment-1', fileId: 'file
|
||||
beforeEach(() => { vi.clearAllMocks() })
|
||||
afterEach(() => { vi.restoreAllMocks(); document.body.innerHTML = '' })
|
||||
describe('TruckAttachmentDialog workflows', () => {
|
||||
it('keeps a long file selection and attachment actions usable across fullscreen and reopening', async () => {
|
||||
const fileName = '司机证件与车辆资料'.repeat(20) + '.pdf'
|
||||
const longAttachment = { ...attachment, fileName }
|
||||
vi.mocked(uploadTruckAppointmentAttachment).mockResolvedValue(longAttachment)
|
||||
const wrapper = mount(TruckAttachmentDialog, { props: { modelValue: true, appointmentId: 'appointment-internal', attachments: [longAttachment], canManage: true }, global: { plugins: [ElementPlus] }, attachTo: document.body })
|
||||
try {
|
||||
await flushPromises()
|
||||
const input = wrapper.get<HTMLInputElement>('.attachment-picker input[type="file"]')
|
||||
const file = new File(['data'], fileName, { type: 'application/pdf' })
|
||||
Object.defineProperty(input.element, 'files', { configurable: true, value: [file] })
|
||||
await input.trigger('change')
|
||||
await flushPromises()
|
||||
expect(wrapper.get('.attachment-picker .el-upload-list__item-name').text()).toContain(fileName)
|
||||
expect(wrapper.get('.attachment-row strong').text()).toBe(fileName)
|
||||
expect(wrapper.get('.attachment-row button').text()).toBe('删除')
|
||||
document.querySelector<HTMLButtonElement>('[aria-label="展开全屏"]')!.click()
|
||||
await flushPromises()
|
||||
expect(wrapper.get('.attachment-picker .el-upload-list__item-name').text()).toContain(fileName)
|
||||
document.querySelector<HTMLButtonElement>('[aria-label="退出全屏"]')!.click()
|
||||
await flushPromises()
|
||||
const upload = Array.from(document.querySelectorAll<HTMLButtonElement>('button')).find(button => button.textContent?.trim() === '上传并关联')!
|
||||
expect(upload.disabled).toBe(false)
|
||||
upload.click()
|
||||
await flushPromises()
|
||||
expect(uploadTruckAppointmentAttachment).toHaveBeenCalledExactlyOnceWith('appointment-internal', file, 'OTHER')
|
||||
await wrapper.setProps({ modelValue: false })
|
||||
await wrapper.setProps({ modelValue: true })
|
||||
await flushPromises()
|
||||
expect(document.querySelector('.el-dialog.is-fullscreen')).toBeNull()
|
||||
expect(wrapper.get('.attachment-row strong').text()).toBe(fileName)
|
||||
expect(deleteTruckAppointmentAttachment).not.toHaveBeenCalled()
|
||||
} finally {
|
||||
wrapper.unmount()
|
||||
}
|
||||
})
|
||||
|
||||
it('keeps attachment names readable through fullscreen and protects read-only access', async () => {
|
||||
const wrapper = mount(TruckAttachmentDialog, { props: { modelValue: true, appointmentId: 'appointment-internal', appointmentNo: 'TA-123', attachments: [attachment], canManage: false }, global: { plugins: [ElementPlus] }, attachTo: document.body })
|
||||
await flushPromises()
|
||||
|
||||
@@ -26,7 +26,7 @@ async function remove(item: TruckAttachmentReference) { if (busy.value || !props
|
||||
<AppDialog class="admin-density-dialog admin-workbench is-dialog" :model-value="props.modelValue" :title="attachmentDialogTitle('预约附件')" width="min(640px, 94vw)" fullscreenable :show-confirm="false" :close-on-click-modal="true" @update:model-value="emit('update:modelValue', $event)">
|
||||
<el-alert v-if="error" type="error" :closable="true" show-icon @close="error = null"><template #title>{{ error.message }}</template><ApiErrorMeta :details="error" /></el-alert>
|
||||
<div class="density-dialog-sections">
|
||||
<section v-if="props.canManage" class="density-dialog-section" data-tone="work"><h3 class="density-dialog-section__title">上传附件</h3><div class="upload-panel"><el-select v-model="selectedType" aria-label="附件类型" class="attachment-type"><el-option v-for="(label, type) in attachmentTypeLabels" :key="type" :label="label" :value="type" /></el-select><el-upload :auto-upload="false" :limit="1" :show-file-list="true" :on-change="selectFile" :on-remove="() => { selectedFile = null }"><el-button><FileUp :size="15" />选择附件</el-button></el-upload><el-button type="primary" :loading="busy" :disabled="!selectedFile" @click="upload">上传并关联</el-button></div></section>
|
||||
<section v-if="props.canManage" class="density-dialog-section" data-tone="work"><h3 class="density-dialog-section__title">上传附件</h3><div class="upload-panel"><el-select v-model="selectedType" aria-label="附件类型" class="attachment-type"><el-option v-for="(label, type) in attachmentTypeLabels" :key="type" :label="label" :value="type" /></el-select><el-upload class="attachment-picker" :auto-upload="false" :limit="1" :show-file-list="true" :on-change="selectFile" :on-remove="() => { selectedFile = null }"><el-button><FileUp :size="15" />选择附件</el-button></el-upload><el-button type="primary" :loading="busy" :disabled="!selectedFile" @click="upload">上传并关联</el-button></div></section>
|
||||
<section class="density-dialog-section" data-tone="source"><h3 class="density-dialog-section__title">现有附件 <small>共 {{ attachments.length }} 份</small></h3>
|
||||
<el-empty v-if="attachments.length === 0" description="暂无预约附件" :image-size="72" />
|
||||
<div v-for="item in attachments" :key="item.fileId" class="attachment-row">
|
||||
@@ -41,6 +41,8 @@ async function remove(item: TruckAttachmentReference) { if (busy.value || !props
|
||||
<style scoped>
|
||||
.upload-panel { display:flex; align-items:center; flex-wrap:wrap; gap:var(--admin-space-3); }
|
||||
.attachment-type { width:160px; }
|
||||
.attachment-picker { flex:1 1 220px; min-width:0; max-width:100%; }
|
||||
.upload-panel > .el-button, .attachment-row > .el-button { flex-shrink:0; }
|
||||
.attachment-row { display:flex; justify-content:space-between; gap:var(--admin-space-5); overflow-wrap:anywhere; margin:0; padding:var(--admin-space-3) 0; border:0; border-bottom:1px solid var(--workbench-border); border-radius:0; }.attachment-row small { display:block; margin-top:var(--admin-space-1); color:var(--el-text-color-secondary); }
|
||||
.attachment-row>div{min-width:0}.attachment-row strong{overflow-wrap:anywhere}
|
||||
@media (max-width: 560px) { .attachment-row { flex-direction:column; margin:0; padding:var(--admin-space-3) 0; border:0; border-bottom:1px solid var(--workbench-border); border-radius:0; } }
|
||||
|
||||
Reference in New Issue
Block a user