feat(web-admin): open cert maintain dialog on reminder page

Keep users on the document reminder list by reusing vehicle/personnel
form dialogs instead of navigating away to base-info pages.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
wuzilongandCursor committed 2026-11-12 19:29:37 +08:00
1 parent fba478dcca
commit 01d607d766
4 files changed
+156 -120

No files matched your search

@@ -2,11 +2,24 @@ import assert from 'node:assert/strict'
import { describe, it } from 'node:test'
import {
resolveDocumentReminderEditPath,
resolveDocumentReminderFormMode,
DOCUMENT_REMINDER_JUMP_UNSUPPORTED
} from './pl-document-reminder-jump'
describe('证件提醒跳转路径', () => {
it('车辆按 vehicleType 分流自有与三方', () => {
describe('证件提醒表单模式与路径', () => {
it('车辆按 vehicleType 解析弹窗类型与路径', () => {
assert.deepEqual(
resolveDocumentReminderFormMode({ ownerType: 'vehicle', vehicleType: 'self' }),
{ kind: 'vehicle', vehicleType: 'self' }
)
assert.deepEqual(
resolveDocumentReminderFormMode({ ownerType: 'vehicle', vehicleType: 'carrier' }),
{ kind: 'vehicle', vehicleType: 'carrier' }
)
assert.deepEqual(resolveDocumentReminderFormMode({ ownerType: 'vehicle', vehicleType: '' }), {
kind: 'vehicle',
vehicleType: 'carrier'
})
assert.equal(
resolveDocumentReminderEditPath({ ownerType: 'vehicle', vehicleType: 'self' }),
'/vehicle-mgmt/base-info/self-vehicle'
@@ -15,19 +28,29 @@ describe('证件提醒跳转路径', () => {
resolveDocumentReminderEditPath({ ownerType: 'vehicle', vehicleType: 'carrier' }),
'/vehicle-mgmt/base-info/vehicle'
)
assert.equal(
resolveDocumentReminderEditPath({ ownerType: 'vehicle', vehicleType: '' }),
'/vehicle-mgmt/base-info/vehicle'
)
})
it('人员按 personnelAffiliation 分流', () => {
assert.equal(
resolveDocumentReminderEditPath({
it('人员按 personnelAffiliation 解析弹窗归属与路径', () => {
assert.deepEqual(
resolveDocumentReminderFormMode({
ownerType: 'personnel',
personnelAffiliation: 'self'
}),
'/vehicle-mgmt/base-info/personnel'
{ kind: 'personnel', affiliation: 'self' }
)
assert.deepEqual(
resolveDocumentReminderFormMode({
ownerType: 'personnel',
personnelAffiliation: 'carrier'
}),
{ kind: 'personnel', affiliation: 'carrier' }
)
assert.deepEqual(
resolveDocumentReminderFormMode({
ownerType: 'personnel',
personnelAffiliation: ''
}),
{ kind: 'personnel', affiliation: 'self' }
)
assert.equal(
resolveDocumentReminderEditPath({
@@ -36,17 +59,10 @@ describe('证件提醒跳转路径', () => {
}),
'/vehicle-mgmt/base-info/personnel-carrier'
)
assert.equal(
resolveDocumentReminderEditPath({
ownerType: 'personnel',
personnelAffiliation: ''
}),
'/vehicle-mgmt/base-info/personnel'
)
})
it('不支持的主体返回 null', () => {
assert.equal(resolveDocumentReminderEditPath({ ownerType: 'carrier' }), null)
assert.equal(resolveDocumentReminderFormMode({ ownerType: 'carrier' }), null)
assert.equal(resolveDocumentReminderEditPath({ ownerType: '' }), null)
assert.equal(DOCUMENT_REMINDER_JUMP_UNSUPPORTED, '暂不支持该主体类型的证件维护跳转')
})
@@ -6,17 +6,41 @@ export type ReminderJumpInput = {
personnelAffiliation?: string | null
}
export function resolveDocumentReminderEditPath(input: ReminderJumpInput): string | null {
export type ReminderFormMode =
| { kind: 'vehicle'; vehicleType: 'self' | 'carrier' }
| { kind: 'personnel'; affiliation: 'self' | 'carrier' }
/** 提醒页本页弹窗:解析车辆/人员表单锁定类型。 */
export function resolveDocumentReminderFormMode(
input: ReminderJumpInput
): ReminderFormMode | null {
const ownerType = String(input.ownerType || '').trim()
if (ownerType === 'vehicle') {
return String(input.vehicleType || '').trim() === 'self'
? '/vehicle-mgmt/base-info/self-vehicle'
: '/vehicle-mgmt/base-info/vehicle'
return {
kind: 'vehicle',
vehicleType: String(input.vehicleType || '').trim() === 'self' ? 'self' : 'carrier'
}
}
if (ownerType === 'personnel') {
return String(input.personnelAffiliation || '').trim() === 'carrier'
? '/vehicle-mgmt/base-info/personnel-carrier'
: '/vehicle-mgmt/base-info/personnel'
return {
kind: 'personnel',
affiliation:
String(input.personnelAffiliation || '').trim() === 'carrier' ? 'carrier' : 'self'
}
}
return null
}
/** 可选深链:档案页 path(提醒主流程已改为本页弹窗)。 */
export function resolveDocumentReminderEditPath(input: ReminderJumpInput): string | null {
const mode = resolveDocumentReminderFormMode(input)
if (!mode) return null
if (mode.kind === 'vehicle') {
return mode.vehicleType === 'self'
? '/vehicle-mgmt/base-info/self-vehicle'
: '/vehicle-mgmt/base-info/vehicle'
}
return mode.affiliation === 'carrier'
? '/vehicle-mgmt/base-info/personnel-carrier'
: '/vehicle-mgmt/base-info/personnel'
}
@@ -242,6 +242,19 @@
</div>
</div>
</section>
<PlVehicleFormDialog
v-model="vehicleFormVisible"
:vehicle-type="vehicleFormType"
:vehicle-id="editingOwnerId"
@saved="handleOwnerFormSaved"
/>
<PlPersonnelFormDialog
v-model="personnelFormVisible"
:affiliation="personnelFormAffiliation"
:personnel-id="editingOwnerId"
@saved="handleOwnerFormSaved"
/>
</div>
</template>
@@ -250,6 +263,8 @@ import ListQuickSearchInput from '@/components/business/list-quick-search-input/
import ColumnHeaderFilter from '@/components/business/column-header-filter/index.vue'
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
import PlVehicleFormDialog from '@/components/business/pl-vehicle-form-dialog/index.vue'
import PlPersonnelFormDialog from '@/components/business/pl-personnel-form-dialog/index.vue'
import { CircleCheck, Filter, EditPen } from '@element-plus/icons-vue'
import {
inventoryApi,
@@ -259,10 +274,9 @@ import {
type VehicleDetail,
type PersonnelDetail
} from '@/api/pl'
import { useRouter } from 'vue-router'
import { pickBxData } from '@/utils/http/bx'
import {
resolveDocumentReminderEditPath,
resolveDocumentReminderFormMode,
DOCUMENT_REMINDER_JUMP_UNSUPPORTED
} from '@/utils/pl-document-reminder-jump'
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
@@ -355,8 +369,12 @@ const { tableHeight, recalc: recalcTableHeight } = useListTableViewportHeight({
tableRef: docReminderTableRef
})
const router = useRouter()
const maintainLoadingId = ref<string | null>(null)
const vehicleFormVisible = ref(false)
const personnelFormVisible = ref(false)
const vehicleFormType = ref<'self' | 'carrier'>('carrier')
const personnelFormAffiliation = ref<'self' | 'carrier'>('self')
const editingOwnerId = ref<string | null>(null)
const loading = ref(false)
const resolveLoading = ref(false)
@@ -473,37 +491,52 @@ function handleToolbarResolve() {
handleResolve(selectedRow.value)
}
function handleOwnerFormSaved() {
ElMessage.success('保存成功')
fetchData()
}
async function handleMaintainCert(row: DocumentReminder) {
const ownerId = String(row.ownerId || '').trim()
const ownerType = String(row.ownerType || '').trim()
if (!ownerId || !ownerType) {
ElMessage.warning('缺少主体信息,无法跳转维护')
ElMessage.warning('缺少主体信息,无法维护证件')
return
}
maintainLoadingId.value = row.id
try {
let path: string | null = null
let mode = null as ReturnType<typeof resolveDocumentReminderFormMode>
if (ownerType === 'vehicle') {
const res = await vehicleApi.get(ownerId)
const detail = pickBxData<VehicleDetail>(res) || (res as any)?.data || res
const vehicleType = String((detail as VehicleDetail)?.vehicleType || '')
path = resolveDocumentReminderEditPath({ ownerType, vehicleType })
mode = resolveDocumentReminderFormMode({ ownerType, vehicleType })
} else if (ownerType === 'personnel') {
const res = await personnelApi.get(ownerId)
const detail = pickBxData<PersonnelDetail>(res) || (res as any)?.data || res
const personnelAffiliation = String(
(detail as PersonnelDetail)?.personnelAffiliation || ''
)
path = resolveDocumentReminderEditPath({ ownerType, personnelAffiliation })
mode = resolveDocumentReminderFormMode({ ownerType, personnelAffiliation })
} else {
ElMessage.warning(DOCUMENT_REMINDER_JUMP_UNSUPPORTED)
return
}
if (!path) {
if (!mode) {
ElMessage.warning(DOCUMENT_REMINDER_JUMP_UNSUPPORTED)
return
}
await router.push({ path, query: { editId: ownerId } })
editingOwnerId.value = ownerId
vehicleFormVisible.value = false
personnelFormVisible.value = false
await nextTick()
if (mode.kind === 'vehicle') {
vehicleFormType.value = mode.vehicleType
vehicleFormVisible.value = true
} else {
personnelFormAffiliation.value = mode.affiliation
personnelFormVisible.value = true
}
} catch {
ElMessage.error('无法打开主体档案,请确认数据存在且有权限')
} finally {