add-export-to-nine-precautions-v2.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. const fs = require('fs')
  2. const path = require('path')
  3. const { execSync } = require('child_process')
  4. const baseDir = path.resolve(__dirname, '../src/views/elderly/apply/nine-precautions')
  5. const configs = [
  6. {
  7. dir: 'MMSE',
  8. pageApi: 'mmseGetPage',
  9. title: 'MMSE认知评估',
  10. columns: [
  11. { key: 'orgName', title: '机构名称' },
  12. { key: 'elderName', title: '长者姓名' },
  13. { key: 'assessor', title: '评估人' },
  14. { key: 'assessDate', title: '记录日期' },
  15. { key: 'riskLevelText', title: '风险等级' },
  16. { key: 'creator', title: '记录人' }
  17. ],
  18. riskMode: 'info'
  19. },
  20. {
  21. dir: 'anti-entertainment',
  22. pageApi: 'entertainmentPage',
  23. title: '防文娱活动意外评估',
  24. columns: [
  25. { key: 'orgName', title: '机构名称' },
  26. { key: 'elderName', title: '长者姓名' },
  27. { key: 'assessor', title: '评估人' },
  28. { key: 'assessDate', title: '记录日期' },
  29. { key: 'assessScore', title: '评估总得分' },
  30. { key: 'riskLevelText', title: '风险等级' },
  31. { key: 'creator', title: '记录人' }
  32. ],
  33. riskMode: 'text'
  34. },
  35. {
  36. dir: 'asphyxiation-by-choking',
  37. pageApi: 'asphyxiationPage',
  38. title: '防噎食评估',
  39. columns: [
  40. { key: 'orgName', title: '机构名称' },
  41. { key: 'elderName', title: '长者姓名' },
  42. { key: 'assessor', title: '评估人' },
  43. { key: 'assessDate', title: '记录日期' },
  44. { key: 'riskLevelText', title: '风险等级' },
  45. { key: 'creator', title: '记录人' }
  46. ],
  47. riskMode: 'text'
  48. },
  49. {
  50. dir: 'attack',
  51. pageApi: 'attackRiskPage',
  52. title: '攻击风险评估',
  53. columns: [
  54. { key: 'orgName', title: '机构名称' },
  55. { key: 'elderName', title: '长者姓名' },
  56. { key: 'assessor', title: '评估人' },
  57. { key: 'riskLevelText', title: '风险等级' },
  58. { key: 'assessDate', title: '记录日期' },
  59. { key: 'creator', title: '记录人' }
  60. ],
  61. riskMode: 'info'
  62. },
  63. {
  64. dir: 'commit-suicide',
  65. pageApi: 'ngasrPage',
  66. title: '自伤自杀风险评估',
  67. columns: [
  68. { key: 'orgName', title: '机构名称' },
  69. { key: 'elderName', title: '长者姓名' },
  70. { key: 'assessor', title: '评估人' },
  71. { key: 'assessDate', title: '记录日期' },
  72. { key: 'riskLevelText', title: '风险等级' },
  73. { key: 'creator', title: '记录人' }
  74. ],
  75. riskMode: 'info'
  76. },
  77. {
  78. dir: 'communication',
  79. pageApi: 'perceptionPage',
  80. title: '感知沟通评估',
  81. columns: [
  82. { key: 'orgName', title: '机构名称' },
  83. { key: 'elderName', title: '长者姓名' },
  84. { key: 'assessor', title: '评估人' },
  85. { key: 'assessDate', title: '记录日期' },
  86. { key: 'riskLevelText', title: '风险等级' },
  87. { key: 'creator', title: '记录人' }
  88. ],
  89. riskMode: 'info'
  90. },
  91. {
  92. dir: 'daily-life',
  93. pageApi: 'dailyLifePage',
  94. title: '日常生活活动能力评估',
  95. columns: [
  96. { key: 'orgName', title: '机构名称' },
  97. { key: 'elderName', title: '长者姓名' },
  98. { key: 'assessor', title: '评估人' },
  99. { key: 'assessDate', title: '记录日期' },
  100. { key: 'assessScore', title: '评估总得分' },
  101. { key: 'riskLevelText', title: '结果等级' },
  102. { key: 'creator', title: '记录人' }
  103. ],
  104. riskMode: 'result'
  105. },
  106. {
  107. dir: 'empyrosis',
  108. pageApi: 'burnPreventionPage',
  109. title: '防烫伤评估',
  110. columns: [
  111. { key: 'orgName', title: '机构名称' },
  112. { key: 'elderName', title: '长者姓名' },
  113. { key: 'assessor', title: '评估人' },
  114. { key: 'assessDate', title: '记录日期' },
  115. { key: 'riskLevelText', title: '风险等级' },
  116. { key: 'assessScore', title: '评估总得分' },
  117. { key: 'creator', title: '记录人' }
  118. ],
  119. riskMode: 'text'
  120. },
  121. {
  122. dir: 'equilibrium',
  123. pageApi: 'equilibriumPage',
  124. title: '平衡能力评估',
  125. columns: [
  126. { key: 'orgName', title: '机构名称' },
  127. { key: 'elderName', title: '长者姓名' },
  128. { key: 'assessor', title: '评估人' },
  129. { key: 'assessDate', title: '记录日期' },
  130. { key: 'assessScore', title: '评估总得分' },
  131. { key: 'riskLevelText', title: '风险等级' },
  132. { key: 'creator', title: '记录人' }
  133. ],
  134. riskMode: 'text'
  135. },
  136. {
  137. dir: 'fall-down',
  138. pageApi: 'fallDownPage',
  139. title: '跌倒风险评估',
  140. columns: [
  141. { key: 'orgName', title: '机构名称' },
  142. { key: 'elderName', title: '长者姓名' },
  143. { key: 'assessor', title: '评估人' },
  144. { key: 'assessDate', title: '记录日期' },
  145. { key: 'assessScore', title: '评估总得分' },
  146. { key: 'riskLevelText', title: '风险等级' },
  147. { key: 'creator', title: '记录人' }
  148. ],
  149. riskMode: 'text'
  150. },
  151. {
  152. dir: 'fall-prevention-measures',
  153. pageApi: 'fallPreventionPage',
  154. title: '防坠床评估',
  155. columns: [
  156. { key: 'orgName', title: '机构名称' },
  157. { key: 'elderName', title: '长者姓名' },
  158. { key: 'assessor', title: '评估人' },
  159. { key: 'assessDate', title: '记录日期' },
  160. { key: 'assessScore', title: '评估总得分' },
  161. { key: 'riskLevelText', title: '风险等级' },
  162. { key: 'creator', title: '记录人' }
  163. ],
  164. riskMode: 'text'
  165. },
  166. {
  167. dir: 'pressure-sores',
  168. pageApi: 'pressureSoresPage',
  169. title: '防压疮评估',
  170. columns: [
  171. { key: 'orgName', title: '机构名称' },
  172. { key: 'elderName', title: '长者姓名' },
  173. { key: 'assessor', title: '评估人' },
  174. { key: 'assessDate', title: '记录日期' },
  175. { key: 'assessScore', title: '评估总得分' },
  176. { key: 'riskLevelText', title: '风险等级' },
  177. { key: 'creator', title: '记录人' }
  178. ],
  179. riskMode: 'text'
  180. },
  181. {
  182. dir: 'nutritional-risk',
  183. pageApi: 'nutritionalRiskPage',
  184. title: '营养风险评估',
  185. columns: [
  186. { key: 'orgName', title: '机构名称' },
  187. { key: 'elderName', title: '长者姓名' },
  188. { key: 'assessor', title: '评估人' },
  189. { key: 'assessDate', title: '记录日期' },
  190. { key: 'assessScore', title: '量表总分' },
  191. { key: 'riskLevelText', title: '评估结果' },
  192. { key: 'creator', title: '记录人' }
  193. ],
  194. riskMode: 'result'
  195. },
  196. {
  197. dir: 'wander-away',
  198. pageApi: 'wanderAwayPage',
  199. title: '防走失风险评估',
  200. columns: [
  201. { key: 'orgName', title: '机构名称' },
  202. { key: 'elderName', title: '长者姓名' },
  203. { key: 'assessor', title: '评估人' },
  204. { key: 'assessDate', title: '记录日期' },
  205. { key: 'assessScore', title: '评估总得分' },
  206. { key: 'riskLevelText', title: '风险等级' },
  207. { key: 'creator', title: '记录人' }
  208. ],
  209. riskMode: 'text'
  210. }
  211. ]
  212. function buildExportFunction(config) {
  213. const { pageApi, title, columns, riskMode } = config
  214. const headersStr = JSON.stringify(columns, null, 6)
  215. .replace(/"/g, "'")
  216. .replace(/\n /g, '\n ')
  217. let riskLevelProcess = ''
  218. if (riskMode === 'info') {
  219. riskLevelProcess = `const riskInfo = getRiskLevelInfo(item.assessData)
  220. row.riskLevelText = riskInfo.text || '-'`
  221. } else if (riskMode === 'text') {
  222. riskLevelProcess = `row.riskLevelText = getRiskLevelText(item.riskLevel) || '-'`
  223. } else if (riskMode === 'result') {
  224. riskLevelProcess = `row.riskLevelText = getResultLevelText(item.riskLevel) || '-'`
  225. }
  226. return `// 打开导出弹窗
  227. const handleImportCard = async () => {
  228. exportLoading.value = true
  229. try {
  230. const queryP = {
  231. pageNo: 1,
  232. pageSize: 9999,
  233. elderName: queryParams.elderName,
  234. assessor: queryParams.assessor,
  235. assessDate: queryParams.assessDate,
  236. tenantIds: queryParams.tenantIds
  237. }
  238. const data = await ${pageApi}(queryP)
  239. const exportData = data.list || []
  240. if (exportData.length === 0) {
  241. message.warning('暂无数据可导出')
  242. return
  243. }
  244. const processedData = exportData.map((item) => {
  245. const row: any = {
  246. orgName: findLabelById(userStore.getOrgTenant.options, item.tenantId) || '',
  247. elderName: item.elderName || '',
  248. assessor: item.assessor || '',
  249. assessDate: item.assessDate || '',
  250. assessScore: item.assessScore ?? '',
  251. creator: item.creator || ''
  252. }
  253. ${riskLevelProcess}
  254. return row
  255. })
  256. const headers = ${headersStr}
  257. exportWithExpandedObjectArrays(processedData, headers, \`${title}_\${new Date().getTime()}.xlsx\`, '${title}')
  258. message.success('导出成功')
  259. } catch (error) {
  260. console.error('导出失败:', error)
  261. message.error('导出失败,请重试')
  262. } finally {
  263. exportLoading.value = false
  264. }
  265. }
  266. `
  267. }
  268. // 从 git 读取原始文件
  269. function readOriginal(relativePath) {
  270. return execSync(`git show HEAD:${relativePath}`, {
  271. cwd: path.resolve(__dirname, '..'),
  272. encoding: 'utf-8'
  273. })
  274. }
  275. function removeBlockByRegex(content, regex) {
  276. const match = content.match(regex)
  277. if (!match) return content
  278. const start = match.index
  279. let depth = 0
  280. let end = start
  281. for (let i = start; i < content.length; i++) {
  282. if (content[i] === '{') depth++
  283. if (content[i] === '}') {
  284. depth--
  285. if (depth === 0) {
  286. end = i + 1
  287. break
  288. }
  289. }
  290. }
  291. let before = content.slice(0, start)
  292. let after = content.slice(end)
  293. // 去掉后面多余的换行
  294. if (after.startsWith('\n')) after = after.slice(1)
  295. if (after.startsWith('\n')) after = after.slice(1)
  296. return before + after
  297. }
  298. function processFile(config) {
  299. const relativePath = `src/views/elderly/apply/nine-precautions/${config.dir}/index.vue`
  300. const filePath = path.resolve(__dirname, '..', relativePath)
  301. let content = readOriginal(relativePath)
  302. // 1. 添加 ButtonImport 导入
  303. const buttonAddImport = "import ButtonAdd from '@/components/ButtonAdd/src/ButtonAdd.vue'"
  304. if (content.includes(buttonAddImport)) {
  305. content = content.replace(
  306. buttonAddImport,
  307. `${buttonAddImport}\nimport ButtonImport from '@/components/ButtonImport/src/ButtonImport.vue'`
  308. )
  309. } else {
  310. // nutritional-risk 没有 ButtonAdd import,ButtonAdd 是全局注册的
  311. content = content.replace(
  312. '<script setup lang="ts">',
  313. '<script setup lang="ts">\nimport ButtonImport from \'@/components/ButtonImport/src/ButtonImport.vue\''
  314. )
  315. }
  316. // 2. 添加 exportWithExpandedObjectArrays 导入
  317. const apiImportMatch = content.match(/import \{[^}]+\} from '@\/api\/social-work'/)
  318. if (apiImportMatch) {
  319. const insertPos = apiImportMatch.index + apiImportMatch[0].length
  320. content = content.slice(0, insertPos) + "\nimport { exportWithExpandedObjectArrays } from '@/utils/excel-export'" + content.slice(insertPos)
  321. } else {
  322. content = content.replace(
  323. '<script setup lang="ts">',
  324. '<script setup lang="ts">\nimport { exportWithExpandedObjectArrays } from \'@/utils/excel-export\''
  325. )
  326. }
  327. // 3. 添加导出按钮
  328. content = content.replace(
  329. /<ButtonAdd @click="openForm\(undefined\)"\s*\/>/g,
  330. '<ButtonAdd @click="openForm(undefined)" />\n <ButtonImport @click="handleImportCard" />'
  331. )
  332. // 移除旧的注释导入按钮
  333. content = content.replace(/\s*<!--\s*<ButtonImport[^>]*>\s*-->\s*/g, '\n')
  334. // 4. 移除 BatchExportDialog
  335. content = content.replace(
  336. /\s*<!-- 通用批量导出弹窗 -->\s*<BatchExportDialog[\s\S]*?<\/BatchExportDialog>/,
  337. ''
  338. )
  339. // 5. 移除旧的 handleImportCard / handleBatchExport / handleExport 空壳函数
  340. content = removeBlockByRegex(
  341. content,
  342. /\/\/ 打开导出弹窗\s*const handleImportCard = async \(\) => \{/
  343. )
  344. content = removeBlockByRegex(
  345. content,
  346. /\/\/ 处理批量导出\s*const handleBatchExport = async \(batch: number, count: number\) => \{/
  347. )
  348. content = removeBlockByRegex(
  349. content,
  350. /const handleExport = \(\) => \{/
  351. )
  352. // 6. 精简状态管理为只保留 exportLoading
  353. content = content.replace(
  354. /\n\/\/ 状态管理\s*const showBatchExport = ref\(false\)\s*const exportConfig = ref\(\{[\s\S]*?description: \[\] as string\[\]\s*\}\)\s*const exportLoading = ref\(false\)\s*/,
  355. '\nconst exportLoading = ref(false)\n'
  356. )
  357. // 7. 插入新的 handleImportCard 函数
  358. const exportFunc = buildExportFunction(config)
  359. const queryFormRefPattern = /const queryFormRef = ref\(\)\s*\/\/ 搜索的表单/
  360. if (queryFormRefPattern.test(content)) {
  361. content = content.replace(queryFormRefPattern, `const queryFormRef = ref() // 搜索的表单\n\n${exportFunc}`)
  362. } else {
  363. content = content.replace(
  364. /const queryFormRef = ref\(\)\s*$/m,
  365. `const queryFormRef = ref()\n\n${exportFunc}`
  366. )
  367. }
  368. fs.writeFileSync(filePath, content, 'utf-8')
  369. console.log(`已处理:${filePath}`)
  370. }
  371. configs.forEach(processFile)