vue2-client 1.17.39 → 1.17.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (353) hide show
  1. package/.claude/settings.local.json +20 -20
  2. package/.cursorrules +19 -19
  3. package/.env.apply +19 -19
  4. package/.env.gaslink +19 -19
  5. package/.env.his +19 -19
  6. package/.env.liuli +20 -20
  7. package/.env.scada +19 -19
  8. package/.eslintrc.js +90 -90
  9. package/.serena/memories/code_style_conventions.md +217 -217
  10. package/.serena/memories/project_overview.md +54 -54
  11. package/.serena/memories/project_structure.md +329 -329
  12. package/.serena/memories/suggested_commands.md +127 -127
  13. package/.serena/memories/task_completion_checklist.md +183 -183
  14. package/.serena/memories/tech_stack.md +94 -94
  15. package/CHANGELOG.md +830 -830
  16. package/CLAUDE.md +97 -97
  17. package/Components.md +60 -60
  18. package/docs/LowCode/lowcode.md +155 -155
  19. package/docs/LowCode/lowcodeForDeveloper.md +230 -230
  20. package/docs/index.md +30 -30
  21. package/index.js +31 -31
  22. package/jest-transform-stub.js +8 -8
  23. package/jest.setup.js +7 -7
  24. package/jsconfig.json +19 -19
  25. package/package.json +1 -1
  26. package/public/his/editor/editor.html +51 -51
  27. package/public/his/editor/mock/bind_data.html +779 -779
  28. package/public/his/editor/mock/data_table.html +40 -40
  29. package/public/his/editor/mock/sign.html +75 -75
  30. package/public/his/editor/vender/JsBarcode.all.js +3669 -3669
  31. package/public/his/editor/vender/date97/My97DatePicker.htm +65 -65
  32. package/public/his/editor/vender/date97/WdatePicker.js +677 -677
  33. package/public/his/editor/vender/date97/calendar.js +4 -4
  34. package/public/his/editor/vender/date97/lang/en.js +13 -13
  35. package/public/his/editor/vender/date97/lang/zh-cn.js +13 -13
  36. package/public/his/editor/vender/date97/lang/zh-tw.js +13 -13
  37. package/public/his/editor/vender/date97/skin/WdatePicker.css +10 -10
  38. package/public/his/editor/vender/date97/skin/default/datepicker.css +328 -328
  39. package/public/his/editor/vender/date97/skin/ext/datepicker.css +308 -308
  40. package/public/his/editor/vender/date97/skin/whyGreen/datepicker.css +255 -255
  41. package/public/his/editor/vender/diff.js +1627 -1627
  42. package/public/his/editor/vender/editor.js +1 -1
  43. package/public/his/editor/vender/fabric.js +31187 -31187
  44. package/public/his/editor/vender/jquery/jquery.base64.js +190 -190
  45. package/public/his/editor/vender/jquery/jquery.js +10872 -10872
  46. package/public/his/editor/vender/jquery/jquery.print.js +255 -255
  47. package/public/his/editor/vender/jquery/zTreeStyle/zTreeStyle.css +96 -96
  48. package/public/his/editor/vender/mui/mui.min.css +4 -4
  49. package/public/his/editor/vender/mui/mui.min.js +5 -5
  50. package/public/his/editor/vender/mui/mui.picker.min.css +6 -6
  51. package/public/his/editor/vender/mui/mui.picker.min.js +6 -6
  52. package/public/his/editor/vender/qrcode.js +7 -7
  53. package/public/his/editor/vender/requirejs/require.js +2145 -2145
  54. package/public/his/editor/vender/signature/jSignature.CompressorSVG.js +518 -518
  55. package/public/his/editor/vender/signature/jSignature.UndoButton.js +164 -164
  56. package/public/his/editor/vender/signature/jSignature.js +1486 -1486
  57. package/public/his/editor/vender/validator.js +5094 -5094
  58. package/public/his/editor/vender/weui/weui.css +5659 -5659
  59. package/public/his/editor/vender/weui/weui.min.css +4 -4
  60. package/public/his/editor/vender/weui/weui.min.js +11 -11
  61. package/src/assets/img/paymentMethod/package.info +1 -1
  62. package/src/assets/img/querySlotDemo.svg +15 -15
  63. package/src/assets/svg/badtwo.svg +1 -1
  64. package/src/assets/svg/female.svg +1 -1
  65. package/src/assets/svg/goodtwo.svg +1 -1
  66. package/src/assets/svg/male.svg +1 -1
  67. package/src/base-client/components/AI/AskAiBtn.vue +136 -136
  68. package/src/base-client/components/AI/demo.vue +31 -31
  69. package/src/base-client/components/common/AddressSearchCombobox/IcMapIcon.vue +16 -16
  70. package/src/base-client/components/common/AddressSearchCombobox/demo.vue +36 -36
  71. package/src/base-client/components/common/AddressSearchCombobox/ic_map.svg +6 -6
  72. package/src/base-client/components/common/AmapMarker/AmapPointRendering.vue +120 -120
  73. package/src/base-client/components/common/CitySelect/index.js +3 -3
  74. package/src/base-client/components/common/CitySelect/index.md +109 -109
  75. package/src/base-client/components/common/CreateQuery/CreateQuery.vue +669 -669
  76. package/src/base-client/components/common/CreateQuery/CreateQueryItem.vue +1014 -1014
  77. package/src/base-client/components/common/CreateQuery/index.js +3 -3
  78. package/src/base-client/components/common/CreateQuery/index.md +42 -42
  79. package/src/base-client/components/common/CreateSimpleFormQuery/CreateSimpleFormQuery.vue +452 -452
  80. package/src/base-client/components/common/CreateSimpleFormQuery/CreateSimpleFormQueryItem.vue +511 -511
  81. package/src/base-client/components/common/CreateSimpleFormQuery/index.js +3 -3
  82. package/src/base-client/components/common/CreateSimpleFormQuery/index.md +42 -42
  83. package/src/base-client/components/common/FormGroupEdit/index.js +3 -3
  84. package/src/base-client/components/common/FormGroupEdit/index.md +43 -43
  85. package/src/base-client/components/common/FormGroupQuery/FormGroupQuery.vue +166 -166
  86. package/src/base-client/components/common/FormGroupQuery/index.js +3 -3
  87. package/src/base-client/components/common/FormGroupQuery/index.md +43 -43
  88. package/src/base-client/components/common/HIS/HButtons/HButtons.vue +491 -491
  89. package/src/base-client/components/common/HIS/HFormGroup/index.js +3 -3
  90. package/src/base-client/components/common/HIS/HTab/HTab.vue +443 -443
  91. package/src/base-client/components/common/HIS/demo.vue +61 -61
  92. package/src/base-client/components/common/JSONToTree/jsontotree.vue +271 -271
  93. package/src/base-client/components/common/LowCodeComponent/LowCodeEditorModal.vue +108 -108
  94. package/src/base-client/components/common/LowCodeComponent/LowCodeEditorPanel.vue +413 -413
  95. package/src/base-client/components/common/LowCodeComponent/LowCodePageOrganization.vue +502 -502
  96. package/src/base-client/components/common/LowCodeComponent/LowCodeRender.vue +728 -728
  97. package/src/base-client/components/common/LowCodeComponent/LowCodeRenderEnter.vue +29 -29
  98. package/src/base-client/components/common/LowCodeComponent/LowCodeUIStore.vue +219 -219
  99. package/src/base-client/components/common/LowCodeComponent/modal/lowCodeAddPageModal.vue +117 -117
  100. package/src/base-client/components/common/LowCodeComponent/modal/lowCodeCustomJSModal.vue +80 -80
  101. package/src/base-client/components/common/LowCodeComponent/modal/lowCodeEventEditorModal.vue +398 -398
  102. package/src/base-client/components/common/LowCodeComponent/modal/lowCodeLifeCycleModal.vue +65 -65
  103. package/src/base-client/components/common/LowCodeComponent/modal/lowCodeLogicCallbackModal.vue +64 -64
  104. package/src/base-client/components/common/LowCodeComponent/modal/lowCodeLogicParamModal.vue +73 -73
  105. package/src/base-client/components/common/LowCodeComponent/modal/lowCodeRunFunctionParamModal.vue +76 -76
  106. package/src/base-client/components/common/PersonSetting/PersonSetting.vue +208 -208
  107. package/src/base-client/components/common/PersonSetting/index.js +3 -3
  108. package/src/base-client/components/common/Recording/Recording.vue +243 -243
  109. package/src/base-client/components/common/Recording/index.js +3 -3
  110. package/src/base-client/components/common/Tree/Tree.vue +149 -149
  111. package/src/base-client/components/common/Tree/index.js +2 -2
  112. package/src/base-client/components/common/Upload/index.js +3 -3
  113. package/src/base-client/components/common/XAddForm/XAddForm.vue +113 -113
  114. package/src/base-client/components/common/XAddNativeForm/index.md +146 -146
  115. package/src/base-client/components/common/XAddNativeFormOA/XAddNativeFormOA.vue +304 -304
  116. package/src/base-client/components/common/XAddNativeFormOA/index.js +3 -3
  117. package/src/base-client/components/common/XAddNativeFormOA/index.md +146 -146
  118. package/src/base-client/components/common/XAddReport/index.js +3 -3
  119. package/src/base-client/components/common/XAddReport/index.md +56 -56
  120. package/src/base-client/components/common/XBadge/XBadge.vue +94 -94
  121. package/src/base-client/components/common/XButtons/XButtonDemo.vue +28 -28
  122. package/src/base-client/components/common/XButtons/index.js +3 -3
  123. package/src/base-client/components/common/XButtons/index.md +61 -61
  124. package/src/base-client/components/common/XCalendar/XCalendar.vue +4 -4
  125. package/src/base-client/components/common/XCard/XCard.vue +64 -64
  126. package/src/base-client/components/common/XCheckList/XCheckList.vue +106 -106
  127. package/src/base-client/components/common/XCheckList/XCheckListDemo.vue +41 -41
  128. package/src/base-client/components/common/XCollapse/XCollapse.vue +830 -830
  129. package/src/base-client/components/common/XDataCard/index.js +3 -3
  130. package/src/base-client/components/common/XDataCard/index.md +1 -1
  131. package/src/base-client/components/common/XDataDrawer/XDataDrawer.vue +180 -180
  132. package/src/base-client/components/common/XDataDrawer/index.js +3 -3
  133. package/src/base-client/components/common/XDataDrawer/index.md +41 -41
  134. package/src/base-client/components/common/XDatePicker/demo.vue +153 -153
  135. package/src/base-client/components/common/XDescriptions/index.js +3 -3
  136. package/src/base-client/components/common/XDescriptions/index.md +83 -83
  137. package/src/base-client/components/common/XDetailsView/XDetailsView.vue +238 -238
  138. package/src/base-client/components/common/XDetailsView/index.js +3 -3
  139. package/src/base-client/components/common/XForm/XFormItem.vue +12 -4
  140. package/src/base-client/components/common/XForm/XStatusButton.vue +54 -54
  141. package/src/base-client/components/common/XForm/index.md +178 -178
  142. package/src/base-client/components/common/XForm/itemComponent/XClickChangeBtn/index.vue +49 -49
  143. package/src/base-client/components/common/XFormGroup/index.js +3 -3
  144. package/src/base-client/components/common/XFormGroup/index.md +38 -38
  145. package/src/base-client/components/common/XFormGroupDetails/index.js +3 -3
  146. package/src/base-client/components/common/XFormTable/XFormTable.vue +1093 -1092
  147. package/src/base-client/components/common/XFormTable/demo.vue +113 -89
  148. package/src/base-client/components/common/XFormTable/index.md +92 -92
  149. package/src/base-client/components/common/XLabelSelect/XLabelSelect.vue +110 -110
  150. package/src/base-client/components/common/XLabelSelect/XLabelSelectDemo.vue +35 -35
  151. package/src/base-client/components/common/XLicensePlate/XLicensePlate.vue +193 -193
  152. package/src/base-client/components/common/XLicensePlate/XLicensePlateDemo.vue +48 -48
  153. package/src/base-client/components/common/XPrint/OpenInvoice.vue +21 -21
  154. package/src/base-client/components/common/XPrint/PrintHtml.js +98 -98
  155. package/src/base-client/components/common/XPrint/css/hiPrintCss.js +359 -359
  156. package/src/base-client/components/common/XPrint/css/lodopCss.js +26 -26
  157. package/src/base-client/components/common/XPrint/css/print-lock.css +351 -351
  158. package/src/base-client/components/common/XPrint/index.vue +97 -97
  159. package/src/base-client/components/common/XReport/XReportDesign.vue +463 -463
  160. package/src/base-client/components/common/XReport/XReportJsonRender.vue +381 -381
  161. package/src/base-client/components/common/XReport/index.js +3 -3
  162. package/src/base-client/components/common/XReport/print.js +186 -186
  163. package/src/base-client/components/common/XReportDrawer/index.js +3 -3
  164. package/src/base-client/components/common/XReportGrid/index.js +3 -3
  165. package/src/base-client/components/common/XReportGrid/index.md +44 -44
  166. package/src/base-client/components/common/XReportSlot/XReportSlot.vue +110 -110
  167. package/src/base-client/components/common/XReportSlot/index.js +3 -3
  168. package/src/base-client/components/common/XReportSlot/index.md +48 -48
  169. package/src/base-client/components/common/XSimpleDescriptions/XSimpleDescriptions.vue +166 -166
  170. package/src/base-client/components/common/XSimpleDescriptions/index.js +3 -3
  171. package/src/base-client/components/common/XSimpleDescriptions/index.md +7 -7
  172. package/src/base-client/components/common/XStepView/XStepView.vue +252 -252
  173. package/src/base-client/components/common/XStepView/index.js +3 -3
  174. package/src/base-client/components/common/XStepView/index.md +31 -31
  175. package/src/base-client/components/common/XTab/XTabDemo.vue +22 -22
  176. package/src/base-client/components/common/XTab/index.js +3 -3
  177. package/src/base-client/components/common/XTable/CustomFuncCel.vue +51 -51
  178. package/src/base-client/components/common/XTable/TableCellRenderer.vue +161 -161
  179. package/src/base-client/components/common/XTable/XTable.vue +46 -0
  180. package/src/base-client/components/common/XTable/XTableWrapper.vue +706 -669
  181. package/src/base-client/components/common/XTable/index.md +255 -255
  182. package/src/base-client/components/common/XTagGroup/index.vue +52 -52
  183. package/src/base-client/components/common/XTimeline/XTimeline.vue +477 -477
  184. package/src/base-client/components/common/XTree/XTree.vue +424 -424
  185. package/src/base-client/components/common/XTree/index.js +3 -3
  186. package/src/base-client/components/common/XTree/index.md +36 -36
  187. package/src/base-client/components/common/XTreeOne/XTreeOne.vue +113 -113
  188. package/src/base-client/components/common/XTreeOne/XTreeOnePro.vue +128 -128
  189. package/src/base-client/components/common/richTextModal/index.vue +56 -56
  190. package/src/base-client/components/common/richTextModal/richDemo.vue +48 -48
  191. package/src/base-client/components/his/XCharge/XChargeDemo.vue +145 -145
  192. package/src/base-client/components/his/XHisEditor/XHisEditor.vue +705 -705
  193. package/src/base-client/components/his/XHisEditor/index.js +3 -3
  194. package/src/base-client/components/his/XList/XList.vue +938 -938
  195. package/src/base-client/components/his/XTimeSelect/XTimeSelect.vue +354 -354
  196. package/src/base-client/components/his/XTitle/XTitle.vue +314 -314
  197. package/src/base-client/components/his/XTreeRows/XTreeRows.vue +341 -341
  198. package/src/base-client/components/his/threeTestOrders/editor.vue +113 -113
  199. package/src/base-client/components/index.js +51 -51
  200. package/src/base-client/components/layout/XTreeView/XTreeView.vue +130 -130
  201. package/src/base-client/components/layout/XTreeView/index.js +3 -3
  202. package/src/base-client/components/layout/XTreeView/index.md +46 -46
  203. package/src/base-client/components/system/DictionaryDetailsView/DictionaryDetailsView.vue +232 -232
  204. package/src/base-client/components/system/QueryParamsDetailsView/QueryParamsDetailsView.vue +281 -281
  205. package/src/base-client/plugins/Config.js +19 -19
  206. package/src/base-client/plugins/GetLoginInfoService.js +183 -183
  207. package/src/base-client/plugins/Recording.js +258 -258
  208. package/src/base-client/plugins/index.js +23 -23
  209. package/src/base-client/plugins/tabs-page-plugin.js +39 -39
  210. package/src/components/Charts/Bar.vue +62 -62
  211. package/src/components/Charts/ChartCard.vue +134 -134
  212. package/src/components/Charts/Liquid.vue +67 -67
  213. package/src/components/Charts/MiniArea.vue +39 -39
  214. package/src/components/Charts/MiniBar.vue +39 -39
  215. package/src/components/Charts/MiniProgress.vue +75 -75
  216. package/src/components/Charts/MiniSmoothArea.vue +40 -40
  217. package/src/components/Charts/Radar.vue +68 -68
  218. package/src/components/Charts/RankList.vue +77 -77
  219. package/src/components/Charts/TagCloud.vue +113 -113
  220. package/src/components/Charts/TransferBar.vue +64 -64
  221. package/src/components/Charts/Trend.vue +82 -82
  222. package/src/components/Charts/chart.less +12 -12
  223. package/src/components/Charts/smooth.area.less +13 -13
  224. package/src/components/CodeMirror/inedx.vue +118 -118
  225. package/src/components/CodeMirror/setting.js +40 -40
  226. package/src/components/NumberInfo/NumberInfo.vue +54 -54
  227. package/src/components/NumberInfo/index.js +3 -3
  228. package/src/components/NumberInfo/index.less +54 -54
  229. package/src/components/NumberInfo/index.md +43 -43
  230. package/src/components/STable/index.js +771 -771
  231. package/src/components/card/ChartCard.vue +79 -79
  232. package/src/components/chart/Bar.vue +60 -60
  233. package/src/components/chart/MiniArea.vue +67 -67
  234. package/src/components/chart/MiniBar.vue +59 -59
  235. package/src/components/chart/MiniProgress.vue +57 -57
  236. package/src/components/chart/Radar.vue +80 -80
  237. package/src/components/chart/RankingList.vue +60 -60
  238. package/src/components/chart/Trend.vue +79 -79
  239. package/src/components/chart/index.less +9 -9
  240. package/src/components/checkbox/ColorCheckbox.vue +157 -157
  241. package/src/components/checkbox/ImgCheckbox.vue +117 -117
  242. package/src/components/checkbox/ImgCheckboxGroup.vue +76 -76
  243. package/src/components/checkbox/index.js +9 -9
  244. package/src/components/exception/ExceptionPage.vue +70 -70
  245. package/src/components/g2Charts/constants.js +202 -202
  246. package/src/components/g2Charts/demo.vue +808 -808
  247. package/src/components/g2Charts/designer.vue +228 -228
  248. package/src/components/g2Charts/designerBaseConfig.vue +61 -61
  249. package/src/components/g2Charts/designerDataConfig.vue +259 -259
  250. package/src/components/g2Charts/designerStyleConfig.vue +16 -16
  251. package/src/components/g2Charts/index.vue +397 -397
  252. package/src/components/index.js +36 -36
  253. package/src/components/input/IInput.vue +66 -66
  254. package/src/components/menu/SideMenu.vue +75 -75
  255. package/src/components/menu/menu.js +273 -273
  256. package/src/components/setting/Setting.vue +234 -234
  257. package/src/components/tool/AStepItem.vue +60 -60
  258. package/src/config/CreateQueryConfig.js +325 -325
  259. package/src/config/default/antd.config.js +89 -89
  260. package/src/config/default/setting.config.js +55 -55
  261. package/src/font-style/font.css +60 -60
  262. package/src/layouts/CommonLayout.vue +56 -56
  263. package/src/layouts/PageLayout.vue +151 -151
  264. package/src/layouts/SinglePageView.vue +136 -136
  265. package/src/layouts/header/AdminHeader.vue +132 -132
  266. package/src/layouts/header/HeaderNotice.vue +177 -177
  267. package/src/layouts/header/InstitutionDetail.vue +181 -181
  268. package/src/layouts/tabs/TabsHead.vue +189 -189
  269. package/src/lib.js +1 -1
  270. package/src/mock/extend/index.js +84 -84
  271. package/src/mock/goods/index.js +108 -108
  272. package/src/pages/DefaultExample/index.vue +77 -77
  273. package/src/pages/DynamicStatistics/ChartSelector.vue +331 -331
  274. package/src/pages/DynamicStatistics/DataTabs.vue +83 -83
  275. package/src/pages/DynamicStatistics/DynamicTable.vue +128 -128
  276. package/src/pages/DynamicStatistics/EvaluationArea.vue +69 -69
  277. package/src/pages/DynamicStatistics/FavoriteList.vue +50 -50
  278. package/src/pages/DynamicStatistics/QuestionHistoryAndFavorites.vue +591 -591
  279. package/src/pages/DynamicStatistics/SearchBar.vue +192 -192
  280. package/src/pages/DynamicStatistics/index.vue +282 -282
  281. package/src/pages/Example/childIndex.vue +15 -15
  282. package/src/pages/Example/index.vue +30 -30
  283. package/src/pages/NewDynamicStatistics/ChartSelector.vue +331 -331
  284. package/src/pages/NewDynamicStatistics/DataTabs.vue +122 -122
  285. package/src/pages/NewDynamicStatistics/DynamicTable.vue +128 -128
  286. package/src/pages/NewDynamicStatistics/EvaluationArea.vue +69 -69
  287. package/src/pages/NewDynamicStatistics/FavoriteList.vue +50 -50
  288. package/src/pages/NewDynamicStatistics/QuestionHistoryAndFavorites.vue +289 -289
  289. package/src/pages/NewDynamicStatistics/SearchBar.vue +193 -193
  290. package/src/pages/NewDynamicStatistics/index.vue +258 -258
  291. package/src/pages/Recording/index.vue +77 -77
  292. package/src/pages/ServiceReview/index.vue +284 -284
  293. package/src/pages/SubExample/index.vue +26 -26
  294. package/src/pages/WorkflowDetail/WorkflowPageDetail/TrimTextTail.vue +23 -23
  295. package/src/pages/WorkflowDetail/WorkflowPageDetail/WorkFlowHandle.vue +1815 -1815
  296. package/src/pages/WorkflowDetail/WorkflowPageDetail/WorkFlowTimeline.vue +1014 -1014
  297. package/src/pages/XReportView/index.vue +64 -64
  298. package/src/pages/XTreeOneProExample/index.vue +67 -67
  299. package/src/pages/dashboard/workplace/WorkPlace.vue +141 -141
  300. package/src/pages/login/Login.vue +379 -379
  301. package/src/pages/login/LoginV3.vue +389 -389
  302. package/src/pages/lowCode/lowCodeEditor.vue +1219 -1219
  303. package/src/pages/lowCode/lowCodeRenderPage.vue +43 -43
  304. package/src/pages/report/ReportTable.js +124 -124
  305. package/src/pages/resourceManage/orgListManage.vue +98 -98
  306. package/src/pages/system/dictionary/index.vue +44 -44
  307. package/src/pages/system/monitor/loginInfor/index.vue +37 -37
  308. package/src/pages/system/monitor/operLog/index.vue +37 -37
  309. package/src/pages/system/settings/modifyPassword.vue +117 -117
  310. package/src/pages/system/ticket/index.vue +480 -480
  311. package/src/pages/system/ticket/submitTicketSuccess.vue +484 -484
  312. package/src/pages/userInfoDetailManage/ChangeMeterRecordQuery/index.vue +64 -64
  313. package/src/pages/userInfoDetailManage/ExceptionRecordQuery/index.vue +45 -45
  314. package/src/pages/userInfoDetailManage/InfoChangeRecordQuery/index.vue +64 -64
  315. package/src/pages/userInfoDetailManage/InstructRecordQuery/index.vue +64 -64
  316. package/src/pages/userInfoDetailManage/MeterParamRecordQuery/index.vue +64 -64
  317. package/src/pages/userInfoDetailManage/TransferRecordQuery/index.vue +66 -66
  318. package/src/pages/userInfoDetailManage/WatchCollectionRecordQuery/index.vue +64 -64
  319. package/src/plugins/EventLogPlugin.js +33 -33
  320. package/src/plugins/FindParentsData.js +17 -17
  321. package/src/router/async/router.map.js +133 -133
  322. package/src/services/DataModel.js +30 -30
  323. package/src/services/LodopFuncs.js +137 -137
  324. package/src/services/api/TicketDetailsViewApi.js +46 -46
  325. package/src/services/api/cas.js +79 -79
  326. package/src/services/api/entity.js +18 -18
  327. package/src/services/api/index.js +17 -17
  328. package/src/store/modules/account.js +121 -121
  329. package/src/store/modules/index.js +5 -5
  330. package/src/store/modules/lowCode.js +33 -33
  331. package/src/store/modules/setting.js +119 -119
  332. package/src/theme/default/style.less +58 -58
  333. package/src/theme/global.less +311 -311
  334. package/src/utils/authority-utils.js +85 -85
  335. package/src/utils/errorCode.js +6 -6
  336. package/src/utils/formatter.js +74 -74
  337. package/src/utils/htmlToPDF.js +108 -108
  338. package/src/utils/htmlToPDFApi.js +5 -5
  339. package/src/utils/login.js +188 -188
  340. package/src/utils/lowcode/lowcodeComponentMixin.js +120 -120
  341. package/src/utils/lowcode/lowcodeLog.js +29 -29
  342. package/src/utils/lowcode/lowcodeUtils.js +373 -373
  343. package/src/utils/lowcode/registerComponentForEditor.js +1 -1
  344. package/src/utils/lowcode/registerComponentForRender.js +11 -11
  345. package/src/utils/map-utils.js +47 -47
  346. package/src/utils/reg.js +95 -95
  347. package/src/utils/runEvalFunction.js +14 -14
  348. package/src/utils/theme-color-replacer-extend.js +92 -92
  349. package/src/utils/util.js +329 -329
  350. package/src/utils/waterMark.js +31 -31
  351. package//350/277/201/347/247/273/346/227/245/345/277/227.md +15 -15
  352. package/src-base-client/components/common/HIS/HForm/HForm.vue +0 -347
  353. package/src-base-client/components/common/XCollapse/XCollapse.vue +0 -0
