vue2-client 1.14.58 → 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.
- package/docs/Logic/345/207/275/346/225/260/344/275/277/347/224/250/347/233/270/345/205/263.md +0 -1
- package/docs//345/207/275/346/225/260/344/275/277/347/224/250/347/233/270/345/205/263.md +1 -2
- package/package.json +1 -1
- package/src/base-client/components/common/XReportGrid/XReport.vue +2 -0
- package/src/base-client/components/common/XTab/XTab.vue +1 -1
- package/src/base-client/components/his/XHisEditor/XHisEditor.vue +122 -16
- package/src/base-client/components/his/XTextCard/XTextCard.vue +207 -207
- package/src/base-client/components/his/XTitle/README.md +5 -8
- package/src/base-client/components/his/XTreeRows/TreeNode.vue +100 -100
- package/src/base-client/components/his/XTreeRows/XTreeRows.vue +197 -197
- package/src/base-client/components/his/threeTestOrders/editor.vue +111 -111
- package/src/base-client/components/his/threeTestOrders/textBox.vue +463 -463
- package/src/pages/ReportGrid/index.vue +5 -1
- package/src/router/async/router.map.js +5 -4
- package/vue.config.js +1 -1
- package/.history/src/base-client/components/common/AddressSearchCombobox/AddressSearchCombobox_20250527173925.vue +0 -509
- package/.history/src/base-client/components/common/AddressSearchCombobox/AddressSearchCombobox_20250527174316.vue +0 -524
- package/.history/src/base-client/components/common/AddressSearchCombobox/AddressSearchCombobox_20250527174419.vue +0 -524
- package/.history/src/base-client/components/common/AddressSearchCombobox/AddressSearchCombobox_20250527174422.vue +0 -524
- package/.history/src/base-client/components/common/XForm/XFormItem_20250508134122.vue +0 -1320
- package/.history/src/base-client/components/common/XForm/XFormItem_20250527171604.vue +0 -1332
- package/.history/src/base-client/components/common/XForm/XFormItem_20250527171613.vue +0 -1331
- package/.history/src/base-client/components/common/XForm/XFormItem_20250527171703.vue +0 -1331
- package/.history/src/base-client/components/common/XForm/XFormItem_20250527171720.vue +0 -1331
- package/.history/src/base-client/components/common/XForm/XFormItem_20250527174327.vue +0 -1339
- package/Users/objecrt/af-vue2-client/src/base-client/components/his/XShiftSchedule/XShiftSchedule.vue +0 -36
- package/src/base-client/components/TreeList/TreeList.vue +0 -91
- package/src/base-client/components/TreeList/TreeNode.vue +0 -81
- package/src/base-client/components/common/XCardSet/XTiltle.vue +0 -191
package/docs/Logic/345/207/275/346/225/260/344/275/277/347/224/250/347/233/270/345/205/263.md
CHANGED
|
@@ -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
|
-
|
|
64
|
-
- "pageMaxSize": (int) num,
|
|
63
|
+
|
|
65
64
|
# x-report 插槽 使用说明
|
|
66
65
|
|
|
67
66
|
- init(configName,configData) 配置名称 / 报表数据
|
package/package.json
CHANGED
|
@@ -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
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
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
|
-
}
|
|
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
|
|
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
|