提交
This commit is contained in:
1 parent
3d98104455
commit
0d52442902
76 files changed
+21994
-12642
No files matched your search
@@ -63,7 +63,8 @@ export const setWorktab = (to: RouteLocationNormalized): void => {
|
||||
keepAlive: meta.keepAlive as boolean,
|
||||
params,
|
||||
query,
|
||||
fixedTab: meta.fixedTab as boolean
|
||||
fixedTab: meta.fixedTab as boolean,
|
||||
worktabMulti: Boolean(meta.worktabMulti)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
import ExcelJS from 'exceljs'
|
||||
import FileSaver from 'file-saver'
|
||||
|
||||
export type OaHistoryExportColumn = {
|
||||
key: string
|
||||
label: string
|
||||
kind?: 'business' | 'related'
|
||||
subLabel?: string
|
||||
}
|
||||
|
||||
export type OaHistoryExportFixedColumn = {
|
||||
key: string
|
||||
label: string
|
||||
}
|
||||
|
||||
export type OaHistoryExportRow = {
|
||||
index?: number
|
||||
id?: string
|
||||
business?: Record<string, string>
|
||||
fixed?: Record<string, string>
|
||||
}
|
||||
|
||||
export type OaHistoryExportPayload = {
|
||||
appName?: string
|
||||
businessColumns?: OaHistoryExportColumn[]
|
||||
fixedColumns?: OaHistoryExportFixedColumn[]
|
||||
rows?: OaHistoryExportRow[]
|
||||
}
|
||||
|
||||
type SheetColumn = {
|
||||
key: string
|
||||
label: string
|
||||
subLabel?: string
|
||||
width: number
|
||||
}
|
||||
|
||||
const HEADER_FILL: ExcelJS.Fill = {
|
||||
type: 'pattern',
|
||||
pattern: 'solid',
|
||||
fgColor: { argb: 'FFF0FDF4' }
|
||||
}
|
||||
|
||||
const HEADER_FONT: Partial<ExcelJS.Font> = {
|
||||
bold: true,
|
||||
color: { argb: 'FF065F46' },
|
||||
size: 11
|
||||
}
|
||||
|
||||
const BORDER: Partial<ExcelJS.Borders> = {
|
||||
top: { style: 'thin', color: { argb: 'FFE2E8F0' } },
|
||||
left: { style: 'thin', color: { argb: 'FFE2E8F0' } },
|
||||
bottom: { style: 'thin', color: { argb: 'FFE2E8F0' } },
|
||||
right: { style: 'thin', color: { argb: 'FFE2E8F0' } }
|
||||
}
|
||||
|
||||
function pad(n: number) {
|
||||
return String(n).padStart(2, '0')
|
||||
}
|
||||
|
||||
function exportTimestamp() {
|
||||
const d = new Date()
|
||||
return (
|
||||
`${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}` +
|
||||
`${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`
|
||||
)
|
||||
}
|
||||
|
||||
function sanitizeFilename(name: string) {
|
||||
return String(name || '历史记录')
|
||||
.replace(/[\\/:*?"<>|]/g, '_')
|
||||
.trim()
|
||||
}
|
||||
|
||||
function styleHeaderCell(cell: ExcelJS.Cell) {
|
||||
cell.fill = HEADER_FILL
|
||||
cell.font = HEADER_FONT
|
||||
cell.alignment = { vertical: 'middle', horizontal: 'center', wrapText: true }
|
||||
cell.border = BORDER
|
||||
}
|
||||
|
||||
function styleBodyCell(cell: ExcelJS.Cell) {
|
||||
cell.alignment = { vertical: 'top', horizontal: 'left', wrapText: true }
|
||||
cell.border = BORDER
|
||||
}
|
||||
|
||||
function buildSheetColumns(payload: OaHistoryExportPayload): SheetColumn[] {
|
||||
const cols: SheetColumn[] = [
|
||||
{ key: '__index', label: '序号', width: 8 },
|
||||
{ key: '__id', label: '数据id', width: 28 }
|
||||
]
|
||||
for (const col of payload.businessColumns || []) {
|
||||
if (col.kind === 'related') {
|
||||
cols.push({ key: col.key, label: col.label, width: 18 })
|
||||
cols.push({
|
||||
key: `${col.key}__titles`,
|
||||
label: col.label,
|
||||
subLabel: col.subLabel || '关联标题',
|
||||
width: 24
|
||||
})
|
||||
} else {
|
||||
cols.push({ key: col.key, label: col.label, width: 20 })
|
||||
}
|
||||
}
|
||||
for (const col of payload.fixedColumns || []) {
|
||||
cols.push({
|
||||
key: col.key,
|
||||
label: col.label,
|
||||
width: col.key === 'approvalRecord' ? 48 : 18
|
||||
})
|
||||
}
|
||||
return cols
|
||||
}
|
||||
|
||||
function cellValue(row: OaHistoryExportRow, key: string) {
|
||||
if (key === '__index') return row.index ?? ''
|
||||
if (key === '__id') return row.id ?? ''
|
||||
const fixed = row.fixed || {}
|
||||
const business = row.business || {}
|
||||
if (key in fixed) return fixed[key] ?? ''
|
||||
return business[key] ?? ''
|
||||
}
|
||||
|
||||
function writeHeaderRows(worksheet: ExcelJS.Worksheet, sheetColumns: SheetColumn[]) {
|
||||
const headerRow1 = worksheet.getRow(1)
|
||||
const headerRow2 = worksheet.getRow(2)
|
||||
headerRow1.height = 24
|
||||
headerRow2.height = 20
|
||||
|
||||
let colIdx = 1
|
||||
let i = 0
|
||||
while (i < sheetColumns.length) {
|
||||
const col = sheetColumns[i]
|
||||
const next = sheetColumns[i + 1]
|
||||
const isRelatedPair = Boolean(next?.subLabel && next.label === col.label && !col.subLabel)
|
||||
|
||||
if (isRelatedPair) {
|
||||
const c1 = headerRow1.getCell(colIdx)
|
||||
c1.value = col.label
|
||||
styleHeaderCell(c1)
|
||||
worksheet.mergeCells(1, colIdx, 1, colIdx + 1)
|
||||
|
||||
const c2a = headerRow2.getCell(colIdx)
|
||||
c2a.value = ''
|
||||
styleHeaderCell(c2a)
|
||||
|
||||
const c2b = headerRow2.getCell(colIdx + 1)
|
||||
c2b.value = next.subLabel || '关联标题'
|
||||
styleHeaderCell(c2b)
|
||||
|
||||
colIdx += 2
|
||||
i += 2
|
||||
continue
|
||||
}
|
||||
|
||||
const c1 = headerRow1.getCell(colIdx)
|
||||
c1.value = col.label
|
||||
styleHeaderCell(c1)
|
||||
const c2 = headerRow2.getCell(colIdx)
|
||||
c2.value = ''
|
||||
styleHeaderCell(c2)
|
||||
worksheet.mergeCells(1, colIdx, 2, colIdx)
|
||||
colIdx += 1
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
|
||||
export async function downloadOaHistoryExcel(
|
||||
payload: OaHistoryExportPayload,
|
||||
options?: { filenamePrefix?: string }
|
||||
) {
|
||||
const rows = payload.rows || []
|
||||
if (!rows.length) {
|
||||
throw new Error('暂无可导出数据')
|
||||
}
|
||||
|
||||
const sheetColumns = buildSheetColumns(payload)
|
||||
const workbook = new ExcelJS.Workbook()
|
||||
const sheetName = sanitizeFilename(payload.appName || '历史记录').slice(0, 31)
|
||||
const worksheet = workbook.addWorksheet(sheetName)
|
||||
|
||||
worksheet.columns = sheetColumns.map((c) => ({ width: c.width }))
|
||||
writeHeaderRows(worksheet, sheetColumns)
|
||||
|
||||
rows.forEach((row, rowIndex) => {
|
||||
const excelRow = worksheet.getRow(rowIndex + 3)
|
||||
sheetColumns.forEach((col, i) => {
|
||||
const cell = excelRow.getCell(i + 1)
|
||||
cell.value = cellValue(row, col.key)
|
||||
styleBodyCell(cell)
|
||||
})
|
||||
})
|
||||
|
||||
worksheet.views = [{ state: 'frozen', ySplit: 2 }]
|
||||
|
||||
const buffer = await workbook.xlsx.writeBuffer()
|
||||
const prefix = sanitizeFilename(options?.filenamePrefix || payload.appName || '历史记录')
|
||||
const blob = new Blob([buffer], {
|
||||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||
})
|
||||
FileSaver.saveAs(blob, `${prefix}-${exportTimestamp()}.xlsx`)
|
||||
}
|
||||
@@ -74,7 +74,7 @@ export const PRODUCTION_WORK_ORDER_TABS: ProductionWorkOrderTabConfig[] = [
|
||||
},
|
||||
{
|
||||
key: 'temporary',
|
||||
label: '临时生产',
|
||||
label: '扩增/传代生产',
|
||||
group: 'temporary',
|
||||
workOrderType: 'temporary',
|
||||
listLayout: 'standalone'
|
||||
|
||||
@@ -119,6 +119,14 @@ const SOP_SHARED_CONTENT_STYLE = `
|
||||
.sop-body-table tbody {
|
||||
height: 100%;
|
||||
}
|
||||
.sop-header-table.sop-row-hidden,
|
||||
.sop-body-table tr.sop-row-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
.sop-record.sop-a4:has(.sop-row-hidden) {
|
||||
min-height: auto !important;
|
||||
height: auto !important;
|
||||
}
|
||||
.sop-body-table tr.sop-fill-row {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user