@@ -1,938 +1,938 @@
1
- <template>
2
- <!-- 列表卡片模式 listMode: card -->
3
- <div
4
- class="x-list-wrapper"
5
- :class="wrapperClassObject"
6
- v-if="listMode"
7
- ref="listRef"
8
- @scroll="handleInfiniteOnLoad">
9
- <a-list
10
- :grid="{ gutter: 16, xs: 1, sm: 2, md: 2, lg: 3, xl: 3, xxl: 4 }"
11
- :data-source="localData">
12
- <a-list-item slot="renderItem" slot-scope="item, index">
13
- <div class="card-a-col" :class="{ 'selected-active': enableSelectRow && currentSelectedIndex === index }" :style="getCardStyle(currentTitleValue(index))" @click="handleCardClick(index)">
14
- <a-row class="card-row">
15
- <a-col class="id-a-col" :span="4" v-for="(detail,idx) in item.filter(d => d.label == label)" :key="idx">
16
- {{ detail.value }}
17
- <div class="gender-icon" v-if="getHasPatient(item) && getGender(item)">
18
- <img :src="getGender(item) === '男' ? maleIcon : femaleIcon" :alt="getGender(item)" class="gender-img" />
19
- </div>
20
- </a-col>
21
- <a-col :span="20" class="id-a-col-2">
22
- <template v-for="(detail,idx) in item">
23
- <div :key="`title_${idx}`" class="title-row" v-if="detail.type == 'title'">
24
- <a-tooltip :title="detail.value" placement="topLeft">
25
- <span class="describe-list-a-col" :class="{name: detail.bold}">{{ detail.value }}</span>
26
- </a-tooltip>
27
- <div class="title-actions" v-if="getTitleOptions && getTitleOptions.length">
28
- <span class="title-select-label">{{ getDisplayTitleLabel(index) }}</span>
29
- <a-dropdown placement="bottomRight" trigger="['click']">
30
- <a class="arrow-btn" @click.prevent>
31
- <a-icon type="down" />
32
- </a>
33
- <a-menu slot="overlay" :selectedKeys="[String(currentTitleValue(index))]" @click="info => handleTitleMenuClick(info, index)">
34
- <a-menu-item v-for="opt in getTitleOptions" :key="String(opt && opt.value !== undefined ? opt.value : opt)">
35
- {{ opt && opt.label !== undefined ? opt.label : opt }}
36
- </a-menu-item>
37
- </a-menu>
38
- </a-dropdown>
39
- </div>
40
- </div>
41
- <span :key="idx" class="component-a-col" v-else-if="getHasPatient(item) && detail.type == 'component' && detail.label != label">
42
- <a-tooltip :title="detail.label" placement="topLeft">
43
- <span class="label-text">{{ `${detail.label}:` }}</span>
44
- </a-tooltip>
45
- <component
46
- :is="detail.slotType"
47
- :key="idx"
48
- :ref="`dynamicComponent_${ idx.slotType || idx}_${idx}`"
49
- :serviceName="serviceName"
50
- v-on="forwardAllEvents"
51
- :queryParamsName="detail.value"
52
- :countVisible="false"
53
- />
54
- </span>
55
- <span :key="idx" class="component-a-col" v-else-if="getHasPatient(item) && detail.type == 'date'">
56
- <a-tooltip :title="detail.label" placement="topLeft">
57
- <span class="label-text">{{ `${detail.label}:` }}</span>
58
- </a-tooltip>
59
- <a-date-picker @change="onChange" />
60
- </span>
61
- <a-tooltip :key="idx" :title="`${detail.label}:${detail.value}`" placement="topLeft" v-else-if="getHasPatient(item) && detail.label != label">
62
- <span class="describe-list-a-col" :class="{name: detail.bold}">{{ `${detail.label}:${detail.value}` }}</span>
63
- </a-tooltip>
64
- </template>
65
- <a-button
66
- v-if="getHasPatient(item) && showCardButtons"
67
- v-for="(btn, i) in buttonNames"
68
- :key="i"
69
- icon="search"
70
- class="button-a-col"
71
- @click.stop="click(item, index)">
72
- {{ btn }}
73
- </a-button>
74
- </a-col>
75
- </a-row>
76
- </div>
77
- </a-list-item>
78
- <div v-if="loading" class="demo-loading-container">
79
- <a-spin />
80
- </div>
81
- <div v-if="allLoaded">
82
- <div class="demo-infinite-list-bottom">
83
- 已经显示全部数据
84
- </div>
85
- </div>
86
- </a-list>
87
- </div>
88
-
89
- <!-- 默认标签模式 -->
90
- <div class="list-wrapper x-list-wrapper" :class="wrapperClassObject" v-else>
91
- <a-list size="large" :data-source="data" itemLayout="horizontal" class="list-container" ref="listRef">
92
- <a-list-item
93
- slot="renderItem"
94
- slot-scope="item, index"
95
- class="list-item"
96
- @click="handleClick(index)"
97
- @mouseenter="enableHoverOptions && handleMouseEnter(index)"
98
- @mouseleave="handleMouseLeave"
99
- :class="{ 'hover-active': enableHoverOptions && hoveredIndex === index, 'selected-active': enableSelectRow && currentSelectedIndex === index }">
100
- <i
101
- v-if="icon"
102
- class="icon-menu"
103
- :style="getIconStyle(item)">
104
- </i>
105
- <span
106
- class="item-text"
107
- :class="{ 'text-truncated': enableHoverOptions && hoveredIndex === index }"
108
- :style="getTextStyle(index)">
109
- {{ item.number }} {{ item.name }}
110
- </span>
111
-
112
- <div v-if="button" class="button-group">
113
- <a-button
114
- v-for="(name, idx) in buttonNames"
115
- :key="idx"
116
- type="link"
117
- :class="['confirm-btn', buttonMode ? 'hover-btn' : '']"
118
- @click.stop="click(index, idx)">
119
- <span :class="{ 'hover-active': enableHoverOptions && hoveredIndex === index }">{{ name }}</span>
120
- </a-button>
121
- </div>
122
-
123
- <!-- 悬浮选项框 -->
124
- <div
125
- v-show="enableHoverOptions && hoveredIndex === index"
126
- class="hover-options"
127
- @mouseenter="handleOptionsEnter"
128
- @mouseleave="handleOptionsLeave">
129
- <div class="hover-options-content">
130
- <div
131
- v-for="(Item, idx) in select_options"
132
- :key="idx"
133
- class="option-item"
134
- @click="handleOptionClick(index, Item)">
135
- {{ Item }}
136
- </div>
137
- </div>
138
- </div>
139
- </a-list-item>
140
- </a-list>
141
- </div>
142
- </template>
143
-
144
- <script>
145
-
146
- import { getConfigByName, runLogic } from '@vue2-client/services/api/common'
147
-
148
- export default {
149
- name: 'XList',
150
- components: {
151
- XReport: () => import('@vue2-client/base-client/components/common/XReport/XReport.vue'),
152
- XButtons: () => import('@vue2-client/base-client/components/common/XButtons/XButtons.vue'),
153
- XInput: () => import('@vue2-client/base-client/components/common/XInput/XInput.vue'),
154
- XRadio: () => import('@vue2-client/base-client/components/his/XRadio/XRadio.vue'),
155
- XTimeSelect: () => import('@vue2-client/base-client/components/his/XTimeSelect/XTimeSelect.vue'),
156
- XCheckbox: () => import('@vue2-client/base-client/components/his/XCheckbox/XCheckbox.vue'),
157
- XTitle: () => import('@vue2-client/base-client/components/his/XTitle/XTitle.vue'),
158
- XSelect: () => import('@vue2-client/base-client/components/his/XSelect/XSelect.vue')
159
- },
160
- props: {
161
- queryParamsName: {
162
- type: Object,
163
- default: null
164
- },
165
- fixedQueryForm: {
166
- type: Object,
167
- default: { condition: '1=1' }
168
- },
169
- enableHoverOptions: {
170
- type: Boolean,
171
- default: true
172
- },
173
- serviceName: {
174
- type: String,
175
- default: 'af-his'
176
- },
177
- // 点击是否触发选中(默认不通过点击选中,仅手动控制)
178
- selectOnClick: {
179
- type: Boolean,
180
- default: false
181
- },
182
- // 受控选中索引;不传则内部维护
183
- selectedIndex: {
184
- type: Number,
185
- default: undefined
186
- },
187
- // 卡片按钮显示控制(默认隐藏,可通过属性或配置开启)
188
- showCardButtons: {
189
- type: Boolean,
190
- default: false
191
- },
192
- // 标题右侧下拉选项与受控值
193
- titleSelectOptions: {
194
- type: Array,
195
- default: () => []
196
- },
197
- titleSelectValue: {
198
- type: [String, Number],
199
- default: undefined
200
- },
201
- },
202
- data () {
203
- return {
204
- data: [], // 数据源
205
- localData: [], // 本地数据源
206
- loading: false, // 加载中
207
- busy: false, // 繁忙状态
208
- button: false,
209
- icon: false,
210
- buttonNames: [],
211
- listMode: undefined, // 列表模式
212
- buttonMode: true,
213
- hoveredIndex: -1, // 当前悬浮的索引
214
- isOptionsHovered: false, // 悬浮选项框是否悬浮
215
- hoverTimer: null, // 悬浮选项框定时器
216
- leaveTimer: null, // 离开选项框定时器
217
- select_options: [], // 悬浮选项框
218
- logicName: '',
219
- nowPage: 0, // 当前页
220
- pageSize: 12,
221
- allLoaded: false,
222
- label: 'id',
223
- scrollTimer: null,
224
- // 内部选中索引(非受控时使用)
225
- localSelectedIndex: -1,
226
- maleIcon: require('@vue2-client/assets/svg/male.svg'),
227
- femaleIcon: require('@vue2-client/assets/svg/female.svg'),
228
- // 下拉配置
229
- internalTitleOptions: [],
230
- titleValueByIndex: {},
231
- // 选择请求的轻量防抖
232
- selectDebounceTimer: null
233
- }
234
- },
235
- inject: ['getComponentByName'],
236
-
237
- created () {
238
- this.getData(this.queryParamsName, this.fixedQueryForm)
239
- },
240
- mounted () {},
241
- computed: {
242
- // 参考 HForm 的 wrapperClassObject 规则,支持通过组件属性动态控制样式
243
- wrapperClassObject () {
244
- const a = this.$attrs || {}
245
- const classes = {}
246
- // 多个布尔型样式开关(存在且为真则生效)
247
- const booleanStyleKeys = [
248
- 'enableNewListStyle'
249
- ]
250
- booleanStyleKeys.forEach(key => {
251
- const val = a[key]
252
- const truthy = val === true || val === '' || val === 'true'
253
- if (truthy) classes[`x-list-${key}`] = true
254
- })
255
- return classes
256
- },
257
- // 标题下拉:优先使用外部 props,否则使用内部配置
258
- getTitleOptions () {
259
- if (Array.isArray(this.titleSelectOptions) && this.titleSelectOptions.length) return this.titleSelectOptions
260
- return this.internalTitleOptions
261
- },
262
- currentTitleValue () {
263
- return (index) => {
264
- if (this.titleSelectValue !== undefined) return this.titleSelectValue
265
- const local = this.titleValueByIndex[index]
266
- if (local !== undefined) return local
267
- // 二次回退:若模板标题提供了 titleRightValue,则用于首屏渲染颜色与文案
268
- const row = Array.isArray(this.localData) ? this.localData[index] : null
269
- if (Array.isArray(row)) {
270
- const title = row.find(d => d && d.type === 'title')
271
- if (title && title.titleRightValue !== undefined) return title.titleRightValue
272
- }
273
- // 最终回退:使用 options 的第一个
274
- const def = this.internalTitleOptions && this.internalTitleOptions.length ? (this.internalTitleOptions[0].value !== undefined ? this.internalTitleOptions[0].value : this.internalTitleOptions[0]) : undefined
275
- return def
276
- }
277
- },
278
- // 选择控制:受控优先
279
- currentSelectedIndex () {
280
- return typeof this.selectedIndex === 'number' ? this.selectedIndex : this.localSelectedIndex
281
- },
282
- enableSelectRow () {
283
- const a = this.$attrs || {}
284
- const val = a.enableSelection
285
- return val === true || val === '' || val === 'true'
286
- },
287
- forwardAllEvents () {
288
- return {
289
- // 监听所有事件并转发给父组件
290
- '*': (eventName, ...payload) => {
291
- this.$emit(eventName, ...payload)
292
- }
293
- }
294
- }
295
- },
296
- methods: {
297
- onChange (date, dateString) {
298
- this.$emit('dateChange', date, dateString)
299
- },
300
- handleInfiniteOnLoad (event) {
301
- if (this.busy || this.allLoaded) return // 防止重复加载
302
- if (this.scrollTimer) clearTimeout(this.scrollTimer)
303
- this.scrollTimer = setTimeout(() => {
304
- const container = event.target
305
- const scrollTop = container.scrollTop
306
- const scrollHeight = container.scrollHeight
307
- const clientHeight = container.clientHeight
308
- const bottomOffset = 10
309
- if (scrollTop + clientHeight >= scrollHeight - bottomOffset) {
310
- this.busy = true
311
- this.loading = true
312
- this.nowPage = this.nowPage + this.pageSize
313
- this.fixedQueryForm.condition = `Limit ${this.nowPage}, ${this.pageSize}`
314
- runLogic(this.logicName, this.fixedQueryForm, 'af-his').then(async (res) => {
315
- this.localData = [...this.localData, ...res]
316
- if (res.length < this.pageSize) {
317
- this.allLoaded = true
318
- }
319
- }).catch(e => {
320
- this.$message.error(e.message)
321
- }).finally(() => {
322
- this.loading = false
323
- this.busy = false
324
- })
325
- }
326
- }, 100)
327
- },
328
- async getData (config, param) {
329
- const that = this
330
- getConfigByName(config, 'af-his', async (res) => {
331
- that.listMode = await res.listMode == 'card'
332
- that.logicName = await res.data
333
- that.button = await res.button // 按钮
334
- that.icon = await res.icon // 图标
335
- that.label = await res.label // 标签
336
- that.buttonNames = await res.buttonNames || []// 按钮文本
337
- that.buttonMode = await res.buttonMode || false// 按钮模式
338
- that.cardButtonsVisible = await res.cardButtonsVisible || false// 卡片按钮
339
- // 标题下拉:从配置拿 options: [{label,value,color}]
340
- if (Array.isArray(res.titleOptions)) {
341
- this.internalTitleOptions = res.titleOptions
342
- if (res.titleDefaultValue !== undefined && Array.isArray(this.localData)) {
343
- // 初始化每个卡片的默认值
344
- this.titleValueByIndex = {}
345
- }
346
- }
347
- this.enableHoverOptions = await res.enableHoverOptions || false// 悬浮选项框
348
- if (this.enableHoverOptions) {
349
- this.select_options = await res.select_options
350
- }
351
- if (that.listMode) { param.condition = `Limit ${that.nowPage}, ${that.pageSize}` }
352
- runLogic(res.data, param, 'af-his').then(result => {
353
- that.data = result
354
- if (that.nowPage === 0) { this.localData = result }
355
- // 初始化每张卡片的 title 选中值:优先读取模板 titleRightValue,否则使用配置默认或第一项
356
- if (Array.isArray(this.localData)) {
357
- this.localData.forEach((row, idx) => {
358
- if (this.titleValueByIndex[idx] !== undefined) return
359
- if (Array.isArray(row)) {
360
- const title = row.find(d => d && d.type === 'title')
361
- if (title && title.titleRightValue !== undefined) {
362
- this.$set(this.titleValueByIndex, idx, title.titleRightValue)
363
- return
364
- }
365
- }
366
- // fallback:配置默认或第一项
367
- const def = (this.internalTitleOptions && this.internalTitleOptions.length)
368
- ? (this.internalTitleOptions[0].value !== undefined ? this.internalTitleOptions[0].value : this.internalTitleOptions[0])
369
- : undefined
370
- if (def !== undefined) this.$set(this.titleValueByIndex, idx, def)
371
- })
372
- }
373
- })
374
- })
375
- },
376
- // 提取性别:从数组数据中查找 label 含“性别”的项
377
- getGender (item) {
378
- if (!Array.isArray(item)) return null
379
- const g = item.find(d => d && typeof d.label === 'string' && d.label.indexOf('性别') > -1)
380
- const val = g && (g.value || g.text)
381
- if (!val) return null
382
- if (String(val).includes('男')) return '男'
383
- if (String(val).includes('女')) return '女'
384
- return null
385
- },
386
- // 读取标题项上的 hasPatient 布尔值
387
- getHasPatient (item) {
388
- if (!Array.isArray(item)) return true
389
- const title = item.find(d => d && d.type === 'title')
390
- if (!title || typeof title.hasPatient === 'undefined') return true
391
- return !!title.hasPatient
392
- },
393
- // 标题右侧下拉选择
394
- handleTitleSelectChange (val, index) {
395
- // 重复值拦截:若值未变化则直接返回
396
- const prev = this.normalizeValue(this.currentTitleValue(index))
397
- const next = this.normalizeValue(val)
398
- if (prev === next) return
399
-
400
- this.$set(this.titleValueByIndex, index, val)
401
- this.$emit('update:titleSelectValue', val)
402
- this.$emit('titleSelectChange', { index, value: val })
403
- // 变更后仅通知后端更新,不处理返回值;支持从标题项读取 extraParams 合并(如住院号)
404
- const extra = this.getTitleExtraParams(index)
405
- if (this.selectDebounceTimer) clearTimeout(this.selectDebounceTimer)
406
- this.selectDebounceTimer = setTimeout(() => {
407
- runLogic(this.logicName, Object.assign({ type: 'select', value: val }, extra), 'af-his').catch(() => {})
408
- }, 200)
409
- },
410
- // 读取标题项中额外需要传递的参数(可选),例如 { inpatientNo: row.t_id }
411
- getTitleExtraParams (index) {
412
- const row = Array.isArray(this.localData) ? this.localData[index] : null
413
- if (!Array.isArray(row)) return {}
414
- const title = row.find(d => d && d.type === 'title') || {}
415
- if (title && title.extraParams && typeof title.extraParams === 'object') return title.extraParams
416
- return {}
417
- },
418
- handleTitleMenuClick ({ key }, index) {
419
- const v = isNaN(Number(key)) ? key : Number(key)
420
- this.handleTitleSelectChange(v, index)
421
- },
422
- // 根据当前选择项的 color 设置卡片背景色
423
- normalizeValue (v) { return String(v) },
424
- getCardStyle (val) {
425
- const target = this.normalizeValue(val)
426
- const opt = (this.getTitleOptions || []).find(o => this.normalizeValue(o && (o.value !== undefined ? o.value : o)) === target)
427
- const color = opt && (opt.color || (opt.style && opt.style.background))
428
- return color ? { backgroundColor: color } : {}
429
- },
430
- getTitleLabel (val) {
431
- const target = this.normalizeValue(val)
432
- const opt = (this.getTitleOptions || []).find(o => this.normalizeValue(o && (o.value !== undefined ? o.value : o)) === target)
433
- return opt && (opt.label !== undefined ? opt.label : opt)
434
- },
435
- getDisplayTitleLabel (index) {
436
- // 优先展示“当前选中值”的 label,未选中再回退到模板提供的 titleRightLabel
437
- const current = this.getTitleLabel(this.currentTitleValue(index))
438
- if (current) return current
439
- const title = Array.isArray(this.localData && this.localData[index])
440
- ? this.localData[index].find(d => d && d.type === 'title')
441
- : null
442
- return title && title.titleRightLabel ? title.titleRightLabel : ''
443
- },
444
- // 点击列表项
445
- handleClick (index) {
446
- if (this.enableSelectRow && this.selectOnClick) this.setSelectedIndex(index)
447
- this.$emit('listClick', this.data[index])
448
- },
449
- // 卡片模式点击卡片
450
- handleCardClick (index) {
451
- if (this.enableSelectRow && this.selectOnClick) this.setSelectedIndex(index)
452
- this.$emit('listClick', this.localData[index])
453
- },
454
- // 外部可调用:设置选中索引
455
- setSelectedIndex (index) {
456
- const next = typeof index === 'number' ? index : -1
457
- if (typeof this.selectedIndex === 'number') {
458
- // 受控:仅派发事件
459
- this.$emit('update:selectedIndex', next)
460
- } else {
461
- // 非受控:更新内部并派发事件
462
- this.localSelectedIndex = next
463
- this.$emit('update:selectedIndex', next)
464
- }
465
- },
466
- // 外部可调用:清空选中
467
- clearSelected () { this.setSelectedIndex(-1) },
468
- refreshList (param) {
469
- this.getData(this.queryParamsName, param)
470
- },
471
- click (index, buttonIndex) {
472
- this.$emit('click', { data: this.data[index], name: this.buttonNames[buttonIndex] })
473
- },
474
- // 根据对象字段匹配选中(默认按 id 字段)
475
- setSelectedById (id, field = 'id') {
476
- const list = this.listMode ? this.localData : this.data
477
- if (!Array.isArray(list)) return
478
- const index = list.findIndex(item => {
479
- if (Array.isArray(item)) {
480
- const f = item.find(d => d && d.label === field)
481
- return f && f.value === id
482
- }
483
- return item && item[field] === id
484
- })
485
- if (index >= 0) this.setSelectedIndex(index)
486
- },
487
- // 根据 label/value(卡片数组数据场景)匹配选中
488
- setSelectedByLabelValue (label, value) {
489
- const list = this.listMode ? this.localData : this.data
490
- if (!Array.isArray(list)) return
491
- const index = list.findIndex(item => Array.isArray(item) && item.some(d => d && d.label === label && d.value === value))
492
- if (index >= 0) this.setSelectedIndex(index)
493
- },
494
- // 通用:传入谓词函数决定选中项
495
- setSelectedBy (predicate) {
496
- if (typeof predicate !== 'function') return
497
- const list = this.listMode ? this.localData : this.data
498
- if (!Array.isArray(list)) return
499
- const index = list.findIndex(predicate)
500
- if (index >= 0) this.setSelectedIndex(index)
501
- },
502
- getIconStyle (item) {
503
- return item.picture
504
- ? { backgroundImage: `url(${item.picture})` }
505
- : {}
506
- },
507
- filterData (par) {
508
- runLogic(this.queryParamsName, par, 'af-his').then(res => {
509
- this.data = res.data
510
- })
511
- },
512
- // 鼠标进入列表项
513
- handleMouseEnter (index) {
514
- this.clearAllTimers()
515
- this.hoveredIndex = index
516
- this.isOptionsHovered = true
517
- },
518
- // 鼠标离开列表项
519
- handleMouseLeave () {
520
- this.clearAllTimers()
521
- this.leaveTimer = setTimeout(() => {
522
- this.isOptionsHovered = false
523
- this.hoveredIndex = -1
524
- }, 100)
525
- },
526
- // 鼠标进入悬浮选项框
527
- handleOptionsEnter () {
528
- this.clearAllTimers()
529
- this.isOptionsHovered = true
530
- },
531
- // 鼠标离开悬浮选项框
532
- handleOptionsLeave () {
533
- this.clearAllTimers()
534
- this.leaveTimer = setTimeout(() => {
535
- this.isOptionsHovered = false
536
- this.hoveredIndex = -1
537
- }, 100)
538
- },
539
- // 清除所有定时器
540
- clearAllTimers () {
541
- if (this.hoverTimer) {
542
- clearTimeout(this.hoverTimer)
543
- this.hoverTimer = null
544
- }
545
- if (this.leaveTimer) {
546
- clearTimeout(this.leaveTimer)
547
- this.leaveTimer = null
548
- }
549
- },
550
- // 选项框点击
551
- handleOptionClick (index, action) {
552
- this.$emit('optionClick', { data: this.data[index], action })
553
- },
554
- // 获取文本样式(简化版本,主要依赖CSS类控制)
555
- getTextStyle (index) {
556
- return {}
557
- },
558
- },
559
- watch: {
560
- // 同步受控值变化
561
- selectedIndex (val) {
562
- if (typeof val === 'number') {
563
- // 允许受控值影响内部显示
564
- this.localSelectedIndex = val
565
- }
566
- },
567
- fixedQueryForm: {
568
- deep: true,
569
- handler (val) {
570
- this.refreshList(val)
571
- }
572
- },
573
- },
574
- beforeDestroy () {
575
- const ref = this.$refs.listRef
576
- if (ref && ref.removeEventListener) {
577
- ref.removeEventListener('scroll', this.handleInfiniteOnLoad)
578
- }
579
- this.clearAllTimers()
580
- }
581
- }
582
- </script>
583
-
584
- <style scoped lang="less">
585
- .list-wrapper {
586
- max-height: 240px;
587
- overflow-y: auto;
588
- padding-right: 2px;
589
- }
590
-
591
- .list-container {
592
- width: 100%;
593
- }
594
-
595
- .list-item {
596
- height: 35px;
597
- border-radius: 6px;
598
- background-color: #F4F4F4;
599
- padding: 8px 15px;
600
- font-size: 16px;
601
- display: flex;
602
- align-items: center;
603
- width: 100%;
604
- border: 1px solid #D9D9D9;
605
- box-sizing: border-box;
606
- margin-bottom: 8px !important;
607
- position: relative;
608
- transition: background-color 0.3s ease;
609
- }
610
-
611
- .icon-menu {
612
- display: inline-block;
613
- width: 20px;
614
- height: 20px;
615
- background-color: #ccc;
616
- margin-right: 8px;
617
- }
618
-
619
- .item-text {
620
- flex: 1;
621
- }
622
-
623
- .confirm-btn {
624
- margin-left: auto;
625
- padding: 0 8px;
626
- }
627
-
628
- .confirm-btn.hover-btn {
629
- opacity: 0;
630
- transition: opacity 0.3s ease;
631
- }
632
-
633
- .button-group {
634
- display: flex;
635
- gap: 4px; /* 按钮之间的间距 */
636
- }
637
-
638
- .list-item:hover .confirm-btn.hover-btn {
639
- opacity: 1;
640
- }
641
-
642
- /* 自定义滚动条样式 */
643
- .list-wrapper::-webkit-scrollbar {
644
- width: 6px;
645
- }
646
-
647
- .list-wrapper::-webkit-scrollbar-thumb {
648
- background-color: #d9d9d9;
649
- border-radius: 3px;
650
- }
651
-
652
- .list-wrapper::-webkit-scrollbar-track {
653
- background-color: #f0f0f0;
654
- }
655
-
656
- .hover-active {
657
- color: white;
658
- }
659
-
660
- .list-item.hover-active {
661
- background-color: rgb(0, 87, 254) !important;
662
- color: white;
663
- border: 1px solid black;
664
- }
665
-
666
- /* 选中态样式(通过 selectRow 开启) */
667
- .selected-active { color: white; }
668
- .list-item.selected-active {
669
- background-color: #0057FE !important;
670
- color: white;
671
- border: none !important;
672
- }
673
- .list-item.selected-active .confirm-btn,
674
- .list-item.selected-active .confirm-btn span,
675
- .list-item.selected-active .ant-btn,
676
- .list-item.selected-active .ant-btn > span { color: #ffffff !important; }
677
- .card-a-col.selected-active {
678
- background-color: #0057FE !important;
679
- color: white;
680
- border: none !important;
681
- }
682
- .card-a-col.selected-active .button-a-col,
683
- .card-a-col.selected-active .button-a-col .ant-btn,
684
- .card-a-col.selected-active .button-a-col .ant-btn > span { color: #ffffff !important; }
685
-
686
- .hover-options {
687
- position: absolute;
688
- left: 0;
689
- right: 0;
690
- top: 100%;
691
- background: white;
692
- border: 1px solid #d9d9d9;
693
- border-radius: 4px;
694
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
695
- z-index: 1000;
696
- margin-top: 4px;
697
- width: 100%;
698
- box-sizing: border-box;
699
- pointer-events: auto;
700
- }
701
-
702
- .hover-options-content {
703
- padding: 4px 0;
704
- display: flex;
705
- flex-direction: column;
706
- width: 100%;
707
- }
708
-
709
- .option-item {
710
- padding: 8px 12px;
711
- cursor: pointer;
712
- transition: all 0.3s ease;
713
- color: #333;
714
- font-size: 14px;
715
- display: flex;
716
- align-items: center;
717
- }
718
-
719
- .option-item:hover {
720
- background-color: #f5f5f5;
721
- color: #1890ff;
722
- }
723
-
724
- .option-item:active {
725
- background-color: #e6f7ff;
726
- }
727
-
728
- .demo-loading-container {
729
- position: absolute;
730
- bottom: 40px;
731
- width: 100%;
732
- text-align: center;
733
- }
734
-
735
- .demo-infinite-container{
736
- overflow-x: hidden;
737
- overflow-y: auto;
738
- height: 85vh;
739
- }
740
- .card-row{
741
- height: 100%;
742
- width: 100%;
743
- border-radius: 6px;
744
- padding: 6px;
745
- }
746
- .id-a-col{
747
- font-size: 22px;
748
- font-weight: 700;
749
- display: flex;
750
- flex-direction: column;
751
- align-items: center;
752
- justify-content: center;
753
- gap: 4px;
754
- }
755
- .id-a-col-2{
756
- padding: 8px;
757
- height: 100%;
758
- overflow: hidden;
759
- display: flex;
760
- flex-direction: column;
761
- justify-content: space-between;
762
- }
763
- .describe-list-a-col{
764
- display: block;
765
- font-family: Source Han Sans;
766
- font-size: 16px;
767
- font-weight: normal;
768
- line-height: normal;
769
- overflow: hidden;
770
- text-overflow: ellipsis;
771
- white-space: nowrap;
772
- max-width: 100%;
773
- }
774
- .name{
775
- font-family: Source Han Sans;
776
- font-size: 22px;
777
- font-weight: bold;
778
- line-height: normal;
779
- }
780
- .component-a-col{
781
- display: flex;
782
- align-items: center;
783
- overflow: hidden;
784
- }
785
- .label-text{
786
- overflow: hidden;
787
- text-overflow: ellipsis;
788
- white-space: nowrap;
789
- max-width: 120px;
790
- display: inline-block;
791
- }
792
- .gender-icon{
793
- margin-top: 2px;
794
- }
795
- .gender-icon .male{ color: #2f54eb; font-size: 14px; }
796
- .gender-icon .female{ color: #eb2f96; font-size: 14px; }
797
- .gender-img{ width: 100%; height: 100%; opacity: 1; display: inline-block; }
798
- .title-row{
799
- display: flex;
800
- align-items: center;
801
- justify-content: space-between;
802
- gap: 8px;
803
- }
804
- /* 标题文本占满剩余空间,确保箭头贴右 */
805
- .title-row .describe-list-a-col{ flex: 1; }
806
- .title-actions{ display: inline-flex; align-items: center; gap: 6px; }
807
- .title-select-label{
808
- font-family: Source Han Sans;
809
- font-size: 16px;
810
- font-weight: normal;
811
- line-height: normal;
812
- color: #595959;
813
- }
814
- .title-select{ min-width: 96px; }
815
- .arrow-btn{ display: inline-flex; align-items: center; color: #8C8C8C; }
816
- .arrow-btn .anticon{ font-size: 18px; }
817
- /* 放大下拉箭头的 svg 尺寸以符合 UI(scoped 深度选择) */
818
- ::v-deep .arrow-btn .anticon svg{ width: 2em; height: 2em; }
819
- .button-a-col{
820
- position: absolute;
821
- top: 245px;
822
- left: 225px;
823
- }
824
- .card-a-col{
825
- background-color: rgba(247, 249, 252);
826
- height: 297px;
827
- width: auto;
828
- border-radius: 6px;
829
- border: 1px solid #E5E9F0;
830
- overflow: hidden;
831
- position: relative;
832
- box-sizing: border-box;
833
- margin: 10px;
834
- }
835
-
836
- /* 新列表样式 */
837
- .x-list-enableNewListStyle {
838
- /* 重写 list-wrapper 样式,去除 padding-right、max-height 和滚动条 */
839
- &.x-list-wrapper.list-wrapper {
840
- padding-right: 0 !important;
841
- max-height: none !important;
842
- overflow: visible !important;
843
- overflow-y: visible !important;
844
- }
845
-
846
- .list-item {
847
- width: 100%; /* 正常情况下占据整个宽度 */
848
- height: 35px;
849
- border-radius: 6px;
850
- opacity: 1;
851
- background: #F4F4F4;
852
- padding: 8px 12px;
853
- margin-bottom: 8px !important;
854
- display: flex;
855
- align-items: center;
856
- justify-content: space-between;
857
- box-sizing: border-box;
858
- transition: width 0.3s ease; /* 添加宽度过渡效果 */
859
- }
860
-
861
- /* 悬停时恢复固定宽度 */
862
- .list-item:hover {
863
- width: 234px; /* 悬停时恢复固定宽度 */
864
- }
865
-
866
- .item-text {
867
- height: 20px;
868
- opacity: 1;
869
- font-family: Source Han Sans;
870
- font-size: 14px;
871
- font-weight: normal;
872
- line-height: normal;
873
- letter-spacing: 0em;
874
- font-feature-settings: "kern" on;
875
- color: #313131;
876
- flex: 1; /* 占据剩余空间 */
877
- margin-right: 1px; /* 与按钮组保持8px间距 */
878
- transition: width 0.3s ease; /* 只对宽度进行过渡,避免溢出控制闪烁 */
879
- white-space: nowrap; /* 不换行 */
880
- overflow: visible; /* 正常情况下显示全部内容 */
881
- text-overflow: initial; /* 正常情况下不显示省略号 */
882
- }
883
-
884
- /* 悬停时隐藏超出部分 - 立即生效,不添加过渡 */
885
- .list-item:hover .item-text {
886
- overflow: hidden; /* 悬停时隐藏溢出内容 */
887
- text-overflow: ellipsis; /* 悬停时显示省略号 */
888
- transition: none; /* 溢出控制立即生效,避免闪烁 */
889
- }
890
-
891
- .button-group {
892
- gap: 4px; /* 按钮之间的间距 */
893
- flex-shrink: 0; /* 防止按钮组被压缩 */
894
- }
895
-
896
- .confirm-btn {
897
- height: 20px;
898
- opacity: 0; /* 默认隐藏 */
899
- transition: opacity 0.3s ease; /* 添加过渡效果 */
900
- font-family: Source Han Sans;
901
- font-size: 14px;
902
- font-weight: normal;
903
- line-height: normal;
904
- letter-spacing: 0em;
905
- font-feature-settings: "kern" on;
906
- /* 移除固定颜色,继承默认颜色 */
907
- padding: 0; /* 清除内边距 */
908
- margin-left: 0; /* 移除左边距,使用 gap 控制间距 */
909
-
910
- span {
911
- height: 20px;
912
- opacity: 1;
913
- font-family: Source Han Sans;
914
- font-size: 14px;
915
- font-weight: normal;
916
- line-height: normal;
917
- letter-spacing: 0em;
918
- font-feature-settings: "kern" on;
919
- /* 移除固定颜色,继承默认颜色 */
920
- }
921
- }
922
- /* 悬浮时显示按钮 */
923
- .list-item:hover .confirm-btn {
924
- opacity: 1;
925
- }
926
- /* 选中状态字体颜色 - 使用白色,与全局样式保持一致 */
927
- .list-item.selected-active {
928
- color: white !important; /* 使用白色文本 */
929
- }
930
- .list-item.selected-active .item-text {
931
- color: white !important; /* 确保文本使用白色 */
932
- }
933
- .list-item.selected-active .confirm-btn,
934
- .list-item.selected-active .confirm-btn span {
935
- color: #ffffff !important; /* 按钮使用白色 */
936
- }
937
- }
938
- </style>
1
+ <template>
2
+ <!-- 列表卡片模式 listMode: card -->
3
+ <div
4
+ class="x-list-wrapper"
5
+ :class="wrapperClassObject"
6
+ v-if="listMode"
7
+ ref="listRef"
8
+ @scroll="handleInfiniteOnLoad">
9
+ <a-list
10
+ :grid="{ gutter: 16, xs: 1, sm: 2, md: 2, lg: 3, xl: 3, xxl: 4 }"
11
+ :data-source="localData">
12
+ <a-list-item slot="renderItem" slot-scope="item, index">
13
+ <div class="card-a-col" :class="{ 'selected-active': enableSelectRow && currentSelectedIndex === index }" :style="getCardStyle(currentTitleValue(index))" @click="handleCardClick(index)">
14
+ <a-row class="card-row">
15
+ <a-col class="id-a-col" :span="4" v-for="(detail,idx) in item.filter(d => d.label == label)" :key="idx">
16
+ {{ detail.value }}
17
+ <div class="gender-icon" v-if="getHasPatient(item) && getGender(item)">
18
+ <img :src="getGender(item) === '男' ? maleIcon : femaleIcon" :alt="getGender(item)" class="gender-img" />
19
+ </div>
20
+ </a-col>
21
+ <a-col :span="20" class="id-a-col-2">
22
+ <template v-for="(detail,idx) in item">
23
+ <div :key="`title_${idx}`" class="title-row" v-if="detail.type == 'title'">
24
+ <a-tooltip :title="detail.value" placement="topLeft">
25
+ <span class="describe-list-a-col" :class="{name: detail.bold}">{{ detail.value }}</span>
26
+ </a-tooltip>
27
+ <div class="title-actions" v-if="getTitleOptions && getTitleOptions.length">
28
+ <span class="title-select-label">{{ getDisplayTitleLabel(index) }}</span>
29
+ <a-dropdown placement="bottomRight" trigger="['click']">
30
+ <a class="arrow-btn" @click.prevent>
31
+ <a-icon type="down" />
32
+ </a>
33
+ <a-menu slot="overlay" :selectedKeys="[String(currentTitleValue(index))]" @click="info => handleTitleMenuClick(info, index)">
34
+ <a-menu-item v-for="opt in getTitleOptions" :key="String(opt && opt.value !== undefined ? opt.value : opt)">
35
+ {{ opt && opt.label !== undefined ? opt.label : opt }}
36
+ </a-menu-item>
37
+ </a-menu>
38
+ </a-dropdown>
39
+ </div>
40
+ </div>
41
+ <span :key="idx" class="component-a-col" v-else-if="getHasPatient(item) && detail.type == 'component' && detail.label != label">
42
+ <a-tooltip :title="detail.label" placement="topLeft">
43
+ <span class="label-text">{{ `${detail.label}:` }}</span>
44
+ </a-tooltip>
45
+ <component
46
+ :is="detail.slotType"
47
+ :key="idx"
48
+ :ref="`dynamicComponent_${ idx.slotType || idx}_${idx}`"
49
+ :serviceName="serviceName"
50
+ v-on="forwardAllEvents"
51
+ :queryParamsName="detail.value"
52
+ :countVisible="false"
53
+ />
54
+ </span>
55
+ <span :key="idx" class="component-a-col" v-else-if="getHasPatient(item) && detail.type == 'date'">
56
+ <a-tooltip :title="detail.label" placement="topLeft">
57
+ <span class="label-text">{{ `${detail.label}:` }}</span>
58
+ </a-tooltip>
59
+ <a-date-picker @change="onChange" />
60
+ </span>
61
+ <a-tooltip :key="idx" :title="`${detail.label}:${detail.value}`" placement="topLeft" v-else-if="getHasPatient(item) && detail.label != label">
62
+ <span class="describe-list-a-col" :class="{name: detail.bold}">{{ `${detail.label}:${detail.value}` }}</span>
63
+ </a-tooltip>
64
+ </template>
65
+ <a-button
66
+ v-if="getHasPatient(item) && showCardButtons"
67
+ v-for="(btn, i) in buttonNames"
68
+ :key="i"
69
+ icon="search"
70
+ class="button-a-col"
71
+ @click.stop="click(item, index)">
72
+ {{ btn }}
73
+ </a-button>
74
+ </a-col>
75
+ </a-row>
76
+ </div>
77
+ </a-list-item>
78
+ <div v-if="loading" class="demo-loading-container">
79
+ <a-spin />
80
+ </div>
81
+ <div v-if="allLoaded">
82
+ <div class="demo-infinite-list-bottom">
83
+ 已经显示全部数据
84
+ </div>
85
+ </div>
86
+ </a-list>
87
+ </div>
88
+
89
+ <!-- 默认标签模式 -->
90
+ <div class="list-wrapper x-list-wrapper" :class="wrapperClassObject" v-else>
91
+ <a-list size="large" :data-source="data" itemLayout="horizontal" class="list-container" ref="listRef">
92
+ <a-list-item
93
+ slot="renderItem"
94
+ slot-scope="item, index"
95
+ class="list-item"
96
+ @click="handleClick(index)"
97
+ @mouseenter="enableHoverOptions && handleMouseEnter(index)"
98
+ @mouseleave="handleMouseLeave"
99
+ :class="{ 'hover-active': enableHoverOptions && hoveredIndex === index, 'selected-active': enableSelectRow && currentSelectedIndex === index }">
100
+ <i
101
+ v-if="icon"
102
+ class="icon-menu"
103
+ :style="getIconStyle(item)">
104
+ </i>
105
+ <span
106
+ class="item-text"
107
+ :class="{ 'text-truncated': enableHoverOptions && hoveredIndex === index }"
108
+ :style="getTextStyle(index)">
109
+ {{ item.number }} {{ item.name }}
110
+ </span>
111
+
112
+ <div v-if="button" class="button-group">
113
+ <a-button
114
+ v-for="(name, idx) in buttonNames"
115
+ :key="idx"
116
+ type="link"
117
+ :class="['confirm-btn', buttonMode ? 'hover-btn' : '']"
118
+ @click.stop="click(index, idx)">
119
+ <span :class="{ 'hover-active': enableHoverOptions && hoveredIndex === index }">{{ name }}</span>
120
+ </a-button>
121
+ </div>
122
+
123
+ <!-- 悬浮选项框 -->
124
+ <div
125
+ v-show="enableHoverOptions && hoveredIndex === index"
126
+ class="hover-options"
127
+ @mouseenter="handleOptionsEnter"
128
+ @mouseleave="handleOptionsLeave">
129
+ <div class="hover-options-content">
130
+ <div
131
+ v-for="(Item, idx) in select_options"
132
+ :key="idx"
133
+ class="option-item"
134
+ @click="handleOptionClick(index, Item)">
135
+ {{ Item }}
136
+ </div>
137
+ </div>
138
+ </div>
139
+ </a-list-item>
140
+ </a-list>
141
+ </div>
142
+ </template>
143
+
144
+ <script>
145
+
146
+ import { getConfigByName, runLogic } from '@vue2-client/services/api/common'
147
+
148
+ export default {
149
+ name: 'XList',
150
+ components: {
151
+ XReport: () => import('@vue2-client/base-client/components/common/XReport/XReport.vue'),
152
+ XButtons: () => import('@vue2-client/base-client/components/common/XButtons/XButtons.vue'),
153
+ XInput: () => import('@vue2-client/base-client/components/common/XInput/XInput.vue'),
154
+ XRadio: () => import('@vue2-client/base-client/components/his/XRadio/XRadio.vue'),
155
+ XTimeSelect: () => import('@vue2-client/base-client/components/his/XTimeSelect/XTimeSelect.vue'),
156
+ XCheckbox: () => import('@vue2-client/base-client/components/his/XCheckbox/XCheckbox.vue'),
157
+ XTitle: () => import('@vue2-client/base-client/components/his/XTitle/XTitle.vue'),
158
+ XSelect: () => import('@vue2-client/base-client/components/his/XSelect/XSelect.vue')
159
+ },
160
+ props: {
161
+ queryParamsName: {
162
+ type: Object,
163
+ default: null
164
+ },
165
+ fixedQueryForm: {
166
+ type: Object,
167
+ default: { condition: '1=1' }
168
+ },
169
+ enableHoverOptions: {
170
+ type: Boolean,
171
+ default: true
172
+ },
173
+ serviceName: {
174
+ type: String,
175
+ default: 'af-his'
176
+ },
177
+ // 点击是否触发选中(默认不通过点击选中,仅手动控制)
178
+ selectOnClick: {
179
+ type: Boolean,
180
+ default: false
181
+ },
182
+ // 受控选中索引;不传则内部维护
183
+ selectedIndex: {
184
+ type: Number,
185
+ default: undefined
186
+ },
187
+ // 卡片按钮显示控制(默认隐藏,可通过属性或配置开启)
188
+ showCardButtons: {
189
+ type: Boolean,
190
+ default: false
191
+ },
192
+ // 标题右侧下拉选项与受控值
193
+ titleSelectOptions: {
194
+ type: Array,
195
+ default: () => []
196
+ },
197
+ titleSelectValue: {
198
+ type: [String, Number],
199
+ default: undefined
200
+ },
201
+ },
202
+ data () {
203
+ return {
204
+ data: [], // 数据源
205
+ localData: [], // 本地数据源
206
+ loading: false, // 加载中
207
+ busy: false, // 繁忙状态
208
+ button: false,
209
+ icon: false,
210
+ buttonNames: [],
211
+ listMode: undefined, // 列表模式
212
+ buttonMode: true,
213
+ hoveredIndex: -1, // 当前悬浮的索引
214
+ isOptionsHovered: false, // 悬浮选项框是否悬浮
215
+ hoverTimer: null, // 悬浮选项框定时器
216
+ leaveTimer: null, // 离开选项框定时器
217
+ select_options: [], // 悬浮选项框
218
+ logicName: '',
219
+ nowPage: 0, // 当前页
220
+ pageSize: 12,
221
+ allLoaded: false,
222
+ label: 'id',
223
+ scrollTimer: null,
224
+ // 内部选中索引(非受控时使用)
225
+ localSelectedIndex: -1,
226
+ maleIcon: require('@vue2-client/assets/svg/male.svg'),
227
+ femaleIcon: require('@vue2-client/assets/svg/female.svg'),
228
+ // 下拉配置
229
+ internalTitleOptions: [],
230
+ titleValueByIndex: {},
231
+ // 选择请求的轻量防抖
232
+ selectDebounceTimer: null
233
+ }
234
+ },
235
+ inject: ['getComponentByName'],
236
+
237
+ created () {
238
+ this.getData(this.queryParamsName, this.fixedQueryForm)
239
+ },
240
+ mounted () {},
241
+ computed: {
242
+ // 参考 HForm 的 wrapperClassObject 规则,支持通过组件属性动态控制样式
243
+ wrapperClassObject () {
244
+ const a = this.$attrs || {}
245
+ const classes = {}
246
+ // 多个布尔型样式开关(存在且为真则生效)
247
+ const booleanStyleKeys = [
248
+ 'enableNewListStyle'
249
+ ]
250
+ booleanStyleKeys.forEach(key => {
251
+ const val = a[key]
252
+ const truthy = val === true || val === '' || val === 'true'
253
+ if (truthy) classes[`x-list-${key}`] = true
254
+ })
255
+ return classes
256
+ },
257
+ // 标题下拉:优先使用外部 props,否则使用内部配置
258
+ getTitleOptions () {
259
+ if (Array.isArray(this.titleSelectOptions) && this.titleSelectOptions.length) return this.titleSelectOptions
260
+ return this.internalTitleOptions
261
+ },
262
+ currentTitleValue () {
263
+ return (index) => {
264
+ if (this.titleSelectValue !== undefined) return this.titleSelectValue
265
+ const local = this.titleValueByIndex[index]
266
+ if (local !== undefined) return local
267
+ // 二次回退:若模板标题提供了 titleRightValue,则用于首屏渲染颜色与文案
268
+ const row = Array.isArray(this.localData) ? this.localData[index] : null
269
+ if (Array.isArray(row)) {
270
+ const title = row.find(d => d && d.type === 'title')
271
+ if (title && title.titleRightValue !== undefined) return title.titleRightValue
272
+ }
273
+ // 最终回退:使用 options 的第一个
274
+ const def = this.internalTitleOptions && this.internalTitleOptions.length ? (this.internalTitleOptions[0].value !== undefined ? this.internalTitleOptions[0].value : this.internalTitleOptions[0]) : undefined
275
+ return def
276
+ }
277
+ },
278
+ // 选择控制:受控优先
279
+ currentSelectedIndex () {
280
+ return typeof this.selectedIndex === 'number' ? this.selectedIndex : this.localSelectedIndex
281
+ },
282
+ enableSelectRow () {
283
+ const a = this.$attrs || {}
284
+ const val = a.enableSelection
285
+ return val === true || val === '' || val === 'true'
286
+ },
287
+ forwardAllEvents () {
288
+ return {
289
+ // 监听所有事件并转发给父组件
290
+ '*': (eventName, ...payload) => {
291
+ this.$emit(eventName, ...payload)
292
+ }
293
+ }
294
+ }
295
+ },
296
+ methods: {
297
+ onChange (date, dateString) {
298
+ this.$emit('dateChange', date, dateString)
299
+ },
300
+ handleInfiniteOnLoad (event) {
301
+ if (this.busy || this.allLoaded) return // 防止重复加载
302
+ if (this.scrollTimer) clearTimeout(this.scrollTimer)
303
+ this.scrollTimer = setTimeout(() => {
304
+ const container = event.target
305
+ const scrollTop = container.scrollTop
306
+ const scrollHeight = container.scrollHeight
307
+ const clientHeight = container.clientHeight
308
+ const bottomOffset = 10
309
+ if (scrollTop + clientHeight >= scrollHeight - bottomOffset) {
310
+ this.busy = true
311
+ this.loading = true
312
+ this.nowPage = this.nowPage + this.pageSize
313
+ this.fixedQueryForm.condition = `Limit ${this.nowPage}, ${this.pageSize}`
314
+ runLogic(this.logicName, this.fixedQueryForm, 'af-his').then(async (res) => {
315
+ this.localData = [...this.localData, ...res]
316
+ if (res.length < this.pageSize) {
317
+ this.allLoaded = true
318
+ }
319
+ }).catch(e => {
320
+ this.$message.error(e.message)
321
+ }).finally(() => {
322
+ this.loading = false
323
+ this.busy = false
324
+ })
325
+ }
326
+ }, 100)
327
+ },
328
+ async getData (config, param) {
329
+ const that = this
330
+ getConfigByName(config, 'af-his', async (res) => {
331
+ that.listMode = await res.listMode == 'card'
332
+ that.logicName = await res.data
333
+ that.button = await res.button // 按钮
334
+ that.icon = await res.icon // 图标
335
+ that.label = await res.label // 标签
336
+ that.buttonNames = await res.buttonNames || []// 按钮文本
337
+ that.buttonMode = await res.buttonMode || false// 按钮模式
338
+ that.cardButtonsVisible = await res.cardButtonsVisible || false// 卡片按钮
339
+ // 标题下拉:从配置拿 options: [{label,value,color}]
340
+ if (Array.isArray(res.titleOptions)) {
341
+ this.internalTitleOptions = res.titleOptions
342
+ if (res.titleDefaultValue !== undefined && Array.isArray(this.localData)) {
343
+ // 初始化每个卡片的默认值
344
+ this.titleValueByIndex = {}
345
+ }
346
+ }
347
+ this.enableHoverOptions = await res.enableHoverOptions || false// 悬浮选项框
348
+ if (this.enableHoverOptions) {
349
+ this.select_options = await res.select_options
350
+ }
351
+ if (that.listMode) { param.condition = `Limit ${that.nowPage}, ${that.pageSize}` }
352
+ runLogic(res.data, param, 'af-his').then(result => {
353
+ that.data = result
354
+ if (that.nowPage === 0) { this.localData = result }
355
+ // 初始化每张卡片的 title 选中值:优先读取模板 titleRightValue,否则使用配置默认或第一项
356
+ if (Array.isArray(this.localData)) {
357
+ this.localData.forEach((row, idx) => {
358
+ if (this.titleValueByIndex[idx] !== undefined) return
359
+ if (Array.isArray(row)) {
360
+ const title = row.find(d => d && d.type === 'title')
361
+ if (title && title.titleRightValue !== undefined) {
362
+ this.$set(this.titleValueByIndex, idx, title.titleRightValue)
363
+ return
364
+ }
365
+ }
366
+ // fallback:配置默认或第一项
367
+ const def = (this.internalTitleOptions && this.internalTitleOptions.length)
368
+ ? (this.internalTitleOptions[0].value !== undefined ? this.internalTitleOptions[0].value : this.internalTitleOptions[0])
369
+ : undefined
370
+ if (def !== undefined) this.$set(this.titleValueByIndex, idx, def)
371
+ })
372
+ }
373
+ })
374
+ })
375
+ },
376
+ // 提取性别:从数组数据中查找 label 含“性别”的项
377
+ getGender (item) {
378
+ if (!Array.isArray(item)) return null
379
+ const g = item.find(d => d && typeof d.label === 'string' && d.label.indexOf('性别') > -1)
380
+ const val = g && (g.value || g.text)
381
+ if (!val) return null
382
+ if (String(val).includes('男')) return '男'
383
+ if (String(val).includes('女')) return '女'
384
+ return null
385
+ },
386
+ // 读取标题项上的 hasPatient 布尔值
387
+ getHasPatient (item) {
388
+ if (!Array.isArray(item)) return true
389
+ const title = item.find(d => d && d.type === 'title')
390
+ if (!title || typeof title.hasPatient === 'undefined') return true
391
+ return !!title.hasPatient
392
+ },
393
+ // 标题右侧下拉选择
394
+ handleTitleSelectChange (val, index) {
395
+ // 重复值拦截:若值未变化则直接返回
396
+ const prev = this.normalizeValue(this.currentTitleValue(index))
397
+ const next = this.normalizeValue(val)
398
+ if (prev === next) return
399
+
400
+ this.$set(this.titleValueByIndex, index, val)
401
+ this.$emit('update:titleSelectValue', val)
402
+ this.$emit('titleSelectChange', { index, value: val })
403
+ // 变更后仅通知后端更新,不处理返回值;支持从标题项读取 extraParams 合并(如住院号)
404
+ const extra = this.getTitleExtraParams(index)
405
+ if (this.selectDebounceTimer) clearTimeout(this.selectDebounceTimer)
406
+ this.selectDebounceTimer = setTimeout(() => {
407
+ runLogic(this.logicName, Object.assign({ type: 'select', value: val }, extra), 'af-his').catch(() => {})
408
+ }, 200)
409
+ },
410
+ // 读取标题项中额外需要传递的参数(可选),例如 { inpatientNo: row.t_id }
411
+ getTitleExtraParams (index) {
412
+ const row = Array.isArray(this.localData) ? this.localData[index] : null
413
+ if (!Array.isArray(row)) return {}
414
+ const title = row.find(d => d && d.type === 'title') || {}
415
+ if (title && title.extraParams && typeof title.extraParams === 'object') return title.extraParams
416
+ return {}
417
+ },
418
+ handleTitleMenuClick ({ key }, index) {
419
+ const v = isNaN(Number(key)) ? key : Number(key)
420
+ this.handleTitleSelectChange(v, index)
421
+ },
422
+ // 根据当前选择项的 color 设置卡片背景色
423
+ normalizeValue (v) { return String(v) },
424
+ getCardStyle (val) {
425
+ const target = this.normalizeValue(val)
426
+ const opt = (this.getTitleOptions || []).find(o => this.normalizeValue(o && (o.value !== undefined ? o.value : o)) === target)
427
+ const color = opt && (opt.color || (opt.style && opt.style.background))
428
+ return color ? { backgroundColor: color } : {}
429
+ },
430
+ getTitleLabel (val) {
431
+ const target = this.normalizeValue(val)
432
+ const opt = (this.getTitleOptions || []).find(o => this.normalizeValue(o && (o.value !== undefined ? o.value : o)) === target)
433
+ return opt && (opt.label !== undefined ? opt.label : opt)
434
+ },
435
+ getDisplayTitleLabel (index) {
436
+ // 优先展示“当前选中值”的 label,未选中再回退到模板提供的 titleRightLabel
437
+ const current = this.getTitleLabel(this.currentTitleValue(index))
438
+ if (current) return current
439
+ const title = Array.isArray(this.localData && this.localData[index])
440
+ ? this.localData[index].find(d => d && d.type === 'title')
441
+ : null
442
+ return title && title.titleRightLabel ? title.titleRightLabel : ''
443
+ },
444
+ // 点击列表项
445
+ handleClick (index) {
446
+ if (this.enableSelectRow && this.selectOnClick) this.setSelectedIndex(index)
447
+ this.$emit('listClick', this.data[index])
448
+ },
449
+ // 卡片模式点击卡片
450
+ handleCardClick (index) {
451
+ if (this.enableSelectRow && this.selectOnClick) this.setSelectedIndex(index)
452
+ this.$emit('listClick', this.localData[index])
453
+ },
454
+ // 外部可调用:设置选中索引
455
+ setSelectedIndex (index) {
456
+ const next = typeof index === 'number' ? index : -1
457
+ if (typeof this.selectedIndex === 'number') {
458
+ // 受控:仅派发事件
459
+ this.$emit('update:selectedIndex', next)
460
+ } else {
461
+ // 非受控:更新内部并派发事件
462
+ this.localSelectedIndex = next
463
+ this.$emit('update:selectedIndex', next)
464
+ }
465
+ },
466
+ // 外部可调用:清空选中
467
+ clearSelected () { this.setSelectedIndex(-1) },
468
+ refreshList (param) {
469
+ this.getData(this.queryParamsName, param)
470
+ },
471
+ click (index, buttonIndex) {
472
+ this.$emit('click', { data: this.data[index], name: this.buttonNames[buttonIndex] })
473
+ },
474
+ // 根据对象字段匹配选中(默认按 id 字段)
475
+ setSelectedById (id, field = 'id') {
476
+ const list = this.listMode ? this.localData : this.data
477
+ if (!Array.isArray(list)) return
478
+ const index = list.findIndex(item => {
479
+ if (Array.isArray(item)) {
480
+ const f = item.find(d => d && d.label === field)
481
+ return f && f.value === id
482
+ }
483
+ return item && item[field] === id
484
+ })
485
+ if (index >= 0) this.setSelectedIndex(index)
486
+ },
487
+ // 根据 label/value(卡片数组数据场景)匹配选中
488
+ setSelectedByLabelValue (label, value) {
489
+ const list = this.listMode ? this.localData : this.data
490
+ if (!Array.isArray(list)) return
491
+ const index = list.findIndex(item => Array.isArray(item) && item.some(d => d && d.label === label && d.value === value))
492
+ if (index >= 0) this.setSelectedIndex(index)
493
+ },
494
+ // 通用:传入谓词函数决定选中项
495
+ setSelectedBy (predicate) {
496
+ if (typeof predicate !== 'function') return
497
+ const list = this.listMode ? this.localData : this.data
498
+ if (!Array.isArray(list)) return
499
+ const index = list.findIndex(predicate)
500
+ if (index >= 0) this.setSelectedIndex(index)
501
+ },
502
+ getIconStyle (item) {
503
+ return item.picture
504
+ ? { backgroundImage: `url(${item.picture})` }
505
+ : {}
506
+ },
507
+ filterData (par) {
508
+ runLogic(this.queryParamsName, par, 'af-his').then(res => {
509
+ this.data = res.data
510
+ })
511
+ },
512
+ // 鼠标进入列表项
513
+ handleMouseEnter (index) {
514
+ this.clearAllTimers()
515
+ this.hoveredIndex = index
516
+ this.isOptionsHovered = true
517
+ },
518
+ // 鼠标离开列表项
519
+ handleMouseLeave () {
520
+ this.clearAllTimers()
521
+ this.leaveTimer = setTimeout(() => {
522
+ this.isOptionsHovered = false
523
+ this.hoveredIndex = -1
524
+ }, 100)
525
+ },
526
+ // 鼠标进入悬浮选项框
527
+ handleOptionsEnter () {
528
+ this.clearAllTimers()
529
+ this.isOptionsHovered = true
530
+ },
531
+ // 鼠标离开悬浮选项框
532
+ handleOptionsLeave () {
533
+ this.clearAllTimers()
534
+ this.leaveTimer = setTimeout(() => {
535
+ this.isOptionsHovered = false
536
+ this.hoveredIndex = -1
537
+ }, 100)
538
+ },
539
+ // 清除所有定时器
540
+ clearAllTimers () {
541
+ if (this.hoverTimer) {
542
+ clearTimeout(this.hoverTimer)
543
+ this.hoverTimer = null
544
+ }
545
+ if (this.leaveTimer) {
546
+ clearTimeout(this.leaveTimer)
547
+ this.leaveTimer = null
548
+ }
549
+ },
550
+ // 选项框点击
551
+ handleOptionClick (index, action) {
552
+ this.$emit('optionClick', { data: this.data[index], action })
553
+ },
554
+ // 获取文本样式(简化版本,主要依赖CSS类控制)
555
+ getTextStyle (index) {
556
+ return {}
557
+ },
558
+ },
559
+ watch: {
560
+ // 同步受控值变化
561
+ selectedIndex (val) {
562
+ if (typeof val === 'number') {
563
+ // 允许受控值影响内部显示
564
+ this.localSelectedIndex = val
565
+ }
566
+ },
567
+ fixedQueryForm: {
568
+ deep: true,
569
+ handler (val) {
570
+ this.refreshList(val)
571
+ }
572
+ },
573
+ },
574
+ beforeDestroy () {
575
+ const ref = this.$refs.listRef
576
+ if (ref && ref.removeEventListener) {
577
+ ref.removeEventListener('scroll', this.handleInfiniteOnLoad)
578
+ }
579
+ this.clearAllTimers()
580
+ }
581
+ }
582
+ </script>
583
+
584
+ <style scoped lang="less">
585
+ .list-wrapper {
586
+ max-height: 240px;
587
+ overflow-y: auto;
588
+ padding-right: 2px;
589
+ }
590
+
591
+ .list-container {
592
+ width: 100%;
593
+ }
594
+
595
+ .list-item {
596
+ height: 35px;
597
+ border-radius: 6px;
598
+ background-color: #F4F4F4;
599
+ padding: 8px 15px;
600
+ font-size: 16px;
601
+ display: flex;
602
+ align-items: center;
603
+ width: 100%;
604
+ border: 1px solid #D9D9D9;
605
+ box-sizing: border-box;
606
+ margin-bottom: 8px !important;
607
+ position: relative;
608
+ transition: background-color 0.3s ease;
609
+ }
610
+
611
+ .icon-menu {
612
+ display: inline-block;
613
+ width: 20px;
614
+ height: 20px;
615
+ background-color: #ccc;
616
+ margin-right: 8px;
617
+ }
618
+
619
+ .item-text {
620
+ flex: 1;
621
+ }
622
+
623
+ .confirm-btn {
624
+ margin-left: auto;
625
+ padding: 0 8px;
626
+ }
627
+
628
+ .confirm-btn.hover-btn {
629
+ opacity: 0;
630
+ transition: opacity 0.3s ease;
631
+ }
632
+
633
+ .button-group {
634
+ display: flex;
635
+ gap: 4px; /* 按钮之间的间距 */
636
+ }
637
+
638
+ .list-item:hover .confirm-btn.hover-btn {
639
+ opacity: 1;
640
+ }
641
+
642
+ /* 自定义滚动条样式 */
643
+ .list-wrapper::-webkit-scrollbar {
644
+ width: 6px;
645
+ }
646
+
647
+ .list-wrapper::-webkit-scrollbar-thumb {
648
+ background-color: #d9d9d9;
649
+ border-radius: 3px;
650
+ }
651
+
652
+ .list-wrapper::-webkit-scrollbar-track {
653
+ background-color: #f0f0f0;
654
+ }
655
+
656
+ .hover-active {
657
+ color: white;
658
+ }
659
+
660
+ .list-item.hover-active {
661
+ background-color: rgb(0, 87, 254) !important;
662
+ color: white;
663
+ border: 1px solid black;
664
+ }
665
+
666
+ /* 选中态样式(通过 selectRow 开启) */
667
+ .selected-active { color: white; }
668
+ .list-item.selected-active {
669
+ background-color: #0057FE !important;
670
+ color: white;
671
+ border: none !important;
672
+ }
673
+ .list-item.selected-active .confirm-btn,
674
+ .list-item.selected-active .confirm-btn span,
675
+ .list-item.selected-active .ant-btn,
676
+ .list-item.selected-active .ant-btn > span { color: #ffffff !important; }
677
+ .card-a-col.selected-active {
678
+ background-color: #0057FE !important;
679
+ color: white;
680
+ border: none !important;
681
+ }
682
+ .card-a-col.selected-active .button-a-col,
683
+ .card-a-col.selected-active .button-a-col .ant-btn,
684
+ .card-a-col.selected-active .button-a-col .ant-btn > span { color: #ffffff !important; }
685
+
686
+ .hover-options {
687
+ position: absolute;
688
+ left: 0;
689
+ right: 0;
690
+ top: 100%;
691
+ background: white;
692
+ border: 1px solid #d9d9d9;
693
+ border-radius: 4px;
694
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
695
+ z-index: 1000;
696
+ margin-top: 4px;
697
+ width: 100%;
698
+ box-sizing: border-box;
699
+ pointer-events: auto;
700
+ }
701
+
702
+ .hover-options-content {
703
+ padding: 4px 0;
704
+ display: flex;
705
+ flex-direction: column;
706
+ width: 100%;
707
+ }
708
+
709
+ .option-item {
710
+ padding: 8px 12px;
711
+ cursor: pointer;
712
+ transition: all 0.3s ease;
713
+ color: #333;
714
+ font-size: 14px;
715
+ display: flex;
716
+ align-items: center;
717
+ }
718
+
719
+ .option-item:hover {
720
+ background-color: #f5f5f5;
721
+ color: #1890ff;
722
+ }
723
+
724
+ .option-item:active {
725
+ background-color: #e6f7ff;
726
+ }
727
+
728
+ .demo-loading-container {
729
+ position: absolute;
730
+ bottom: 40px;
731
+ width: 100%;
732
+ text-align: center;
733
+ }
734
+
735
+ .demo-infinite-container{
736
+ overflow-x: hidden;
737
+ overflow-y: auto;
738
+ height: 85vh;
739
+ }
740
+ .card-row{
741
+ height: 100%;
742
+ width: 100%;
743
+ border-radius: 6px;
744
+ padding: 6px;
745
+ }
746
+ .id-a-col{
747
+ font-size: 22px;
748
+ font-weight: 700;
749
+ display: flex;
750
+ flex-direction: column;
751
+ align-items: center;
752
+ justify-content: center;
753
+ gap: 4px;
754
+ }
755
+ .id-a-col-2{
756
+ padding: 8px;
757
+ height: 100%;
758
+ overflow: hidden;
759
+ display: flex;
760
+ flex-direction: column;
761
+ justify-content: space-between;
762
+ }
763
+ .describe-list-a-col{
764
+ display: block;
765
+ font-family: Source Han Sans;
766
+ font-size: 16px;
767
+ font-weight: normal;
768
+ line-height: normal;
769
+ overflow: hidden;
770
+ text-overflow: ellipsis;
771
+ white-space: nowrap;
772
+ max-width: 100%;
773
+ }
774
+ .name{
775
+ font-family: Source Han Sans;
776
+ font-size: 22px;
777
+ font-weight: bold;
778
+ line-height: normal;
779
+ }
780
+ .component-a-col{
781
+ display: flex;
782
+ align-items: center;
783
+ overflow: hidden;
784
+ }
785
+ .label-text{
786
+ overflow: hidden;
787
+ text-overflow: ellipsis;
788
+ white-space: nowrap;
789
+ max-width: 120px;
790
+ display: inline-block;
791
+ }
792
+ .gender-icon{
793
+ margin-top: 2px;
794
+ }
795
+ .gender-icon .male{ color: #2f54eb; font-size: 14px; }
796
+ .gender-icon .female{ color: #eb2f96; font-size: 14px; }
797
+ .gender-img{ width: 100%; height: 100%; opacity: 1; display: inline-block; }
798
+ .title-row{
799
+ display: flex;
800
+ align-items: center;
801
+ justify-content: space-between;
802
+ gap: 8px;
803
+ }
804
+ /* 标题文本占满剩余空间,确保箭头贴右 */
805
+ .title-row .describe-list-a-col{ flex: 1; }
806
+ .title-actions{ display: inline-flex; align-items: center; gap: 6px; }
807
+ .title-select-label{
808
+ font-family: Source Han Sans;
809
+ font-size: 16px;
810
+ font-weight: normal;
811
+ line-height: normal;
812
+ color: #595959;
813
+ }
814
+ .title-select{ min-width: 96px; }
815
+ .arrow-btn{ display: inline-flex; align-items: center; color: #8C8C8C; }
816
+ .arrow-btn .anticon{ font-size: 18px; }
817
+ /* 放大下拉箭头的 svg 尺寸以符合 UI(scoped 深度选择) */
818
+ ::v-deep .arrow-btn .anticon svg{ width: 2em; height: 2em; }
819
+ .button-a-col{
820
+ position: absolute;
821
+ top: 245px;
822
+ left: 225px;
823
+ }
824
+ .card-a-col{
825
+ background-color: rgba(247, 249, 252);
826
+ height: 297px;
827
+ width: auto;
828
+ border-radius: 6px;
829
+ border: 1px solid #E5E9F0;
830
+ overflow: hidden;
831
+ position: relative;
832
+ box-sizing: border-box;
833
+ margin: 10px;
834
+ }
835
+
836
+ /* 新列表样式 */
837
+ .x-list-enableNewListStyle {
838
+ /* 重写 list-wrapper 样式,去除 padding-right、max-height 和滚动条 */
839
+ &.x-list-wrapper.list-wrapper {
840
+ padding-right: 0 !important;
841
+ max-height: none !important;
842
+ overflow: visible !important;
843
+ overflow-y: visible !important;
844
+ }
845
+
846
+ .list-item {
847
+ width: 100%; /* 正常情况下占据整个宽度 */
848
+ height: 35px;
849
+ border-radius: 6px;
850
+ opacity: 1;
851
+ background: #F4F4F4;
852
+ padding: 8px 12px;
853
+ margin-bottom: 8px !important;
854
+ display: flex;
855
+ align-items: center;
856
+ justify-content: space-between;
857
+ box-sizing: border-box;
858
+ transition: width 0.3s ease; /* 添加宽度过渡效果 */
859
+ }
860
+
861
+ /* 悬停时恢复固定宽度 */
862
+ .list-item:hover {
863
+ width: 234px; /* 悬停时恢复固定宽度 */
864
+ }
865
+
866
+ .item-text {
867
+ height: 20px;
868
+ opacity: 1;
869
+ font-family: Source Han Sans;
870
+ font-size: 14px;
871
+ font-weight: normal;
872
+ line-height: normal;
873
+ letter-spacing: 0em;
874
+ font-feature-settings: "kern" on;
875
+ color: #313131;
876
+ flex: 1; /* 占据剩余空间 */
877
+ margin-right: 1px; /* 与按钮组保持8px间距 */
878
+ transition: width 0.3s ease; /* 只对宽度进行过渡,避免溢出控制闪烁 */
879
+ white-space: nowrap; /* 不换行 */
880
+ overflow: visible; /* 正常情况下显示全部内容 */
881
+ text-overflow: initial; /* 正常情况下不显示省略号 */
882
+ }
883
+
884
+ /* 悬停时隐藏超出部分 - 立即生效,不添加过渡 */
885
+ .list-item:hover .item-text {
886
+ overflow: hidden; /* 悬停时隐藏溢出内容 */
887
+ text-overflow: ellipsis; /* 悬停时显示省略号 */
888
+ transition: none; /* 溢出控制立即生效,避免闪烁 */
889
+ }
890
+
891
+ .button-group {
892
+ gap: 4px; /* 按钮之间的间距 */
893
+ flex-shrink: 0; /* 防止按钮组被压缩 */
894
+ }
895
+
896
+ .confirm-btn {
897
+ height: 20px;
898
+ opacity: 0; /* 默认隐藏 */
899
+ transition: opacity 0.3s ease; /* 添加过渡效果 */
900
+ font-family: Source Han Sans;
901
+ font-size: 14px;
902
+ font-weight: normal;
903
+ line-height: normal;
904
+ letter-spacing: 0em;
905
+ font-feature-settings: "kern" on;
906
+ /* 移除固定颜色,继承默认颜色 */
907
+ padding: 0; /* 清除内边距 */
908
+ margin-left: 0; /* 移除左边距,使用 gap 控制间距 */
909
+
910
+ span {
911
+ height: 20px;
912
+ opacity: 1;
913
+ font-family: Source Han Sans;
914
+ font-size: 14px;
915
+ font-weight: normal;
916
+ line-height: normal;
917
+ letter-spacing: 0em;
918
+ font-feature-settings: "kern" on;
919
+ /* 移除固定颜色,继承默认颜色 */
920
+ }
921
+ }
922
+ /* 悬浮时显示按钮 */
923
+ .list-item:hover .confirm-btn {
924
+ opacity: 1;
925
+ }
926
+ /* 选中状态字体颜色 - 使用白色,与全局样式保持一致 */
927
+ .list-item.selected-active {
928
+ color: white !important; /* 使用白色文本 */
929
+ }
930
+ .list-item.selected-active .item-text {
931
+ color: white !important; /* 确保文本使用白色 */
932
+ }
933
+ .list-item.selected-active .confirm-btn,
934
+ .list-item.selected-active .confirm-btn span {
935
+ color: #ffffff !important; /* 按钮使用白色 */
936
+ }
937
+ }
938
+ </style>