vue2-client 1.14.59 → 1.14.60

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 (28) hide show
  1. package/docs/Logic/345/207/275/346/225/260/344/275/277/347/224/250/347/233/270/345/205/263.md +0 -1
  2. package/docs//345/207/275/346/225/260/344/275/277/347/224/250/347/233/270/345/205/263.md +1 -2
  3. package/package.json +1 -1
  4. package/src/base-client/components/common/XReportGrid/XReport.vue +2 -0
  5. package/src/base-client/components/his/XHisEditor/XHisEditor.vue +122 -16
  6. package/src/base-client/components/his/XTextCard/XTextCard.vue +207 -207
  7. package/src/base-client/components/his/XTitle/README.md +5 -8
  8. package/src/base-client/components/his/XTreeRows/TreeNode.vue +100 -100
  9. package/src/base-client/components/his/XTreeRows/XTreeRows.vue +197 -197
  10. package/src/base-client/components/his/threeTestOrders/editor.vue +111 -111
  11. package/src/base-client/components/his/threeTestOrders/textBox.vue +463 -463
  12. package/src/pages/ReportGrid/index.vue +5 -1
  13. package/src/router/async/router.map.js +5 -4
  14. package/vue.config.js +1 -1
  15. package/.history/src/base-client/components/common/AddressSearchCombobox/AddressSearchCombobox_20250527173925.vue +0 -509
  16. package/.history/src/base-client/components/common/AddressSearchCombobox/AddressSearchCombobox_20250527174316.vue +0 -524
  17. package/.history/src/base-client/components/common/AddressSearchCombobox/AddressSearchCombobox_20250527174419.vue +0 -524
  18. package/.history/src/base-client/components/common/AddressSearchCombobox/AddressSearchCombobox_20250527174422.vue +0 -524
  19. package/.history/src/base-client/components/common/XForm/XFormItem_20250508134122.vue +0 -1320
  20. package/.history/src/base-client/components/common/XForm/XFormItem_20250527171604.vue +0 -1332
  21. package/.history/src/base-client/components/common/XForm/XFormItem_20250527171613.vue +0 -1331
  22. package/.history/src/base-client/components/common/XForm/XFormItem_20250527171703.vue +0 -1331
  23. package/.history/src/base-client/components/common/XForm/XFormItem_20250527171720.vue +0 -1331
  24. package/.history/src/base-client/components/common/XForm/XFormItem_20250527174327.vue +0 -1339
  25. package/Users/objecrt/af-vue2-client/src/base-client/components/his/XShiftSchedule/XShiftSchedule.vue +0 -36
  26. package/src/base-client/components/TreeList/TreeList.vue +0 -91
  27. package/src/base-client/components/TreeList/TreeNode.vue +0 -81
  28. package/src/base-client/components/common/XCardSet/XTiltle.vue +0 -191
@@ -11,7 +11,6 @@
11
11
  - ENV 对应 一个 org.json.JSONObject {tenantName:"租户名称",orgName:"分公司名称",applicationName:"应用名称",dbType:"数据库类型"}
12
12
  - logic 对应 LogicService 类,其中有方法
13
13
  * logic.run(logicName,param) 执行logic / logicName 执行的业务逻辑名称,param 参数 返回 org.json.JSONObject
