exportTemplates.ts 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066
  1. import { cloneDeep, isNumber } from 'lodash'
  2. import ExcelJS from 'exceljs'
  3. import { exportWordDocx, getBase64Sync } from './exportWord'
  4. import { baseURL } from './http'
  5. import { resJiLianFu } from './history'
  6. import {
  7. arrangeImages,
  8. calcTablePages,
  9. getExcelColumnLetter,
  10. ITEMPLATE,
  11. numberToChinese,
  12. removeHtmlTags
  13. } from './exportWordUtils'
  14. import { myTableTransferSize } from '@/components/MyTable'
  15. import dayjs from 'dayjs'
  16. import { D7CEHCK_COLLECTION_RESULT_OPTIONS } from '@/pages/D_storeManage/D7check/constants'
  17. import { exportTempExcel, getImageBase64Extension } from './exportExcelUtils'
  18. import { selectObj } from './select'
  19. import { MEDIA_TYPES } from '@/pages/C_goodsManage/C21wealth/constants'
  20. export enum EXPORT_WORD_ENUM {
  21. /** 借用藏品点交凭证 */
  22. BORROW = 1,
  23. /** 藏品馆内提退凭单 */
  24. HALL_PUT_BACK = 2,
  25. /** 分库藏品提退出入库记录单 */
  26. SUB_PUT_BACK = 3,
  27. /** 分库藏品入库记录单 */
  28. SUB_PUT_IN = 4,
  29. /** 入馆凭证 */
  30. VOUCHER = 5,
  31. /** 藏品图片及相关数字化信息使用申请单 */
  32. FORM_FOR_DIGITAL = 6,
  33. /** 藏品档案 */
  34. COLLECTION_ARCHIVES = 7,
  35. /** 拟征集藏品清单 */
  36. COLLECTION_LIST = 8,
  37. /** 文物鉴定书 */
  38. CERTIFICATE = 9,
  39. /** 入藏凭证 */
  40. STORAGE_VOUCHER = 10,
  41. /** 藏品卡片 */
  42. COLLECTION_CARD = 11,
  43. /** 藏品注销凭证 */
  44. CANCEL_VOUCHER = 12,
  45. /** 藏品移库 */
  46. COLLECTION_RELOCATION = 13,
  47. /** 藏品盘点记录单 */
  48. COLLECTION_INVENTORY = 14,
  49. /** 馆内人员进库申请单 */
  50. INSIDER_FORM = 15,
  51. /** 文物库房外来人员出入库审批表 */
  52. OUTSIDER_FORM = 16,
  53. /** 文物修复单 */
  54. RELIC_REPAIR_LIST = 17,
  55. /** 事故处理凭证 */
  56. ACCIDENT_HANDLING_CERTIFICATE = 18,
  57. /** 藏品现状登记 */
  58. COLLECTION_CURRENT_STATUS = 19,
  59. /** 馆内展览借用藏品登记台账 */
  60. REGISTER_LEDGER = 20,
  61. /** 藏品总账 */
  62. COLLECTION_LEDGER = 21,
  63. /** 藏品提退出入库登记流水账 */
  64. COLLECTION_LOG = 22
  65. }
  66. export const EXPORT_TEMPLATE_MAP: Record<EXPORT_WORD_ENUM, ITEMPLATE> = {
  67. [EXPORT_WORD_ENUM.COLLECTION_LOG]: {
  68. fileName: '藏品提退出入库登记流水账',
  69. options: {
  70. sheetHeader: [
  71. '序号',
  72. '藏品总登记号',
  73. '分类号',
  74. '点交凭证单号',
  75. '藏品名称',
  76. '计件数量',
  77. '文物现状',
  78. ['出库记录', '提用人', '点交人', '出库时间'],
  79. ['退库记录', '退还人', '点收人', '退库时间'],
  80. '备注'
  81. ],
  82. sheetFilter: [
  83. 'index',
  84. 'num',
  85. 'numType',
  86. 'orderNum',
  87. 'name',
  88. 'pcs',
  89. 'preserveState',
  90. 'ckUser1',
  91. 'ckUser2',
  92. 'ckDate',
  93. 'tkUser1',
  94. 'tkUser2',
  95. 'tkDate',
  96. 'snapRtf'
  97. ],
  98. columnWidths: [5, 14, 8, 10, 15, 10, 10, 10, 10, 14, 10, 10, 14, 10]
  99. }
  100. },
  101. [EXPORT_WORD_ENUM.COLLECTION_LEDGER]: {
  102. fileName: '藏品总账',
  103. options: {
  104. sheetHeader: [
  105. ['登记日期', '年', '月', '日'],
  106. '藏品总登记号',
  107. '分类号',
  108. '藏品名称',
  109. '时代',
  110. ['计件', '单位', '件数'],
  111. '尺寸、重量',
  112. '质地',
  113. '完残情况',
  114. '来源',
  115. '采集地点',
  116. ['入馆日期', '年', '月', '日'],
  117. '入馆凭证号',
  118. '注销凭证号',
  119. '级别',
  120. '备注'
  121. ],
  122. sheetFilter: [
  123. 'year',
  124. 'month',
  125. 'day',
  126. 'num',
  127. 'numType',
  128. 'name',
  129. 'dictAge',
  130. 'pcsUnit',
  131. '_pcs',
  132. 'size',
  133. 'dictTexture',
  134. 'dictTorn',
  135. 'source',
  136. '',
  137. 'year2',
  138. 'month2',
  139. 'day2',
  140. 'inHouseNum',
  141. '',
  142. 'dictLevel',
  143. 'rtf'
  144. ],
  145. columnWidths: [5, 5, 5, 10, 5, 10, 10, 5, 5, 10, 5, 5, 5, 5, 5, 5, 5, 10, 10, 10, 10]
  146. }
  147. },
  148. [EXPORT_WORD_ENUM.COLLECTION_CURRENT_STATUS]: {
  149. fileName: '藏品现状登记',
  150. templateName: '16.docx'
  151. },
  152. [EXPORT_WORD_ENUM.ACCIDENT_HANDLING_CERTIFICATE]: {
  153. fileName: '藏品事故处理凭证',
  154. templateName: '15.docx'
  155. },
  156. [EXPORT_WORD_ENUM.RELIC_REPAIR_LIST]: {
  157. fileName: '义乌市博物馆文物修复单',
  158. templateName: '14.docx',
  159. // 每个字段单行最大字符数
  160. perLine: {
  161. name: 9,
  162. dictLevel: 24,
  163. txt2: 4
  164. },
  165. row: {
  166. // 首页最大行数
  167. maxRowFirstPage: 3,
  168. // 尾页最大行数
  169. maxRowLastPage: 6,
  170. // 每页最大行数
  171. maxRowPage: 8,
  172. // 首页单行最大字符行数
  173. maxFirstCharLine: 20,
  174. // 尾页单行最大字符行数
  175. maxLastCharLine: 18,
  176. // 每页最大字符行数
  177. maxCharLine: 26,
  178. // 表格每行最小字符行数
  179. minRowCharLine: 3
  180. }
  181. },
  182. [EXPORT_WORD_ENUM.OUTSIDER_FORM]: {
  183. fileName: '文物库房外来人员出入库审批表',
  184. templateName: '13.docx'
  185. },
  186. [EXPORT_WORD_ENUM.INSIDER_FORM]: {
  187. fileName: '馆内人员进库申请单',
  188. templateName: '12.docx'
  189. },
  190. [EXPORT_WORD_ENUM.COLLECTION_INVENTORY]: {
  191. fileName: '义乌市博物馆分库藏品盘点记录单',
  192. templateName: '11.docx'
  193. },
  194. [EXPORT_WORD_ENUM.COLLECTION_RELOCATION]: {
  195. fileName: '义乌博物馆分库藏品移库记录单',
  196. templateName: '10.docx'
  197. },
  198. [EXPORT_WORD_ENUM.CANCEL_VOUCHER]: {
  199. fileName: '馆藏品注销凭证',
  200. options: {
  201. sheetHeader: [
  202. '藏品总账号',
  203. '藏品分类号',
  204. '名称',
  205. '年代',
  206. '数量',
  207. '尺寸、重量',
  208. '完残情况',
  209. '登记账页码数',
  210. '注销后去向',
  211. '注销原因',
  212. '备注'
  213. ],
  214. sheetFilter: [
  215. 'num',
  216. 'numType',
  217. 'name',
  218. 'dictAge',
  219. 'pcs',
  220. 'size',
  221. 'torn',
  222. '',
  223. 'txt1',
  224. 'txt2',
  225. 'txt3'
  226. ],
  227. columnWidths: [10, 10, 10, 15, 10, 15, 15, 12, 15, 15, 15]
  228. }
  229. },
  230. [EXPORT_WORD_ENUM.REGISTER_LEDGER]: {
  231. fileName: '义乌市博物馆馆内展览借用藏品登记台账',
  232. options: {
  233. sheetHeader: [
  234. '序号',
  235. '年度',
  236. '借用部门',
  237. '展览名称',
  238. '借用文物 实际数量(合计)',
  239. ['借用藏品基本情况', '藏品总登记号', '藏品名称'],
  240. '出借时间',
  241. ['出借经手人', '甲方', '乙方'],
  242. '藏品提用审批单号',
  243. '馆内提退凭证号',
  244. '预计归还日期',
  245. '归还时间',
  246. ['归还经手人', '甲方', '乙方'],
  247. '记录人',
  248. '备注'
  249. ],
  250. sheetFilter: [
  251. 'index',
  252. 'year',
  253. 'sonUnit',
  254. 'typeName',
  255. 'pcs',
  256. 'num',
  257. 'name',
  258. 'lendDate',
  259. 'lenderA',
  260. 'lenderb',
  261. 'sonNum',
  262. 'sonNum2',
  263. 'expectedReturnDate',
  264. 'returnDate',
  265. 'handlerA',
  266. 'handlerB',
  267. 'recorder',
  268. 'remark'
  269. ],
  270. columnWidths: [5, 5, 12, 15, 12, 10, 15, 12, 10, 10, 15, 15, 15, 15, 10, 10, 10, 15]
  271. }
  272. },
  273. [EXPORT_WORD_ENUM.CERTIFICATE]: {
  274. fileName: '义乌市博物馆馆藏文物鉴定书',
  275. options: {
  276. sheetHeader: [
  277. '编号',
  278. '总登记号',
  279. '分类号',
  280. '文物名称',
  281. '图片',
  282. '数量',
  283. '质地',
  284. '时代',
  285. '尺寸(cm)或重量(g)',
  286. '现状概述',
  287. '鉴定等级',
  288. '备注'
  289. ],
  290. sheetFilter: [
  291. 'index',
  292. 'num',
  293. 'numType',
  294. 'name',
  295. 'thumb',
  296. 'pcs',
  297. 'dictTexture',
  298. 'dictAge',
  299. 'size',
  300. 'dictTorn',
  301. 'dictLevel',
  302. 'intro'
  303. ],
  304. columnWidths: [5, 12, 7, 15, 10, 7, 15, 35, 20, 10, 10, 20]
  305. }
  306. },
  307. [EXPORT_WORD_ENUM.COLLECTION_LIST]: {
  308. fileName: '拟征集藏品清单',
  309. options: {
  310. sheetHeader: ['序号', '藏品名称', '初定年代', '报价(万元)', '原持有人', '征集方式'],
  311. sheetFilter: ['index', 'name', 'dictAgeFirst', 'offer', 'holder', 'source'],
  312. columnWidths: [5, 15, 40, 15, 10, 10]
  313. }
  314. },
  315. [EXPORT_WORD_ENUM.BORROW]: {
  316. fileName: '义乌市博物馆借用藏品点交凭证',
  317. templateName: '1.docx',
  318. // 每个字段单行最大字符数
  319. perLine: {
  320. num: 9,
  321. name: 14,
  322. rtf: 11,
  323. dictAge: 6,
  324. dictTexture3: 6
  325. },
  326. row: {
  327. // 首页最大行数
  328. maxRowFirstPage: 1,
  329. // 尾页最大行数
  330. maxRowLastPage: 2,
  331. // 每页最大行数
  332. maxRowPage: 5,
  333. // 首页单行最大字符行数
  334. maxFirstCharLine: 9,
  335. // 尾页单行最大字符行数
  336. maxLastCharLine: 11,
  337. // 每页最大字符行数
  338. maxCharLine: 27,
  339. // 表格每行最小字符行数
  340. minRowCharLine: 4
  341. }
  342. },
  343. [EXPORT_WORD_ENUM.HALL_PUT_BACK]: {
  344. fileName: '义乌市博物馆藏品馆内提退凭单',
  345. templateName: '2.docx',
  346. // 每个字段单行最大字符数
  347. perLine: {
  348. num: 9,
  349. name: 24,
  350. pcsUnit: 4,
  351. rtf: 6
  352. },
  353. row: {
  354. // 首页最大行数
  355. maxRowFirstPage: 3,
  356. // 尾页最大行数
  357. maxRowLastPage: 6,
  358. // 每页最大行数
  359. maxRowPage: 8,
  360. // 首页单行最大字符行数
  361. maxFirstCharLine: 20,
  362. // 尾页单行最大字符行数
  363. maxLastCharLine: 18,
  364. // 每页最大字符行数
  365. maxCharLine: 26,
  366. // 表格每行最小字符行数
  367. minRowCharLine: 3
  368. }
  369. },
  370. [EXPORT_WORD_ENUM.SUB_PUT_BACK]: {
  371. fileName: '义乌市博物馆分库藏品提退出入库记录单',
  372. templateName: '3.docx'
  373. },
  374. [EXPORT_WORD_ENUM.SUB_PUT_IN]: {
  375. fileName: '义乌市博物馆分库藏品入库记录单',
  376. templateName: '4.docx'
  377. },
  378. [EXPORT_WORD_ENUM.VOUCHER]: {
  379. fileName: '义乌市博物馆入馆凭证',
  380. templateName: '5.docx'
  381. },
  382. [EXPORT_WORD_ENUM.FORM_FOR_DIGITAL]: {
  383. fileName: '义乌市博物馆藏品图片及相关数字化信息使用申请单',
  384. templateName: '6.docx'
  385. },
  386. [EXPORT_WORD_ENUM.COLLECTION_ARCHIVES]: {
  387. fileName: '藏品档案样本电子版',
  388. templateName: '7.docx'
  389. },
  390. [EXPORT_WORD_ENUM.STORAGE_VOUCHER]: {
  391. fileName: '义乌市博物馆入藏凭证',
  392. templateName: '8.docx'
  393. },
  394. [EXPORT_WORD_ENUM.COLLECTION_CARD]: {
  395. fileName: '藏品卡片',
  396. templateName: '9.docx'
  397. }
  398. }
  399. /**
  400. * 根据业务类型导出数据
  401. */
  402. export const exportWordHandler = async (type: EXPORT_WORD_ENUM, data: Record<any, any>) => {
  403. let temp = cloneDeep(data)
  404. let page = 1
  405. let excelHandler: (worksheet: ExcelJS.Worksheet) => void = () => {}
  406. const date = dayjs()
  407. const item = EXPORT_TEMPLATE_MAP[type]
  408. temp.sizeUnit && (temp.sizeUnit = resJiLianFu(temp.sizeUnit))
  409. temp.qualityUnit && (temp.qualityUnit = resJiLianFu(temp.qualityUnit))
  410. temp.dictAge && (temp.dictAge = resJiLianFu(temp.dictAge))
  411. temp.pcsUnit && (temp.pcsUnit = resJiLianFu(temp.pcsUnit))
  412. temp.goods =
  413. (Array.isArray(temp.snaps) && temp.snaps.length
  414. ? temp.snaps.map((i: any) => JSON.parse(i.snap || ''))
  415. : temp.collects) ?? []
  416. if (temp.goods.length) {
  417. for (let i = 0; i < temp.goods.length; i++) {
  418. const good = temp.goods[i]
  419. good.index = i + 1
  420. good.rtf && (good.rtf = removeHtmlTags(JSON.parse(good.rtf).txtArr[0].txt))
  421. // excel 需要判断表格中是否需要图片
  422. if (!item.templateName ? item.options?.sheetFilter.includes('thumb') : good.thumb) {
  423. try {
  424. // good.thumb = await getBase64Sync(
  425. // 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'
  426. // )
  427. good.thumb = await getBase64Sync(baseURL + good.thumb)
  428. } catch (err) {
  429. console.log('thumb conversion to base64 faild:', err)
  430. good.thumb = ''
  431. }
  432. }
  433. good.dictAge && (good.dictAge = resJiLianFu(good.dictAge))
  434. good.pcsUnit && (good.pcsUnit = resJiLianFu(good.pcsUnit))
  435. if (good.pcs) {
  436. good._pcs = good.pcs
  437. good.pcs = good.pcs + good.pcsUnit
  438. }
  439. good.accountType &&
  440. (good.accountType = selectObj['入藏去向'].find(i => i.value === good.accountType)?.label)
  441. good.dictTexture3 && (good.dictTexture = resJiLianFu(good.dictTexture3))
  442. good.dictTorn && (good.dictTorn = resJiLianFu(good.dictTorn))
  443. good.source && (good.source = resJiLianFu(good.source))
  444. good.dictAgeFirst && (good.dictAgeFirst = resJiLianFu(good.dictAgeFirst))
  445. good.qualityUnit && (good.qualityUnit = resJiLianFu(good.qualityUnit))
  446. if (good.sizeUnit || good.quality) {
  447. const arr: string[] = []
  448. if (good.sizeUnit) arr.push(myTableTransferSize(good))
  449. if (good.quality) arr.push('重' + good.quality + good.qualityUnit)
  450. good.size = arr.join('、')
  451. }
  452. }
  453. } else {
  454. temp.goods = []
  455. }
  456. if (item.perLine) {
  457. // @ts-ignore
  458. page = calcTablePages(temp.goods, item)
  459. }
  460. // 处理业务数据
  461. switch (type) {
  462. case EXPORT_WORD_ENUM.BORROW:
  463. temp = {
  464. ...temp,
  465. group: numberToChinese(temp.goods.length),
  466. num: numberToChinese(temp.goods.reduce((sum: number, i: any) => sum + (i._pcs || 0), 0)),
  467. page: numberToChinese(page),
  468. borrowDate: dayjs(temp.createTime).format('YYYY年MM月DD日')
  469. }
  470. break
  471. case EXPORT_WORD_ENUM.HALL_PUT_BACK:
  472. temp = {
  473. ...temp,
  474. year: date.format('YYYY'),
  475. group: numberToChinese(temp.goods.length),
  476. page: numberToChinese(page)
  477. }
  478. break
  479. case EXPORT_WORD_ENUM.SUB_PUT_BACK:
  480. temp = {
  481. ...temp,
  482. year: date.format('YYYY'),
  483. month: date.format('MM'),
  484. day: date.format('DD')
  485. }
  486. break
  487. case EXPORT_WORD_ENUM.COLLECTION_INVENTORY:
  488. temp = {
  489. ...temp,
  490. sonNum2: dayjs(temp.date).format('YYYY') + temp.num
  491. }
  492. temp.goods.forEach((i: any) => {
  493. i.checker = i.cusForm[`${i.id}-checker`]
  494. i.remark = i.cusForm[`${i.id}-remark`]
  495. i.cusForm[`${i.id}-statusCheck`] &&
  496. (i.statusCheck = D7CEHCK_COLLECTION_RESULT_OPTIONS.find(
  497. ii => ii.value === i.cusForm[`${i.id}-statusCheck`]
  498. )?.label)
  499. })
  500. break
  501. case EXPORT_WORD_ENUM.VOUCHER:
  502. case EXPORT_WORD_ENUM.STORAGE_VOUCHER:
  503. const _date = dayjs(temp.date)
  504. temp = {
  505. ...temp,
  506. year: _date.format('YYYY'),
  507. month: _date.format('MM'),
  508. day: _date.format('DD'),
  509. group: numberToChinese(temp.goods.length),
  510. page: numberToChinese(page)
  511. }
  512. break
  513. case EXPORT_WORD_ENUM.FORM_FOR_DIGITAL:
  514. const __date = dayjs(temp.createTime)
  515. temp = {
  516. ...temp,
  517. effect: resJiLianFu(temp.effect),
  518. sonTypeName: MEDIA_TYPES.filter(media => temp.sonTypeName.split(',').includes(media.value))
  519. .map(media => media.label)
  520. .join(','),
  521. year2: date.format('YYYY'),
  522. year: __date.format('YYYY'),
  523. month: __date.format('MM'),
  524. day: __date.format('DD')
  525. }
  526. break
  527. case EXPORT_WORD_ENUM.SUB_PUT_IN:
  528. temp = {
  529. ...temp,
  530. sonSource: resJiLianFu(temp.sonSource),
  531. sonNum2: dayjs(temp.date).format('YYYY') + temp.num,
  532. date: dayjs(temp.date).format('YYYY年MM月DD日')
  533. }
  534. break
  535. case EXPORT_WORD_ENUM.COLLECTION_RELOCATION:
  536. console.log(temp.goods)
  537. temp = {
  538. ...temp,
  539. year: date.format('YYYY'),
  540. month: date.format('MM'),
  541. day: date.format('DD'),
  542. date: dayjs(temp.date).format('YYYY年MM月DD日')
  543. }
  544. break
  545. case EXPORT_WORD_ENUM.ACCIDENT_HANDLING_CERTIFICATE:
  546. temp = {
  547. ...temp,
  548. year: date.format('YYYY'),
  549. rtf: temp.rtf ? removeHtmlTags(JSON.parse(temp.rtf).txtArr[0].txt) : '',
  550. authInfoRtf: removeHtmlTags(JSON.parse(temp.authInfoRtf).txtArr[0].txt),
  551. authResultRtf: removeHtmlTags(JSON.parse(temp.authResultRtf).txtArr[0].txt)
  552. }
  553. break
  554. case EXPORT_WORD_ENUM.COLLECTION_ARCHIVES:
  555. case EXPORT_WORD_ENUM.COLLECTION_CARD:
  556. console.log(temp)
  557. temp = {
  558. ...temp,
  559. year: date.format('YYYY'),
  560. month: date.format('MM'),
  561. day: date.format('DD'),
  562. size: myTableTransferSize(temp),
  563. quality: temp?.qualityDictScope ? resJiLianFu(temp.qualityDictScope) : '',
  564. deptName: (temp.records || []).length ? temp.records[0].deptName : '',
  565. recordDate: (temp.records || []).length ? temp.records[0].createTime : '',
  566. records: (temp.records || []).map(
  567. (item: any) =>
  568. `[${temp.dictLevel}],[${item.createTime}][${item.deptName}][${item.creatorName}]意见。`
  569. )
  570. }
  571. if (type === EXPORT_WORD_ENUM.COLLECTION_ARCHIVES) {
  572. temp.imagePages = await arrangeImages(temp.imagePages)
  573. }
  574. break
  575. case EXPORT_WORD_ENUM.OUTSIDER_FORM:
  576. const memberss = JSON.parse(temp.memberIds)
  577. temp = {
  578. ...temp,
  579. time: dayjs(temp.date).format('HH:mm:ss'),
  580. date: dayjs(temp.date).format('YYYY-MM-DD'),
  581. members: memberss.map((i: any) => i.name),
  582. companys: memberss.map((i: any) => i.remark || '空'),
  583. idCards: memberss.map((i: any) => i.papers || '空'),
  584. phones: memberss.map((i: any) => i.phone || '空')
  585. }
  586. break
  587. case EXPORT_WORD_ENUM.RELIC_REPAIR_LIST:
  588. case EXPORT_WORD_ENUM.COLLECTION_CURRENT_STATUS:
  589. const ___date = dayjs(temp.date)
  590. temp = {
  591. ...temp,
  592. year: ___date.format('YYYY'),
  593. page,
  594. rtf: removeHtmlTags(JSON.parse(temp.rtf).txtArr[0].txt)
  595. }
  596. break
  597. case EXPORT_WORD_ENUM.COLLECTION_LIST:
  598. temp.goods.push({
  599. index: '合计',
  600. name: temp.goods.length,
  601. dictAgeFirst: '合计',
  602. offer: temp.goods.reduce((sum: number, cur: any) => sum + Number(cur.offer), 0)
  603. })
  604. excelHandler = worksheet => {
  605. worksheet.insertRow(1, ['拟征集藏品清单'])
  606. worksheet.mergeCells('A1:F1')
  607. const mergedCell = worksheet.getCell('A1')
  608. mergedCell.style = {
  609. fill: {
  610. type: 'pattern',
  611. pattern: 'solid',
  612. fgColor: { argb: 'cce8cf' }
  613. },
  614. font: {
  615. name: '黑体',
  616. size: 18
  617. }
  618. }
  619. const borderStyle: ExcelJS.Border = {
  620. style: 'thin',
  621. color: { argb: 'FF000000' }
  622. }
  623. for (let row = 2; row <= temp.goods.length + 2; row++) {
  624. for (let col = 1; col <= 6; col++) {
  625. const cell = worksheet.getCell(row, col)
  626. cell.border = {
  627. top: borderStyle,
  628. left: borderStyle,
  629. bottom: borderStyle,
  630. right: borderStyle
  631. }
  632. }
  633. }
  634. worksheet.eachRow(row => {
  635. row.eachCell(cell => {
  636. cell.alignment = {
  637. vertical: 'middle',
  638. horizontal: 'center',
  639. wrapText: true
  640. }
  641. })
  642. })
  643. }
  644. break
  645. case EXPORT_WORD_ENUM.CERTIFICATE:
  646. const resultText = Object.entries(
  647. // @ts-ignore
  648. temp.goods.reduce((acc, { dictLevel }) => {
  649. acc[dictLevel] = (acc[dictLevel] || 0) + 1
  650. return acc
  651. }, {})
  652. )
  653. // @ts-ignore
  654. .filter(([_, count]) => count > 0)
  655. .map(
  656. ([level, count]) =>
  657. `${level === '一般' ? level + '珍贵文物' : level + '文物'}${count}件/组;`
  658. )
  659. .join('\n')
  660. temp.goods.push({
  661. index: '鉴\n定\n人\n员',
  662. num: temp.authUser,
  663. thumb: '鉴\n定\n单\n位',
  664. pcs: temp.authUnit,
  665. dictAge: '核\n准\n单\n位',
  666. dictTorn: '说\n\n明',
  667. size: temp.confirmUnit,
  668. dictLevel: `鉴定日期:${temp.date}\n鉴定总数${temp.goods.length}件/组,其中:\n${resultText}`
  669. })
  670. excelHandler = worksheet => {
  671. const lastIndex = temp.goods.length + 2
  672. worksheet.insertRow(1, ['单位:义乌市博物馆'])
  673. worksheet.mergeCells('A1:H1')
  674. worksheet.mergeCells('I1:L1')
  675. worksheet.mergeCells(`B${lastIndex}:D${lastIndex}`)
  676. worksheet.mergeCells(`F${lastIndex}:G${lastIndex}`)
  677. worksheet.mergeCells(`K${lastIndex}:L${lastIndex}`)
  678. worksheet.eachRow(row => {
  679. const col5 = row.getCell(5)
  680. if (isNumber(col5.value)) {
  681. worksheet.addImage(col5.value, `${col5.address}:${col5.address}`)
  682. }
  683. row.eachCell(cell => {
  684. cell.style = {
  685. font: {
  686. name: '宋体',
  687. size: 10
  688. }
  689. }
  690. cell.alignment = {
  691. vertical: 'middle',
  692. horizontal: 'center',
  693. wrapText: true
  694. }
  695. })
  696. })
  697. const titleCell = worksheet.getCell('A1')
  698. const dateCell = worksheet.getCell('I1')
  699. const lastCell = worksheet.getRow(lastIndex)
  700. const borderStyle: ExcelJS.Border = {
  701. style: 'thin',
  702. color: { argb: 'FF000000' }
  703. }
  704. lastCell.height = 80
  705. titleCell.style = {
  706. fill: {
  707. type: 'pattern',
  708. pattern: 'solid',
  709. fgColor: { argb: 'cce8cf' }
  710. },
  711. font: {
  712. size: 16
  713. },
  714. alignment: {
  715. horizontal: 'left',
  716. vertical: 'middle'
  717. }
  718. }
  719. dateCell.value = '日期:' + temp.createTime.split(' ')[0]
  720. dateCell.style = {
  721. fill: {
  722. type: 'pattern',
  723. pattern: 'solid',
  724. fgColor: { argb: 'cce8cf' }
  725. },
  726. font: {
  727. size: 16
  728. },
  729. alignment: {
  730. horizontal: 'right',
  731. vertical: 'middle'
  732. }
  733. }
  734. for (let row = 1; row <= lastIndex; row++) {
  735. for (let col = 1; col <= 12; col++) {
  736. const cell = worksheet.getCell(row, col)
  737. cell.border = {
  738. top: borderStyle,
  739. left: borderStyle,
  740. bottom: borderStyle,
  741. right: borderStyle
  742. }
  743. }
  744. }
  745. }
  746. break
  747. case EXPORT_WORD_ENUM.CANCEL_VOUCHER:
  748. temp.goods.push({
  749. num: '法定代表人:',
  750. dictAge: '保管部负责人:',
  751. torn: '保管员:',
  752. txt1: '珍贵文物注销审批文号:'
  753. })
  754. excelHandler = worksheet => {
  755. const lastIndex = temp.goods.length + 4
  756. const borderStyle: ExcelJS.Border = {
  757. style: 'thin',
  758. color: { argb: 'FF000000' }
  759. }
  760. worksheet.eachRow(row => {
  761. row.eachCell(cell => {
  762. cell.style = {
  763. font: {
  764. name: '宋体',
  765. size: 10
  766. }
  767. }
  768. cell.alignment = {
  769. vertical: 'middle',
  770. horizontal: 'center',
  771. wrapText: true
  772. }
  773. })
  774. })
  775. worksheet.insertRow(1, [])
  776. worksheet.mergeCells('A1:K1')
  777. worksheet.getCell('A1').value = {
  778. richText: [
  779. { font: { size: 20, name: '黑体' }, text: '馆藏品注销凭证 ' },
  780. { font: { size: 11 }, text: '(编号: ) ' }
  781. ]
  782. }
  783. worksheet.getRow(1).height = 60
  784. worksheet.getCell('A1').style = {
  785. alignment: {
  786. horizontal: 'center',
  787. vertical: 'middle'
  788. }
  789. }
  790. worksheet.insertRow(2, [date.format('YYYY年MM月DD日')])
  791. worksheet.mergeCells('A2:K2')
  792. worksheet.getRow(2).height = 30
  793. worksheet.getCell('A2').style = {
  794. font: {
  795. size: 11,
  796. name: '仿宋_GB2312'
  797. },
  798. alignment: {
  799. horizontal: 'right',
  800. vertical: 'middle'
  801. }
  802. }
  803. worksheet.insertRow(3, [
  804. `现将藏品_${temp.goods.length}_件注销,清单开列如下,本凭证连同附页全份共______页(含附件)`
  805. ])
  806. worksheet.mergeCells('A3:K3')
  807. worksheet.getRow(3).height = 30
  808. worksheet.getCell('A3').style = {
  809. font: {
  810. size: 11,
  811. name: '仿宋_GB2312'
  812. },
  813. alignment: {
  814. horizontal: 'center',
  815. vertical: 'middle'
  816. }
  817. }
  818. worksheet.mergeCells(`A${lastIndex}:C${lastIndex}`)
  819. worksheet.mergeCells(`D${lastIndex}:F${lastIndex}`)
  820. worksheet.mergeCells(`G${lastIndex}:H${lastIndex}`)
  821. worksheet.mergeCells(`I${lastIndex}:K${lastIndex}`)
  822. for (let row = 1; row <= lastIndex; row++) {
  823. for (let col = 1; col <= 11; col++) {
  824. const cell = worksheet.getCell(row, col)
  825. cell.border = {
  826. top: borderStyle,
  827. left: borderStyle,
  828. bottom: borderStyle,
  829. right: borderStyle
  830. }
  831. }
  832. }
  833. }
  834. break
  835. case EXPORT_WORD_ENUM.REGISTER_LEDGER:
  836. const totalPcs = temp.goods.reduce((sum: number, i: any) => sum + (i._pcs || 0), 0)
  837. temp.goods.forEach((i: any) => {
  838. i.year = date.format('YYYY') + '年度'
  839. i.sonUnit = temp.sonUnit
  840. i.typeName = temp.typeName
  841. i.lendDate = dayjs(i.cusForm[`${i.id}-lendDate`]).format('YYYY年MM月DD日')
  842. i.lenderA = i.cusForm[`${i.id}-lenderA`]
  843. i.lenderb = i.cusForm[`${i.id}-lenderb`]
  844. i.sonNum = temp.sonNum
  845. i.sonNum2 = temp.sonNum2
  846. i.handlerA = i.cusForm[`${i.id}-handlerA`]
  847. i.handlerB = i.cusForm[`${i.id}-handlerB`]
  848. i.recorder = i.cusForm[`${i.id}-recorder`]
  849. i.remark = i.cusForm[`${i.id}-remark`]
  850. i.pcs = `${i.pcs},计${totalPcs}件`
  851. const expectedReturnDate = i.cusForm[`${i.id}-expectedReturnDate`]
  852. expectedReturnDate &&
  853. (i.expectedReturnDate = dayjs(expectedReturnDate).format('YYYY年MM月DD日'))
  854. const returnDate = i.cusForm[`${i.id}-returnDate`]
  855. returnDate && (i.returnDate = dayjs(returnDate).format('YYYY年MM月DD日'))
  856. })
  857. excelHandler = worksheet => {
  858. const borderStyle: ExcelJS.Border = {
  859. style: 'thin',
  860. color: { argb: 'FF000000' }
  861. }
  862. for (let row = 1; row <= temp.goods.length + 2; row++) {
  863. for (let col = 1; col <= 18; col++) {
  864. const cell = worksheet.getCell(row, col)
  865. cell.border = {
  866. top: borderStyle,
  867. left: borderStyle,
  868. bottom: borderStyle,
  869. right: borderStyle
  870. }
  871. }
  872. }
  873. worksheet.eachRow(row => {
  874. row.eachCell(cell => {
  875. cell.alignment = {
  876. vertical: 'middle',
  877. horizontal: 'center',
  878. wrapText: true
  879. }
  880. })
  881. })
  882. }
  883. break
  884. case EXPORT_WORD_ENUM.COLLECTION_LOG:
  885. excelHandler = worksheet => {
  886. const borderStyle: ExcelJS.Border = {
  887. style: 'thin',
  888. color: { argb: 'FF000000' }
  889. }
  890. for (let row = 1; row <= temp.goods.length + 2; row++) {
  891. for (let col = 1; col <= 14; col++) {
  892. const cell = worksheet.getCell(row, col)
  893. cell.border = {
  894. top: borderStyle,
  895. left: borderStyle,
  896. bottom: borderStyle,
  897. right: borderStyle
  898. }
  899. }
  900. }
  901. worksheet.eachRow(row => {
  902. row.eachCell(cell => {
  903. cell.alignment = {
  904. vertical: 'middle',
  905. horizontal: 'center',
  906. wrapText: true
  907. }
  908. })
  909. })
  910. }
  911. break
  912. case EXPORT_WORD_ENUM.COLLECTION_LEDGER:
  913. temp.goods.forEach((i: any) => {
  914. const createTime = dayjs(i.createTime)
  915. const inHouseTime = dayjs(i.createTime)
  916. i.year = createTime.format('YYYY')
  917. i.month = createTime.format('MM')
  918. i.day = createTime.format('DD')
  919. i.year2 = inHouseTime.format('YYYY')
  920. i.month2 = inHouseTime.format('MM')
  921. i.day2 = inHouseTime.format('DD')
  922. })
  923. excelHandler = worksheet => {
  924. const borderStyle: ExcelJS.Border = {
  925. style: 'thin',
  926. color: { argb: 'FF000000' }
  927. }
  928. for (let row = 1; row <= temp.goods.length + 2; row++) {
  929. for (let col = 1; col <= 21; col++) {
  930. const cell = worksheet.getCell(row, col)
  931. cell.border = {
  932. top: borderStyle,
  933. left: borderStyle,
  934. bottom: borderStyle,
  935. right: borderStyle
  936. }
  937. }
  938. }
  939. worksheet.eachRow(row => {
  940. row.eachCell(cell => {
  941. cell.alignment = {
  942. vertical: 'middle',
  943. horizontal: 'center',
  944. wrapText: true
  945. }
  946. })
  947. })
  948. }
  949. break
  950. }
  951. if (!item.templateName) {
  952. // 没有templateName则输出 excel
  953. exportTempExcel(item.fileName, (worksheet, workbook) => {
  954. let mergeHeadNum = 0
  955. let headTemp: string[] = []
  956. let fatherHeadTemp: {
  957. title: string
  958. position: string[]
  959. }[] = []
  960. // 表头需要占据的行数
  961. const headRow = Math.max(
  962. ...item.options?.sheetHeader.map((head: string | string[]) => (Array.isArray(head) ? 2 : 1))
  963. )
  964. item.options?.sheetHeader.forEach((head: string | string[], index: number) => {
  965. if (Array.isArray(head)) {
  966. fatherHeadTemp.push({
  967. title: head.shift() || '',
  968. position: [
  969. `${getExcelColumnLetter(index + mergeHeadNum)}1`,
  970. `${getExcelColumnLetter(index + head.length - 1 + mergeHeadNum)}1`
  971. ]
  972. })
  973. headTemp.push(...head)
  974. mergeHeadNum += head.length - 1
  975. } else {
  976. headTemp.push(head)
  977. }
  978. })
  979. worksheet.addRow(headTemp)
  980. if (fatherHeadTemp.length) {
  981. // 存在需要合并的父级表头
  982. worksheet.insertRow(1, [])
  983. fatherHeadTemp.forEach(head => {
  984. const cell = worksheet.getCell(head.position[0])
  985. cell.value = head.title
  986. worksheet.mergeCells(`${head.position[0]}:${head.position[1]}`)
  987. })
  988. }
  989. if (headRow > 1) {
  990. // 合并表头列
  991. headTemp.forEach((head, index) => {
  992. const pos = `${getExcelColumnLetter(index)}1:${getExcelColumnLetter(index)}${headRow}`
  993. const cell = worksheet.getCell(`${getExcelColumnLetter(index)}1`)
  994. if (!cell.isMerged) {
  995. worksheet.mergeCells(pos)
  996. cell.value = head
  997. }
  998. })
  999. }
  1000. temp.goods.forEach((good: Record<string, any>, goodIndex: number) => {
  1001. const _temp: string[] = []
  1002. item.options?.sheetFilter.forEach((key: string, index: number) => {
  1003. if (key === 'thumb' && Boolean(good[key])) {
  1004. const extension = getImageBase64Extension(good[key])
  1005. if (extension) {
  1006. // 插入图片
  1007. const imageId = workbook.addImage({
  1008. base64: good[key],
  1009. extension
  1010. })
  1011. good[key] = imageId
  1012. }
  1013. }
  1014. _temp.push(good[key])
  1015. })
  1016. worksheet.addRow(_temp)
  1017. })
  1018. // 设置宽度
  1019. item.options?.columnWidths.forEach((width: number, index: number) => {
  1020. worksheet.getColumn(index + 1).width = width
  1021. })
  1022. excelHandler(worksheet)
  1023. })
  1024. } else {
  1025. // 输出 word
  1026. exportWordDocx(`./templates/${item.templateName}`, temp, item.fileName)
  1027. }
  1028. }