优化
This commit is contained in:
@@ -18,6 +18,7 @@ import {
|
||||
import { createPlatformExportTask } from '@/modules/downloads'
|
||||
import { useAccessPreviewStore } from '@/core/access/accessPreview'
|
||||
import { useAuthStore } from '@/core/auth/auth'
|
||||
import QueryToolbar from '@/shared/components/QueryToolbar.vue'
|
||||
import CustomersView from './CustomersView.vue'
|
||||
|
||||
vi.mock('@/modules/iam', () => ({
|
||||
@@ -47,7 +48,7 @@ class ResizeObserverStub implements ResizeObserver {
|
||||
|
||||
const fullTenant: PlatformTenantResource = {
|
||||
id: '8', tenantCode: 'TEN8', tenantName: '柏悦物流', status: 'PROFILE_REQUIRED',
|
||||
legalName: '柏悦物流有限公司', unifiedSocialCreditCode: '91440300MA5ABCDE12',
|
||||
legalName: '柏悦物流有限公司', legalRepresentative: '张三', unifiedSocialCreditCode: '91440300MA5ABCDE12',
|
||||
contactName: '张三', contactPhone: '13800138000', contactEmail: 'ops@example.com',
|
||||
servicePackage: '基础版', contactWechat: 'baiyue-ops', salesOwnerName: '李四', paymentTermDays: 30,
|
||||
enterpriseType: '有限责任公司', establishedDate: '2020-01-01', registeredCapital: 1000,
|
||||
@@ -83,7 +84,7 @@ describe('CustomersView', () => {
|
||||
setActivePinia(pinia)
|
||||
const auth = useAuthStore()
|
||||
auth.token = 'token'
|
||||
auth.permissions = ['platform:customer:list', 'platform:customer:view', 'platform:customer:edit', 'platform:customer:export']
|
||||
auth.permissions = ['platform:customer:list', 'platform:customer:view', 'platform:customer:edit', 'platform:customer:export', 'platform:download:list']
|
||||
useAccessPreviewStore().initializeAfterLogin()
|
||||
vi.mocked(listPlatformTenants).mockResolvedValue({
|
||||
records: [{ ...fullTenant, contactPhone: '138****8000', contactEmail: 'o***@example.com' }],
|
||||
@@ -132,6 +133,33 @@ describe('CustomersView', () => {
|
||||
expect(preview?.src).toBe('blob:qualification-preview')
|
||||
})
|
||||
|
||||
it('does not count rejected or superseded history as a current qualification when resubmitting', async () => {
|
||||
const rejectedTenant = { ...fullTenant, status: 'REJECTED' }
|
||||
vi.mocked(listPlatformTenants).mockResolvedValue({ records: [rejectedTenant], page: 1, size: 10, total: 1, pages: 1 })
|
||||
vi.mocked(getPlatformTenant).mockResolvedValue(rejectedTenant)
|
||||
vi.mocked(listTenantQualifications).mockResolvedValue([
|
||||
{
|
||||
id: 'qualification-old', tenantId: fullTenant.id, qualificationType: 'BUSINESS_LICENSE',
|
||||
certificateNo: fullTenant.unifiedSocialCreditCode, documentUrl: '/files/old-license.png',
|
||||
status: 'SUPERSEDED', reviewComment: '已替换', validTo: null,
|
||||
},
|
||||
{
|
||||
id: 'qualification-rejected', tenantId: fullTenant.id, qualificationType: 'BUSINESS_LICENSE',
|
||||
certificateNo: fullTenant.unifiedSocialCreditCode, documentUrl: '/files/rejected-license.png',
|
||||
status: 'REJECTED', reviewComment: '请重新上传', validTo: null,
|
||||
},
|
||||
])
|
||||
|
||||
mount(CustomersView, { attachTo: document.body, global: { plugins: [pinia, ElementPlus] } })
|
||||
await flushPromises()
|
||||
tableButtonByText('编辑')?.click()
|
||||
await flushPromises()
|
||||
|
||||
expect(document.querySelector('.qualification-label [aria-label="已上传"]')).toBeNull()
|
||||
expect(document.querySelector('.qualification-file-name')?.textContent).toContain('未选择文件')
|
||||
expect(downloadTenantQualification).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('shows uploaded qualifications in customer detail and opens the full preview', async () => {
|
||||
vi.mocked(listTenantQualifications).mockResolvedValue([{
|
||||
id: 'qualification-1', tenantId: fullTenant.id, qualificationType: 'BUSINESS_LICENSE',
|
||||
@@ -154,6 +182,52 @@ describe('CustomersView', () => {
|
||||
expect(document.querySelector('.qualification-preview img[alt="license.png预览"]')).not.toBeNull()
|
||||
})
|
||||
|
||||
it('does not let an older customer detail response overwrite a newer one', async () => {
|
||||
const secondTenant = {
|
||||
...fullTenant, id: '9', tenantCode: 'TEN9', tenantName: '第二家客户', legalName: '第二家客户有限公司',
|
||||
}
|
||||
vi.mocked(listPlatformTenants).mockResolvedValue({
|
||||
records: [fullTenant, secondTenant], page: 1, size: 10, total: 2, pages: 1,
|
||||
})
|
||||
let resolveFirst!: (value: PlatformTenantResource) => void
|
||||
let resolveSecond!: (value: PlatformTenantResource) => void
|
||||
vi.mocked(getPlatformTenant)
|
||||
.mockImplementationOnce(() => new Promise((resolve) => { resolveFirst = resolve }))
|
||||
.mockImplementationOnce(() => new Promise((resolve) => { resolveSecond = resolve }))
|
||||
|
||||
mount(CustomersView, { attachTo: document.body, global: { plugins: [pinia, ElementPlus] } })
|
||||
await flushPromises()
|
||||
const detailButtons = [...document.querySelectorAll<HTMLButtonElement>('.el-table__body button')]
|
||||
.filter((button) => button.textContent?.trim() === '详情')
|
||||
detailButtons[0]?.click()
|
||||
detailButtons[1]?.click()
|
||||
|
||||
resolveSecond(secondTenant)
|
||||
await flushPromises()
|
||||
expect(document.querySelector('.customer-detail')?.textContent).toContain('第二家客户有限公司')
|
||||
|
||||
resolveFirst(fullTenant)
|
||||
await flushPromises()
|
||||
const detailText = document.querySelector('.customer-detail')?.textContent
|
||||
expect(detailText).toContain('第二家客户有限公司')
|
||||
expect(detailText).not.toContain('柏悦物流有限公司')
|
||||
})
|
||||
|
||||
it('labels replaced qualification history without presenting it as pending review', async () => {
|
||||
vi.mocked(listTenantQualifications).mockResolvedValue([{
|
||||
id: 'qualification-old', tenantId: fullTenant.id, qualificationType: 'BUSINESS_LICENSE',
|
||||
certificateNo: fullTenant.unifiedSocialCreditCode, documentUrl: '/files/old-license.pdf',
|
||||
status: 'SUPERSEDED', reviewComment: '已替换', validTo: null,
|
||||
}])
|
||||
|
||||
mount(CustomersView, { attachTo: document.body, global: { plugins: [pinia, ElementPlus] } })
|
||||
await flushPromises()
|
||||
tableButtonByText('详情')?.click()
|
||||
await flushPromises()
|
||||
|
||||
expect(document.querySelector('.detail-qualification-meta .el-tag')?.textContent).toContain('已替换')
|
||||
})
|
||||
|
||||
it('saves customer data and selected qualifications with one action', async () => {
|
||||
mount(CustomersView, { attachTo: document.body, global: { plugins: [pinia, ElementPlus] } })
|
||||
await flushPromises()
|
||||
@@ -183,9 +257,12 @@ describe('CustomersView', () => {
|
||||
})
|
||||
|
||||
it('submits the current filters to the backend export service without loading every customer page', async () => {
|
||||
mount(CustomersView, { attachTo: document.body, global: { plugins: [pinia, ElementPlus] } })
|
||||
const wrapper = mount(CustomersView, { attachTo: document.body, global: { plugins: [pinia, ElementPlus] } })
|
||||
await flushPromises()
|
||||
|
||||
wrapper.findComponent(QueryToolbar).vm.$emit('update:modelValue', { keyword: ' Acme ', status: 'ACTIVE' })
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
const exportButton = [...document.querySelectorAll<HTMLButtonElement>('button')]
|
||||
.find((button) => button.textContent?.trim() === '导出Excel')
|
||||
exportButton?.click()
|
||||
@@ -193,11 +270,35 @@ describe('CustomersView', () => {
|
||||
|
||||
expect(createPlatformExportTask).toHaveBeenCalledWith({
|
||||
exportType: 'CUSTOMER_LIST', format: 'XLSX', taskName: '客户列表',
|
||||
parameters: { keyword: undefined, status: undefined },
|
||||
parameters: { keyword: 'Acme', status: 'ACTIVE' },
|
||||
})
|
||||
expect(listPlatformTenants).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it('hides customer export when the stable export permission is absent', async () => {
|
||||
const auth = useAuthStore()
|
||||
auth.permissions = ['platform:customer:list', 'platform:customer:view']
|
||||
useAccessPreviewStore().initializeAfterLogin()
|
||||
mount(CustomersView, { attachTo: document.body, global: { plugins: [pinia, ElementPlus] } })
|
||||
await flushPromises()
|
||||
|
||||
expect([...document.querySelectorAll<HTMLButtonElement>('button')]
|
||||
.some((button) => button.textContent?.trim() === '导出Excel')).toBe(false)
|
||||
expect(createPlatformExportTask).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('does not create an unrecoverable export for a role without download-center access', async () => {
|
||||
const auth = useAuthStore()
|
||||
auth.permissions = ['platform:customer:list', 'platform:customer:export']
|
||||
useAccessPreviewStore().initializeAfterLogin()
|
||||
mount(CustomersView, { attachTo: document.body, global: { plugins: [pinia, ElementPlus] } })
|
||||
await flushPromises()
|
||||
|
||||
expect([...document.querySelectorAll<HTMLButtonElement>('button')]
|
||||
.some((button) => button.textContent?.trim() === '导出Excel')).toBe(false)
|
||||
expect(createPlatformExportTask).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('approves a pending enterprise directly from the customer list', async () => {
|
||||
const auth = useAuthStore()
|
||||
auth.permissions = [...auth.permissions, 'platform:customer:review', 'platform:customer:approve']
|
||||
@@ -228,6 +329,35 @@ describe('CustomersView', () => {
|
||||
expect(document.body.textContent).toContain('Temporary#2026')
|
||||
})
|
||||
|
||||
it('keeps the client registration account as administrator after approval', async () => {
|
||||
const auth = useAuthStore()
|
||||
auth.permissions = [...auth.permissions, 'platform:customer:review', 'platform:customer:approve']
|
||||
useAccessPreviewStore().initializeAfterLogin()
|
||||
vi.mocked(listPlatformTenants).mockResolvedValue({
|
||||
records: [{ ...fullTenant, status: 'PENDING' }], page: 1, size: 10, total: 1, pages: 1,
|
||||
})
|
||||
vi.mocked(listEnterpriseReviews).mockResolvedValue([pendingReview])
|
||||
vi.mocked(approveEnterpriseReview).mockResolvedValue({
|
||||
tenantId: fullTenant.id,
|
||||
administratorCreated: false,
|
||||
administratorUsername: null,
|
||||
temporaryPassword: null,
|
||||
})
|
||||
|
||||
mount(CustomersView, { attachTo: document.body, global: { plugins: [pinia, ElementPlus] } })
|
||||
await flushPromises()
|
||||
tableButtonByText('通过')?.click()
|
||||
await flushPromises()
|
||||
;[...document.querySelectorAll<HTMLButtonElement>('button')]
|
||||
.find((button) => button.textContent?.trim() === '确认通过')?.click()
|
||||
await flushPromises()
|
||||
|
||||
expect(approveEnterpriseReview).toHaveBeenCalledWith(pendingReview.id, '企业资料与必填资质完整、清晰,审核通过')
|
||||
expect(rejectEnterpriseReview).not.toHaveBeenCalled()
|
||||
expect(document.body.textContent).toContain('注册账号继续作为企业管理员')
|
||||
expect(document.body.textContent).not.toContain('请立即保存以下一次性凭证')
|
||||
})
|
||||
|
||||
it('keeps review-only roles on the merged customer page without calling the customer list endpoint', async () => {
|
||||
const auth = useAuthStore()
|
||||
auth.permissions = ['platform:customer:review', 'platform:customer:approve']
|
||||
|
||||
Reference in New Issue
Block a user