14
- * logic.remoteRun("服务名","logicName", "param"")
15
14
  - sql 对应 [SqlService]() 类,其中有方法
16
15
  * sql.query(sql别名 string,sql参数 string) 执行已经注册的sql 返回 org.json.JSONArray
17
16
  * sql.query(sql别名 string,sql参数 string,页数 int,每页行数 int) 执行已经注册的sql 返回 org.json.JSONArray
@@ -60,8 +60,7 @@ this.openDialog('xxx', 5, {}, {}, {})
60
60
  afterDelete( res (删除接口返回数据)) 删除后触发
61
61
  action(record (当前记录), id (当前记录主键), actionType (操作类型)) 操作按钮触发
62
62
  - expandedGrid:"栅格名"
63
- - json配置相关
64
- - "pageMaxSize": (int) num,
63
+
65
64
  # x-report 插槽 使用说明
66
65
 
67
66
  - init(configName,configData) 配置名称 / 报表数据
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue2-client",
3
- "version": "1.14.59",
3
+ "version": "1.14.60",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "serve": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve --no-eslint",
@@ -249,6 +249,8 @@ export default {
249
249
  },
250
250
  methods: {
251
251
  findComponentByName (instance, componentName, maxDepth, findType) {
252
+ findType = findType || 'children'
253
+ maxDepth = maxDepth || 50
252
254
  // 基础判断:如果实例不存在或者已经超过最大深度,返回null
253
255
  if (!instance || maxDepth <= 0) {
254
256
  return null
@@ -86,7 +86,8 @@
86
86
  </template>
87
87
 
88
88
  <script>
89
-
89
+ import html2canvas from 'html2canvas'
90
+ import jsPDF from 'jspdf'
90
91
  import { runLogic } from '@vue2-client/services/api/common'
91
92
  import { initDiagnosisDropdown } from './diagnosisAutocomplete'
92
93
 
@@ -387,31 +388,136 @@ export default {
387
388
  })
388
389
  }
389
390
  },
390
- // 保存文档
391
- save () {
391
+ // 修改 save 方法
392
+ async save() {
392
393
  // 验证必须输入项
393
394
  if (this.editorRef.validate()) {
394
- // 获取HTML文档和结构化数据(JSON)
395
- const data = {
396
- doc: this.editorRef.getHtml(),
397
- dataObject: this.editorRef.getBindObject(),
398
- dataMode: this.dataMode,
399
- resId: this.resId,
400
- modifyResModel: this.modifyResModel,
401
- logicExtraParams: this.logicExtraParams
402
- }
403
- // 保存HTML文档和结构化数据到后端服务
404
- runLogic(this.saveDataLogicName, data, this.serviceName).then(res => {
395
+ try {
396
+ // 1. 先生成 PDF
397
+ const pdfBlob = await this.generatePDF()
398
+
399
+ // 2. 获取HTML文档和结构化数据(JSON)
400
+ const data = {
401
+ doc: this.editorRef.getHtml(),
402
+ dataObject: this.editorRef.getBindObject(),
403
+ dataMode: this.dataMode,
404
+ resId: this.resId,
405
+ modifyResModel: this.modifyResModel,
406
+ logicExtraParams: this.logicExtraParams,
407
+ // 添加 PDF 数据
408
+ pdfData: pdfBlob
409
+ }
410
+
411
+ // 3. 保存到后端
412
+ const res = await runLogic(this.saveDataLogicName, data, this.serviceName)
413
+
405
414
  this.$message.success('保存成功')
406
415
  this.changeRes(res.currResData.id)
407
416
  this.$emit('saveafter', data.dataObject)
408
- }).finally(() => {
417
+ } catch (error) {
418
+ console.error('保存失败:', error)
419
+ this.$message.error('保存失败,请重试')
420
+ } finally {
409
421
  this.resDataModalVisible = false
410
- })
422
+ }
411
423
  } else {
412
424
  this.$message.error('请检查未填写的项目')
413
425
  }
414
426
  },
427
+ // 修改 generatePDF 方法,返回 PDF Blob
428
+ async generatePDF() {
429
+ // 显示加载提示
430
+ this.$message.loading('正在生成 PDF...', 0)
431
+
432
+ try {
433
+ const iframe = document.getElementById('x-editor')
434
+ const iframeDocument = iframe.contentDocument || iframe.contentWindow.document
435
+
436
+ // 添加自定义样式
437
+ const style = iframeDocument.createElement('style')
438
+ style.textContent = `
439
+ body {
440
+ font-family: Arial, sans-serif;
441
+ line-height: 1.5;
442
+ color: #333;
443
+ padding: 20px;
444
+ }
445
+ h1, h2, h3 {
446
+ color: #000;
447
+ margin-bottom: 15px;
448
+ }
449
+ table {
450
+ border-collapse: collapse;
451
+ width: 100%;
452
+ margin-bottom: 20px;
453
+ }
454
+ th, td {
455
+ border: 1px solid #ddd;
456
+ padding: 8px;
457
+ text-align: left;
458
+ }
459
+ th {
460
+ background-color: #f5f5f5;
461
+ }
462
+ img {
463
+ max-width: 100%;
464
+ height: auto;
465
+ }
466
+ `
467
+ iframeDocument.head.appendChild(style)
468
+
469
+ const canvas = await html2canvas(iframeDocument.body, {
470
+ scale: 2,
471
+ useCORS: true,
472
+ logging: false,
473
+ backgroundColor: '#ffffff',
474
+ windowWidth: iframeDocument.documentElement.scrollWidth,
475
+ windowHeight: iframeDocument.documentElement.scrollHeight
476
+ })
477
+
478
+ const pdf = new jsPDF({
479
+ orientation: 'portrait',
480
+ unit: 'mm',
481
+ format: 'a4'
482
+ })
483
+
484
+ const imgData = canvas.toDataURL('image/png')
485
+ const imgWidth = 210
486
+ const imgHeight = (canvas.height * imgWidth) / canvas.width
487
+
488
+ const pageHeight = 297
489
+ let heightLeft = imgHeight
490
+ let position = 0
491
+
492
+ pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight)
493
+
494
+ while (heightLeft > 0) {
495
+ position = heightLeft - pageHeight
496
+ pdf.addPage()
497
+ pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight)
498
+ heightLeft -= pageHeight
499
+ }
500
+
501
+ // 生成 PDF 的 Blob 数据
502
+ const pdfBlob = pdf.output('blob')
503
+
504
+ // 预览 PDF
505
+ const pdfUrl = URL.createObjectURL(pdfBlob)
506
+ window.open(pdfUrl, '_blank')
507
+
508
+ // 关闭加载提示
509
+ this.$message.destroy()
510
+ this.$message.success('PDF 生成成功')
511
+
512
+ // 返回 PDF Blob 数据
513
+ return pdfBlob
514
+ } catch (error) {
515
+ console.error('PDF 生成失败:', error)
516
+ this.$message.destroy()
517
+ this.$message.error('PDF 生成失败,请重试')
518
+ throw error // 抛出错误,让 save 方法捕获
519
+ }
520
+ },
415
521
  // 打印文档
