feat: 新增票据夹模块并优化 OCR 与员工画像服务
后端新增票据夹端点、数据模型和服务模块,优化 OCR 端点 Schema 和附件操作逻辑,完善员工行为画像服务和辅助函数, 前端新增票据夹视图和服务层,优化文档中心样式和侧边栏导 航,完善员工画像详情弹窗和权限控制,补充单元测试。
This commit is contained in:
@@ -21,12 +21,21 @@ function testFallsBackToValidMeta() {
|
||||
function testResolvesMainRouteNames() {
|
||||
assert.equal(resolveTargetRouteName('logs'), 'app-settings')
|
||||
assert.equal(resolveTargetRouteName('policies'), 'app-policies')
|
||||
assert.equal(resolveTargetRouteName('receiptFolder'), 'app-receiptFolder')
|
||||
assert.equal(resolveTargetRouteName('requests'), 'app-overview')
|
||||
assert.equal(resolveTargetRouteName('approval'), 'app-overview')
|
||||
assert.equal(resolveTargetRouteName('archive'), 'app-overview')
|
||||
assert.equal(resolveTargetRouteName('missing'), 'app-overview')
|
||||
}
|
||||
|
||||
function testReceiptFolderFollowsDocumentCenter() {
|
||||
assert.equal(appViews[appViews.indexOf('documents') + 1], 'receiptFolder')
|
||||
const documentIndex = navItems.findIndex((item) => item.id === 'documents')
|
||||
const receiptIndex = navItems.findIndex((item) => item.id === 'receiptFolder')
|
||||
assert.equal(receiptIndex, documentIndex + 1)
|
||||
assert.equal(navItems[receiptIndex].label, '票据夹')
|
||||
}
|
||||
|
||||
function testLegacyCentersAreRemovedFromNavigation() {
|
||||
assert.equal(appViews.includes('requests'), false)
|
||||
assert.equal(appViews.includes('approval'), false)
|
||||
@@ -39,6 +48,7 @@ function run() {
|
||||
testDerivesViewFromRouteName()
|
||||
testFallsBackToValidMeta()
|
||||
testResolvesMainRouteNames()
|
||||
testReceiptFolderFollowsDocumentCenter()
|
||||
testLegacyCentersAreRemovedFromNavigation()
|
||||
console.log('navigation route resolution tests passed')
|
||||
}
|
||||
|
||||
75
web/tests/receipt-folder-view.test.mjs
Normal file
75
web/tests/receipt-folder-view.test.mjs
Normal file
@@ -0,0 +1,75 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { join } from 'node:path'
|
||||
|
||||
const root = process.cwd()
|
||||
|
||||
function readProjectFile(path) {
|
||||
return readFileSync(join(root, path), 'utf8')
|
||||
}
|
||||
|
||||
function testReceiptFolderViewSurface() {
|
||||
const view = readProjectFile('web/src/views/ReceiptFolderView.vue')
|
||||
|
||||
assert.match(view, /未关联票据/)
|
||||
assert.match(view, /已关联票据/)
|
||||
assert.match(view, /一键关联票据/)
|
||||
assert.match(view, /基本票据信息/)
|
||||
assert.match(view, /原始文件/)
|
||||
assert.match(view, /返回列表/)
|
||||
assert.match(view, /删除票据/)
|
||||
assert.match(view, /ElCheckboxGroup/)
|
||||
assert.match(view, /fetchReceiptFolderItems\('all'\)/)
|
||||
assert.match(view, /buildReceiptFile\(item\)/)
|
||||
assert.match(view, /source: selectedDraft \? 'detail' : 'receipt-folder'/)
|
||||
assert.match(view, /emit\('open-assistant'/)
|
||||
}
|
||||
|
||||
function testReceiptFolderServiceContract() {
|
||||
const service = readProjectFile('web/src/services/receiptFolder.js')
|
||||
const ocrService = readProjectFile('web/src/services/ocr.js')
|
||||
const reimbursementService = readProjectFile('web/src/services/reimbursements.js')
|
||||
|
||||
assert.match(service, /\/receipt-folder\$\{buildStatusQuery\(status\)\}/)
|
||||
assert.match(service, /\/receipt-folder\/\$\{encodeURIComponent/)
|
||||
assert.match(service, /responseType: 'blob'/)
|
||||
assert.match(service, /new File\(\[blob\], fileName/)
|
||||
assert.match(service, /receiptId/)
|
||||
assert.match(ocrService, /formData\.append\('receipt_ids'/)
|
||||
assert.match(reimbursementService, /formData\.append\('receipt_id'/)
|
||||
}
|
||||
|
||||
function testAppShellWiresReceiptFolder() {
|
||||
const shell = readProjectFile('web/src/views/AppShellRouteView.vue')
|
||||
|
||||
assert.match(shell, /activeView === 'receiptFolder'/)
|
||||
assert.match(shell, /ReceiptFolderView/)
|
||||
assert.match(shell, /@open-assistant="openSmartEntry"/)
|
||||
assert.match(shell, /receipt-folder-workarea/)
|
||||
}
|
||||
|
||||
function testSharedDocumentListStyleReuse() {
|
||||
const receiptView = readProjectFile('web/src/views/ReceiptFolderView.vue')
|
||||
const documentView = readProjectFile('web/src/views/DocumentsCenterView.vue')
|
||||
const receiptStyles = readProjectFile('web/src/assets/styles/views/receipt-folder-view.css')
|
||||
const sharedStyles = readProjectFile('web/src/assets/styles/components/document-list-shared.css')
|
||||
|
||||
assert.match(receiptView, /document-list-shared\.css/)
|
||||
assert.match(documentView, /document-list-shared\.css/)
|
||||
assert.match(sharedStyles, /\.table-wrap\b/)
|
||||
assert.match(sharedStyles, /\.doc-kind-tag\b/)
|
||||
assert.match(sharedStyles, /\.list-foot\b/)
|
||||
assert.doesNotMatch(receiptStyles, /\.table-wrap\b/)
|
||||
assert.doesNotMatch(receiptStyles, /\.doc-kind-tag\b/)
|
||||
assert.doesNotMatch(receiptStyles, /\.list-foot\b/)
|
||||
}
|
||||
|
||||
function run() {
|
||||
testReceiptFolderViewSurface()
|
||||
testReceiptFolderServiceContract()
|
||||
testAppShellWiresReceiptFolder()
|
||||
testSharedDocumentListStyleReuse()
|
||||
console.log('receipt folder view tests passed')
|
||||
}
|
||||
|
||||
run()
|
||||
Reference in New Issue
Block a user