feat(fleet): integrate trip management and fee coverage workflows

This commit is contained in:
2026-10-03 04:35:55 +08:00
parent bca08f8749
commit dc35288a1b
87 changed files with 3774 additions and 233 deletions
+75
View File
@@ -0,0 +1,75 @@
import { h } from 'vue'
import { mount } from '@vue/test-utils'
import { ElOption, ElSelect } from 'element-plus'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { AdminSelect } from './AdminSelect'
const mounted: ReturnType<typeof mount>[] = []
const options = [
{ label: '洛杉矶仓', value: 'LA' },
{ label: '纽约仓', value: 'NY' },
]
function mountSelect(props: Record<string, unknown> = {}) {
const wrapper = mount(AdminSelect, {
attachTo: document.body,
props: { modelValue: '', teleported: false, ...props },
slots: {
default: () => options.map(option => h(ElOption, { ...option, key: option.value })),
header: () => h('span', { class: 'business-header' }, '选择仓库'),
},
})
mounted.push(wrapper)
return wrapper
}
afterEach(() => {
mounted.splice(0).forEach(wrapper => wrapper.unmount())
})
describe('Admin Element Plus select defaults', () => {
it('filters by the displayed label and emits the original value only after selection', async () => {
const wrapper = mountSelect()
await wrapper.find('.el-select__wrapper').trigger('click')
await wrapper.find('input').setValue('洛杉矶')
await vi.waitFor(() => {
const items = wrapper.findAll('.el-select-dropdown__item')
expect(items.filter(item => item.isVisible()).map(item => item.text())).toEqual(['洛杉矶仓'])
})
expect(wrapper.emitted('update:modelValue')).toBeUndefined()
await wrapper.findAll('.el-select-dropdown__item')[0]!.trigger('click')
expect(wrapper.emitted('update:modelValue')).toEqual([['LA']])
expect(wrapper.emitted('change')).toEqual([['LA']])
expect(wrapper.find('.business-header').text()).toBe('选择仓库')
expect(typeof wrapper.vm.focus).toBe('function')
expect(typeof wrapper.vm.blur).toBe('function')
})
it('keeps multiple selection and disabled controls provided by Element Plus', async () => {
const wrapper = mountSelect({ multiple: true, modelValue: ['LA'], disabled: true, size: 'small' })
expect(wrapper.classes()).toContain('el-select--small')
expect(wrapper.find('input').attributes('disabled')).toBeDefined()
await vi.waitFor(() => expect(wrapper.find('.el-tag').text()).toBe('洛杉矶仓'))
await wrapper.find('.el-select__wrapper').trigger('click')
expect(wrapper.find('input').attributes('aria-expanded')).toBe('false')
expect(wrapper.emitted('update:modelValue')).toBeUndefined()
})
it('continues to pass search terms to existing remote search handlers', async () => {
const remoteMethod = vi.fn()
const wrapper = mountSelect({ remote: true, remoteMethod, debounce: 0 })
await wrapper.find('.el-select__wrapper').trigger('click')
await wrapper.find('input').setValue('合作车队')
await vi.waitFor(() => expect(remoteMethod).toHaveBeenCalledWith('合作车队'))
expect(wrapper.emitted('update:modelValue')).toBeUndefined()
})
it('does not mutate Element Plus itself or discard an explicit field setting', () => {
const native = mount(ElSelect, { props: { modelValue: '', teleported: false } })
mounted.push(native)
expect(native.props('filterable')).toBe(false)
expect(mountSelect({ filterable: false }).props('filterable')).toBe(false)
})
})
+9
View File
@@ -0,0 +1,9 @@
import { ElSelect, selectProps } from 'element-plus'
// Keep Element Plus rendering, events, slots and exposed methods; only change the default.
export const AdminSelect = Object.assign({}, ElSelect, {
props: {
...selectProps,
filterable: { type: Boolean, default: true },
},
})
+4
View File
@@ -524,6 +524,10 @@ function setPage(value: number) {
.data-table--integrated .data-table__filters :deep(.el-input__wrapper),
.data-table--integrated .data-table__filters :deep(.el-select__wrapper),
.data-table--integrated .data-table__filters :deep(.el-button) { border-radius: 8px; }
/* Select's default wrapper uses a fixed 32px, unlike input and button sizing. */
.data-table--integrated .data-table__filters :deep(.el-select:not(.el-select--small):not(.el-select--large) .el-select__wrapper) {
min-height: var(--el-component-size);
}
.data-table--integrated .data-table__filters :deep(.el-button--primary:not(:disabled)) {
--el-button-bg-color: #1677ff;
--el-button-border-color: #1677ff;