416
522
  print () {
417
523
  this.editorRef.execCommand('print')
@@ -1,207 +1,207 @@
1
- <template>
2
- <div>
3
- <div class="text-card">
4
- <div
5
- v-for="(item, index) in displayItems"
6
- :key="index"
7
- class="text-item"
8
- @click="handleItemClick(index, item.id)"
9
- @contextmenu.prevent="handleContextMenu(index, item.id)">
10
- <div class="text-content" :class="{ 'is-empty': !item.content }">
11
- {{ item.content || '+' }}
12
- </div>
13
- </div>
14
- <!-- 编辑弹出框 -->
15
- <div
16
- v-if="showEdit"
17
- class="edit-overlay"
18
- @click.self="handleOverlayClick">
19
- <div class="edit-card">
20
- <a-textarea
21
- v-model="editingContent"
22
- :autoSize="{ minRows: 3 }"
23
- @keyup.enter="handleSave"
24
- ref="textarea"/>
25
- </div>
26
- </div>
27
- <!-- 删除确认弹框 -->
28
- <a-modal
29
- v-model="showDeleteModal"
30
- title="确认删除"
31
- okText="确认"
32
- cancelText="取消"
33
- @ok="handleDeleteConfirm">
34
- <p>确定要删除这条内容吗?</p>
35
- </a-modal>
36
- </div>
37
- </div>
38
- </template>
39
-
40
- <script>
41
- import { runLogic } from '@vue2-client/services/api/common'
42
-
43
- export default {
44
- name: 'XTextCard',
45
- props: {
46
- // logic配置名,要求返回一个数组[{ id: , content: }]
47
- queryParamsName: {
48
- type: String,
49
- default: 'memorandumLOGIC'
50
- },
51
- queryParams: {
52
- type: Object,
53
- default: () => { return {} }
54
- },
55
- // 请求参数
56
- parameter: {
57
- type: Object,
58
- default: () => { return {} }
59
- }
60
- },
61
- data () {
62
- return {
63
- localItems: [], // 本地数据
64
- showEdit: false, // 是否显示编辑框
65
- editingIndex: -1, // 当前编辑的索引
66
- editingContent: '', // 编辑框的内容
67
- showDeleteModal: false, // 是否显示删除确认框
68
- deleteIndex: -1, // 要删除的项目索引
69
- ID: 0
70
- }
71
- },
72
- computed: {
73
- // 显示的列表,始终保持一个空行
74
- displayItems () {
75
- const items = [...this.localItems]
76
- // 如果最后一项不是空的,添加一个空项
77
- if (!items.length || items[items.length - 1].content) {
78
- items.push({ content: '' })
79
- }
80
- return items
81
- }
82
- },
83
- methods: {
84
- // 点击项目
85
- handleItemClick (index, id) {
86
- this.ID = id
87
- this.editingIndex = index
88
- this.editingContent = this.displayItems[index].content
89
- this.showEdit = true
90
- this.$nextTick(() => {
91
- this.$refs.textarea?.focus()
92
- })
93
- },
94
- // 点击遮罩层保存
95
- handleOverlayClick () {
96
- this.handleSave()
97
- },
98
- // 保存内容
99
- handleSave () {
100
- if (this.editingContent.trim()) {
101
- if (this.editingIndex === this.localItems.length) {
102
- // 如果是在最后一个空行添加,push新内容
103
- this.localItems.push({ content: this.editingContent.trim() })
104
- } else {
105
- // 否则更新现有内容
106
- this.localItems[this.editingIndex].content = this.editingContent.trim()
107
- }
108
- const addData = { data: this.editingContent.trim(), ID: this.ID }
109
- // 触发更新事件
110
- this.$emit('add', addData)
111
- }
112
- this.showEdit = false
113
- this.editingIndex = -1
114
- this.editingContent = ''
115
- },
116
- // 初始化数据
117
- async initData (data, parameter) {
118
- // 从配置中获取数据
119
- const resData = await runLogic(data, parameter, 'af-his')
120
- this.localItems = resData
121
- return resData
122
- },
123
- // 处理右键菜单
124
- handleContextMenu (index, id) {
125
- // 如果是最后一个空行,不显示删除框
126
- if (index === this.localItems.length) {
127
- return
128
- }
129
- this.ID = id
130
- this.deleteIndex = index
131
- this.showDeleteModal = true
132
- },
133
- // 确认删除
134
- handleDeleteConfirm () {
135
- if (this.deleteIndex > -1) {
136
- this.localItems.splice(this.deleteIndex, 1)
137
- const deleteData = { data: [...this.localItems][this.deleteIndex], ID: this.ID }
138
- this.$emit('deleteData', deleteData)
139
- this.deleteIndex = -1
140
- }
141
- this.showDeleteModal = false
142
- }
143
- },
144
- watch: {
145
- queryParamsName: {
146
- immediate: true,
147
- handler (newVal) {
148
- this.initData(newVal, this.parameter)
149
- },
150
- deep: true
151
- }
152
- }
153
- }
154
- </script>
155
-
156
- <style scoped lang="less">
157
- .text-card {
158
- position: relative;
159
- width: 100%;
160
- .text-item {
161
- padding: 8px 12px;
162
- border-bottom: 1px solid #f0f0f0;
163
- cursor: pointer;
164
- transition: all 0.3s;
165
- user-select: none;
166
-
167
- &:hover {
168
- background-color: #f5f5f5;
169
- }
170
-
171
- .text-content {
172
- white-space: nowrap;
173
- overflow: hidden;
174
- text-overflow: ellipsis;
175
- line-height: 1.5;
176
-
177
- &.is-empty {
178
- color: #5D5C5C;
179
- font-weight: 400;
180
- }
181
- }
182
- }
183
- .edit-overlay {
184
- position: fixed;
185
- top: 0;
186
- left: 0;
187
- right: 0;
188
- bottom: 0;
189
- background-color: rgba(0, 0, 0, 0.45);
190
- z-index: 1000;
191
- display: flex;
192
- align-items: center;
193
- justify-content: center;
194
- .edit-card {
195
- background: white;
196
- padding: 16px;
197
- border-radius: 8px;
198
- width: 90%;
199
- max-width: 500px;
200
- box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.12);
201
- .ant-input {
202
- width: 100%;
203
- }
204
- }
205
- }
206
- }
207
- </style>
1
+ <template>
2
+ <div>
3
+ <div class="text-card">
4
+ <div
5
+ v-for="(item, index) in displayItems"
6
+ :key="index"
7
+ class="text-item"
8
+ @click="handleItemClick(index, item.id)"
9
+ @contextmenu.prevent="handleContextMenu(index, item.id)">
10
+ <div class="text-content" :class="{ 'is-empty': !item.content }">
11
+ {{ item.content || '+' }}
12
+ </div>
13
+ </div>
14
+ <!-- 编辑弹出框 -->
15
+ <div
16
+ v-if="showEdit"
17
+ class="edit-overlay"
18
+ @click.self="handleOverlayClick">
19
+ <div class="edit-card">
20
+ <a-textarea
21
+ v-model="editingContent"
22
+ :autoSize="{ minRows: 3 }"
23
+ @keyup.enter="handleSave"
24
+ ref="textarea"/>
25
+ </div>
26
+ </div>
27
+ <!-- 删除确认弹框 -->
28
+ <a-modal
29
+ v-model="showDeleteModal"
30
+ title="确认删除"
31
+ okText="确认"
32
+ cancelText="取消"
33
+ @ok="handleDeleteConfirm">
34
+ <p>确定要删除这条内容吗?</p>
35
+ </a-modal>
36
+ </div>
37
+ </div>
38
+ </template>
39
+
40
+ <script>
41
+ import { runLogic } from '@vue2-client/services/api/common'
42
+
43
+ export default {
44
+ name: 'XTextCard',
45
+ props: {
46
+ // logic配置名,要求返回一个数组[{ id: , content: }]
47
+ queryParamsName: {
48
+ type: String,
49
+ default: 'memorandumLOGIC'
50
+ },
51
+ queryParams: {
52
+ type: Object,
53
+ default: () => { return {} }
54
+ },
55
+ // 请求参数
56
+ parameter: {
57
+ type: Object,
58
+ default: () => { return {} }
59
+ }
60
+ },
61
+ data () {
62
+ return {
63
+ localItems: [], // 本地数据
64
+ showEdit: false, // 是否显示编辑框
65
+ editingIndex: -1, // 当前编辑的索引
66
+ editingContent: '', // 编辑框的内容
67
+ showDeleteModal: false, // 是否显示删除确认框
68
+ deleteIndex: -1, // 要删除的项目索引
69
+ ID: 0
70
+ }
71
+ },
72
+ computed: {
73
+ // 显示的列表,始终保持一个空行
74
+ displayItems () {
75
+ const items = [...this.localItems]
76
+ // 如果最后一项不是空的,添加一个空项
77
+ if (!items.length || items[items.length - 1].content) {
78
+ items.push({ content: '' })
79
+ }
80
+ return items
81
+ }
82
+ },
83
+ methods: {
84
+ // 点击项目
85
+ handleItemClick (index, id) {
86
+ this.ID = id
87
+ this.editingIndex = index
88
+ this.editingContent = this.displayItems[index].content
89
+ this.showEdit = true
90
+ this.$nextTick(() => {
91
+ this.$refs.textarea?.focus()
92
+ })
93
+ },
94
+ // 点击遮罩层保存
95
+ handleOverlayClick () {
96
+ this.handleSave()
97
+ },
98
+ // 保存内容
99
+ handleSave () {
100
+ if (this.editingContent.trim()) {
101
+ if (this.editingIndex === this.localItems.length) {
102
+ // 如果是在最后一个空行添加,push新内容
103
+ this.localItems.push({ content: this.editingContent.trim() })
104
+ } else {
105
+ // 否则更新现有内容
106
+ this.localItems[this.editingIndex].content = this.editingContent.trim()
107
+ }
108
+ const addData = { data: this.editingContent.trim(), ID: this.ID }
109
+ // 触发更新事件
110
+ this.$emit('add', addData)
111
+ }
112
+ this.showEdit = false
113
+ this.editingIndex = -1
114
+ this.editingContent = ''
115
+ },
116
+ // 初始化数据
117
+ async initData (data, parameter) {
118
+ // 从配置中获取数据
119
+ const resData = await runLogic(data, parameter, 'af-his')
120
+ this.localItems = resData
121
+ return resData
122
+ },
123
+ // 处理右键菜单
124
+ handleContextMenu (index, id) {
125
+ // 如果是最后一个空行,不显示删除框
126
+ if (index === this.localItems.length) {
127
+ return
128
+ }
129
+ this.ID = id
130
+ this.deleteIndex = index
131
+ this.showDeleteModal = true
132
+ },
133
+ // 确认删除
134
+ handleDeleteConfirm () {
135
+ if (this.deleteIndex > -1) {
136
+ this.localItems.splice(this.deleteIndex, 1)
137
+ const deleteData = { data: [...this.localItems][this.deleteIndex], ID: this.ID }
138
+ this.$emit('deleteData', deleteData)
139
+ this.deleteIndex = -1
140
+ }
141
+ this.showDeleteModal = false
142
+ }
143
+ },
144
+ watch: {
145
+ queryParamsName: {
146
+ immediate: true,
147
+ handler (newVal) {
148
+ this.initData(newVal, this.parameter)
149
+ },
150
+ deep: true
151
+ }
152
+ }
153
+ }
154
+ </script>
155
+
156
+ <style scoped lang="less">
157
+ .text-card {
158
+ position: relative;
159
+ width: 100%;
160
+ .text-item {
161
+ padding: 8px 12px;
162
+ border-bottom: 1px solid #f0f0f0;
163
+ cursor: pointer;
164
+ transition: all 0.3s;
165
+ user-select: none;
166
+
167
+ &:hover {
168
+ background-color: #f5f5f5;
169
+ }
170
+
171
+ .text-content {
172
+ white-space: nowrap;
173
+ overflow: hidden;
174
+ text-overflow: ellipsis;
175
+ line-height: 1.5;
176
+
177
+ &.is-empty {
178
+ color: #5D5C5C;
179
+ font-weight: 400;
180
+ }
181
+ }
182
+ }
183
+ .edit-overlay {
184
+ position: fixed;
185
+ top: 0;
186
+ left: 0;
187
+ right: 0;
188
+ bottom: 0;
189
+ background-color: rgba(0, 0, 0, 0.45);
190
+ z-index: 1000;
191
+ display: flex;
192
+ align-items: center;
193
+ justify-content: center;
194
+ .edit-card {
195
+ background: white;
196
+ padding: 16px;
197
+ border-radius: 8px;
198
+ width: 90%;
199
+ max-width: 500px;
200
+ box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.12);
201
+ .ant-input {
202
+ width: 100%;
203
+ }
204
+ }
205
+ }
206
+ }
207
+ </style>
@@ -22,7 +22,7 @@ XTitle 是一个多功能的标题组件,可以显示标题文本或按钮,
22
22
 
23
23
  ### 配置参数格式
24
24
 
25
- XTitle 组件通过一个字符串参数进行配置
25
+ XTitle 组件通过一个字符串参数进行配置
26
26
 
27
27
  各部分说明:
28
28
 
@@ -37,6 +37,9 @@ XTitle 组件通过一个字符串参数进行配置
37
37
 
38
38
  ### 1. 基本标题
39
39
 
40
+ ```vue
41
+ <x-title query-params-name="患者信息"></x-title>
42
+ ```
40
43
  ```vue
41
44
  <x-title query-params-name="患者信息-title"></x-title>
42
45
  ```
@@ -44,7 +47,7 @@ XTitle 组件通过一个字符串参数进行配置
44
47
  ### 2. 带下划线的标题
45
48
 
46
49
  ```vue
47
- <x-title query-params-name="患者信息-title--line"></x-title>
50
+ <x-title query-params-name="患者信息-title-line"></x-title>
48
51
  ```
49
52
 
50
53
  ### 3. 自定义下划线颜色和宽度
@@ -53,12 +56,6 @@ XTitle 组件通过一个字符串参数进行配置
53
56
  <x-title query-params-name="患者信息-title--line-red-800"></x-title>
54
57
  ```
55
58
 
56
- ### 4. 带点击事件的标题
57
-
58
- ```vue
59
- <x-title query-params-name="患者信息-title-showPatient-line" @showPatient="handleShowPatient"></x-title>
60
- ```
61
-
62
59
  ### 5. 按钮模式
63
60
 
64
61
  ```vue