vue2-client 1.22.3 → 1.22.5

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 (90) hide show
  1. package/.env.his +19 -19
  2. package/.idea/.name +1 -0
  3. package/.idea/MarsCodeWorkspaceAppSettings.xml +8 -0
  4. package/.idea/deployment.xml +14 -0
  5. package/.idea/gradle.xml +7 -0
  6. package/.idea/inspectionProfiles/Project_Default.xml +6 -0
  7. package/.idea/libraries/contour_plot.xml +9 -0
  8. package/.idea/material_theme_project_new.xml +18 -0
  9. package/.idea/misc.xml +87 -5
  10. package/package.json +1 -1
  11. package/src/base-client/components/common/HIS/HForm/HForm.vue +1186 -1186
  12. package/src/base-client/components/common/XMarkdownViewer/demo.vue +102 -102
  13. package/src/base-client/components/his/HAi/HAi.vue +1177 -1177
  14. package/src/base-client/components/his/XTransfer/index.md +327 -327
  15. package/src/base-client/plugins/GetLoginInfoService.js +4 -4
  16. package/src/pages/login/Login.vue +9 -7
  17. package/src/pages/login/LoginV3.vue +9 -7
  18. package/src/utils/login.js +8 -19
  19. package/.history/.eslintrc_20260521171150.js +0 -74
  20. package/.history/.eslintrc_20260521171213.js +0 -74
  21. package/.history/src/base-client/components/common/HIS/HAddNativeForm/HAddNativeForm_20260601154443.vue +0 -726
  22. package/.history/src/base-client/components/common/HIS/HAddNativeForm/HAddNativeForm_20260601154700.vue +0 -478
  23. package/.history/src/base-client/components/common/HIS/HButtons/HButtons_20260512175435.vue +0 -706
  24. package/.history/src/base-client/components/common/HIS/HButtons/HButtons_20260512175450.vue +0 -694
  25. package/.history/src/base-client/components/common/HIS/HButtons/HButtons_20260611152602.vue +0 -755
  26. package/.history/src/base-client/components/common/HIS/HForm/HForm_20260513145941.vue +0 -524
  27. package/.history/src/base-client/components/common/HIS/HForm/HForm_20260513153133.vue +0 -731
  28. package/.history/src/base-client/components/common/HIS/HForm/HForm_20260513160316.vue +0 -525
  29. package/.history/src/base-client/components/common/HIS/HForm/HForm_20260601144150.vue +0 -1046
  30. package/.history/src/base-client/components/common/HIS/HFormTable/HFormTable_20260310142713.vue +0 -512
  31. package/.history/src/base-client/components/common/HIS/HFormTable/HFormTable_20260310145118.vue +0 -511
  32. package/.history/src/base-client/components/common/HIS/HFormTable/HFormTable_20260311094834.vue +0 -696
  33. package/.history/src/base-client/components/common/HIS/HFormTable/HFormTable_20260320143028.vue +0 -693
  34. package/.history/src/base-client/components/common/HIS/HFormTable/HFormTable_20260409101450.vue +0 -677
  35. package/.history/src/base-client/components/common/HIS/HTab/HTab_20260508164645.vue +0 -758
  36. package/.history/src/base-client/components/common/HIS/HTab/HTab_20260508164714.vue +0 -693
  37. package/.history/src/base-client/components/common/HIS/HTab/HTab_20260508171651.vue +0 -716
  38. package/.history/src/base-client/components/common/HIS/HTab/HTab_20260509133717.vue +0 -695
  39. package/.history/src/base-client/components/common/HIS/HTab/HTab_20260509171115.vue +0 -664
  40. package/.history/src/base-client/components/common/XAddNativeForm/XAddNativeForm_20260513140637.vue +0 -1455
  41. package/.history/src/base-client/components/common/XAddNativeForm/XAddNativeForm_20260513140935.vue +0 -1441
  42. package/.history/src/base-client/components/common/XAddNativeForm/XAddNativeForm_20260513150818.vue +0 -1441
  43. package/.history/src/base-client/components/common/XAddNativeForm/XAddNativeForm_20260513153119.vue +0 -1442
  44. package/.history/src/base-client/components/common/XAddNativeForm/XAddNativeForm_20260513153126.vue +0 -1486
  45. package/.history/src/base-client/components/common/XForm/XFormItem_20260513140854.vue +0 -1607
  46. package/.history/src/base-client/components/common/XMarkdownViewer/XMarkdownViewer_20260519140403.vue +0 -643
  47. package/.history/src/base-client/components/common/XMarkdownViewer/XMarkdownViewer_20260519140829.vue +0 -628
  48. package/.history/src/base-client/components/common/XMarkdownViewer/demo_20260519142824.vue +0 -104
  49. package/.history/src/base-client/components/common/XMarkdownViewer/demo_20260519143155.vue +0 -102
  50. package/.history/src/base-client/components/common/XReportGrid/XReport_20260309171231.vue +0 -1241
  51. package/.history/src/base-client/components/common/XReportGrid/XReport_20260309171441.vue +0 -1223
  52. package/.history/src/base-client/components/his/HAi/HAi_20260612174826.vue +0 -472
  53. package/.history/src/base-client/components/his/HAi/HAi_20260612175839.vue +0 -538
  54. package/.history/src/base-client/components/his/HAi/HAi_20260615103331.vue +0 -650
  55. package/.history/src/base-client/components/his/XHDescriptions/XHDescriptions_20260424134504.vue +0 -1469
  56. package/.history/src/base-client/components/his/XSidebar/XSidebar_20260610171133.vue +0 -788
  57. package/.history/src/base-client/components/his/XSidebar/XSidebar_20260610171151.vue +0 -780
  58. package/.history/src/base-client/components/his/XTransfer/XTransfer_20260511170841.vue +0 -585
  59. package/.history/src/base-client/components/his/XTransfer/XTransfer_20260511171138.vue +0 -787
  60. package/.history/src/base-client/components/his/XTransfer/XTransfer_20260512141830.vue +0 -739
  61. package/.history/src/components/STable/index_20260409155138.js +0 -806
  62. package/.history/src/components/STable/index_20260409155218.js +0 -814
  63. package/.history/src/expression/core/Expression_20260305164427.js +0 -1371
  64. package/.history/src/expression/core/Expression_20260305170258.js +0 -1358
  65. package/.history/src/expression/core/Program_20260305111830.js +0 -944
  66. package/.history/src/expression/core/Program_20260305112041.js +0 -931
  67. package/.history/src/logic/LogicRunner_20260304154306.js +0 -170
  68. package/.history/src/logic/LogicRunner_20260304155553.js +0 -112
  69. package/.history/src/logic/LogicRunner_20260305105834.js +0 -112
  70. package/.history/src/logic/LogicRunner_20260305112718.js +0 -129
  71. package/.history/src/logic/LogicRunner_20260305182436.js +0 -133
  72. package/.history/src/logic/LogicRunner_20260306151301.js +0 -213
  73. package/.history/src/logic/LogicRunner_20260306152419.js +0 -213
  74. package/.history/src/logic/plugins/common/DateTools_20260305154159.js +0 -61
  75. package/.history/src/logic/plugins/common/DateTools_20260305154217.js +0 -44
  76. package/.history/src/logic/plugins/common/DateTools_20260305161014.js +0 -44
  77. package/.history/src/logic/plugins/common/HttpTools_20260305164352.js +0 -80
  78. package/.history/src/logic/plugins/common/HttpTools_20260305170258.js +0 -75
  79. package/.history/src/logic/plugins/common/HttpTools_20260305171634.js +0 -75
  80. package/.history/src/logic/plugins/common/HttpTools_20260306152419.js +0 -72
  81. package/.history/src/services/api/restTools_20260427142149.js +0 -245
  82. package/.history/src/services/api/restTools_20260427142853.js +0 -230
  83. package/.history/src/services/api/restTools_20260519135558.js +0 -230
  84. package/.history/src/services/api/restTools_20260519140825.js +0 -230
  85. package/.history/src/services/api/restTools_20260519151223.js +0 -230
  86. package/.history/src/utils/indexedDB_20260306150918.js +0 -593
  87. package/.history/src/utils/indexedDB_20260306151301.js +0 -586
  88. package/.idea/codeStyles/Project.xml +0 -62
  89. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  90. package/preview-input-box.html +0 -180
@@ -1,472 +0,0 @@
1
- <template>
2
- <div class="ai-consultation-outer">
3
- <div class="ai-consultation-container">
4
- <div class="chat-area">
5
- <!-- 对话区域 -->
6
- <div class="dialog-area">
7
- <div
8
- v-for="(message, index) in dialogMessages"
9
- :key="index"
10
- :class="['dialog-message', message.type]"
11
- >
12
- <div class="message-text" v-html="renderMd(message.content)" />
13
- <span v-if="message.type === 'ai' && isAiStreaming && index === dialogMessages.length - 1" class="typing-cursor">▍</span>
14
- </div>
15
- </div>
16
- </div>
17
-
18
- <div class="bottom-input-wrapper">
19
- <div class="input-container">
20
- <a-textarea
21
- ref="consultTextarea"
22
- v-model="doctorInputText"
23
- placeholder="医生补充信息或提问..."
24
- class="bottom-input"
25
- :rows="1"
26
- resize="none"
27
- @input="handleInput"
28
- @keydown="handleKeydown"
29
- ></a-textarea>
30
-
31
- <input
32
- ref="uploadInput"
33
- type="file"
34
- style="display: none"
35
- @change="handleFileChange"
36
- multiple
37
- accept="image/*,.pdf,.doc,.docx"
38
- />
39
-
40
- <div class="input-controls">
41
- <div class="input-controls-left">
42
- <a-button class="upload-btn" @click="triggerUpload">
43
- <a-icon type="plus" class="upload-icon" />
44
- <span class="upload-text">上传(报告、图片)</span>
45
- </a-button>
46
- </div>
47
-
48
- <div class="input-controls-right">
49
- <span class="enter-tip">Enter</span>
50
- <a-button
51
- type="primary"
52
- shape="circle"
53
- class="send-btn"
54
- @click="handleSendMessage"
55
- :disabled="!doctorInputText.trim()"
56
- >
57
- <span class="send-icon">↑</span>
58
- </a-button>
59
- </div>
60
- </div>
61
- </div>
62
- </div>
63
- </div>
64
- </div>
65
- </template>
66
-
67
- <script>
68
- import { startEventStreamPOST } from '@vue2-client/services/api/restTools'
69
- import { marked } from 'marked'
70
- import moment from 'moment/moment'
71
- import { mapState } from 'vuex'
72
-
73
- export default {
74
- name: 'AIConsultation',
75
- data() {
76
- return {
77
- currentDialogId: null,
78
- doctorInputText: '',
79
- isPlaying: false,
80
- isRecording: false,
81
- patientComplaint: '',
82
- doctorQuestions: [],
83
- examinationOrder: null,
84
- aiDiagnosis: null,
85
- dialogMessages: [],
86
- currentStreamConnection: null,
87
- isAiStreaming: false,
88
- resizeTimeout: null
89
- }
90
- },
91
- computed: {
92
- ...mapState('account', {currUser: 'user'})
93
- },
94
- mounted() {
95
- this.$nextTick(() => {
96
- this.autoResizeTextarea()
97
- })
98
- },
99
- beforeDestroy() {
100
- // 组件销毁时关闭流式连接
101
- if (this.currentStreamConnection) {
102
- this.currentStreamConnection()
103
- this.currentStreamConnection = null
104
- }
105
- if (this.resizeTimeout) {
106
- clearTimeout(this.resizeTimeout)
107
- }
108
- },
109
- methods: {
110
- autoResizeTextarea() {
111
- this.$nextTick(() => {
112
- const textarea = this.$refs.consultTextarea?.$el || this.$refs.consultTextarea
113
- if (!textarea) return
114
-
115
- textarea.style.height = 'auto'
116
- const scrollHeight = textarea.scrollHeight
117
- textarea.style.height = `${Math.min(Math.max(scrollHeight, 120), 250)}px`
118
- })
119
- },
120
-
121
- handleInput() {
122
- if (this.resizeTimeout) clearTimeout(this.resizeTimeout)
123
- this.resizeTimeout = setTimeout(() => {
124
- this.autoResizeTextarea()
125
- }, 16)
126
- },
127
-
128
- renderMd(text) {
129
- if (!text) return ''
130
- try {
131
- return marked.parse(text, { breaks: true, gfm: true, headerIds: false, mangle: false })
132
- } catch {
133
- return text
134
- }
135
- },
136
-
137
- handleKeydown(event) {
138
- if (event.key === 'Enter' && !event.shiftKey) {
139
- event.preventDefault()
140
- this.handleSendMessage()
141
- }
142
- },
143
-
144
- initDialog() {
145
- if (!this.currentDialogId) {
146
- this.currentDialogId = moment().format('YYYYMMDDHHmmss')
147
- }
148
- },
149
-
150
- clearDialog() {
151
- this.currentDialogId = moment().format('YYYYMMDDHHmmss')
152
- this.dialogMessages = []
153
- },
154
-
155
- handleSendMessage() {
156
- if (!this.doctorInputText.trim()) return
157
-
158
- // 确保有dialogId
159
- if (!this.currentDialogId) {
160
- this.initDialog()
161
- }
162
-
163
- const messageContent = this.doctorInputText.trim()
164
- const doctorMessage = {
165
- type: 'user',
166
- content: messageContent,
167
- time: new Date().toLocaleTimeString(),
168
- timestamp: Date.now()
169
- }
170
- this.dialogMessages.push(doctorMessage)
171
- this.scrollToBottom()
172
-
173
- this.doctorInputText = ''
174
- this.autoResizeTextarea()
175
-
176
- const chatId = this.currentDialogId
177
- let aiContent = ''
178
- const aiMsgIndex = this.dialogMessages.length
179
- this.dialogMessages.push({
180
- type: 'ai',
181
- content: '',
182
- time: new Date().toLocaleTimeString(),
183
- timestamp: Date.now()
184
- })
185
- this.scrollToBottom()
186
-
187
- this.isAiStreaming = true
188
-
189
- this.currentStreamConnection = startEventStreamPOST(
190
- '/his-web/api/af-his/ai/chat/stream',
191
- { userMessage: messageContent, chatId, model: '', prompt: '', useContext: true, user: this.currUser.operInfo },
192
- {'Content-Type': 'application/json'},
193
- (data, type) => {
194
- if (type === 'additionalInfo' || type === 'sourceInfo') return
195
-
196
- let textChunk = ''
197
- if (typeof data === 'object' && data !== null) {
198
- const choices = data.choices
199
- if (Array.isArray(choices) && choices.length > 0) {
200
- const delta = choices[0].delta
201
-
202
- // 优先取 delta.content(标准 OpenAI 格式)
203
- if (delta && typeof delta.content === 'string' && delta.content) {
204
- textChunk = delta.content
205
- }
206
-
207
- // 兼容百川模型的 thinking 字段
208
- if (!textChunk && delta && delta.thinking) {
209
- const thinking = delta.thinking
210
- // 取 summary 描述
211
- if (thinking.summary && typeof thinking.summary === 'string') {
212
- textChunk = `[思考中] ${thinking.summary}`
213
- }
214
- // 取 reasoning steps
215
- if (Array.isArray(thinking.steps)) {
216
- const activeStep = thinking.steps.find(s => s.status === 'in_progress')
217
- if (activeStep && activeStep.label) {
218
- textChunk = `[思考中] ${activeStep.label}`
219
- }
220
- }
221
- }
222
-
223
- // 检测模型拒答
224
- const finishReason = choices[0].finish_reason
225
- if (finishReason === 'refuse_answer') {
226
- const refuseTip = '\n\n> ⚠️ 很抱歉,当前问题我无法回答,请尝试调整提问方式或联系管理员。'
227
- if (!this.dialogMessages[aiMsgIndex].content.includes('无法回答')) {
228
- this.dialogMessages[aiMsgIndex].content += refuseTip
229
- this.isAiStreaming = false
230
- this.scrollToBottom()
231
- }
232
- }
233
- }
234
- } else if (typeof data === 'string') {
235
- textChunk = data
236
- }
237
-
238
- if (textChunk) {
239
- aiContent += textChunk
240
- this.dialogMessages[aiMsgIndex].content = aiContent
241
- this.scrollToBottom()
242
- }
243
- },
244
- (error) => {
245
- this.isAiStreaming = false
246
- this.dialogMessages[aiMsgIndex].content += `\n\n[错误: ${error.message || '请求失败'}]`
247
- this.scrollToBottom()
248
- },
249
- () => {
250
- this.isAiStreaming = false
251
- this.scrollToBottom()
252
- }
253
- )
254
- },
255
-
256
- setPatientComplaint(complaint) {
257
- this.patientComplaint = complaint
258
- },
259
-
260
- scrollToBottom(delay = 0) {
261
- this.$nextTick(() => {
262
- setTimeout(() => {
263
- const chatArea = document.querySelector('.chat-area')
264
- if (chatArea) {
265
- chatArea.scrollTop = chatArea.scrollHeight
266
- }
267
- }, delay)
268
- })
269
- },
270
-
271
- reset() {
272
- if (this.currentStreamConnection) {
273
- this.currentStreamConnection()
274
- this.currentStreamConnection = null
275
- }
276
- this.isAiStreaming = false
277
- this.patientComplaint = ''
278
- this.doctorQuestions = []
279
- this.examinationOrder = null
280
- this.aiDiagnosis = null
281
- this.doctorInputText = ''
282
- this.isPlaying = false
283
- this.isRecording = false
284
- this.dialogMessages = []
285
- this.$nextTick(() => {
286
- this.autoResizeTextarea()
287
- const chatArea = document.querySelector('.chat-area')
288
- if (chatArea) {
289
- chatArea.scrollTop = 0
290
- }
291
- })
292
- },
293
-
294
- triggerUpload() {
295
- this.$refs.uploadInput.click()
296
- },
297
-
298
- handleFileChange(event) {
299
- const files = Array.from(event.target.files || [])
300
- if (!files.length) return
301
-
302
- this.dialogMessages.push({
303
- type: 'user',
304
- content: `已上传文件:${files.map(f => f.name).join('、')}`,
305
- time: new Date().toLocaleTimeString(),
306
- timestamp: Date.now()
307
- })
308
- this.scrollToBottom()
309
- event.target.value = ''
310
- }
311
- }
312
- }
313
- </script>
314
-
315
- <style scoped>
316
- .ai-consultation-outer {
317
- box-sizing: border-box;
318
- margin: 0;
319
- padding: 0;
320
- width: 100%;
321
- height: 860px;
322
- }
323
-
324
- .ai-consultation-container {
325
- width: 100%;
326
- height: 100%;
327
- display: flex;
328
- flex-direction: column;
329
- background: #FFFFFF;
330
- border: 1px solid #E5E9F0;
331
- }
332
-
333
- .chat-area {
334
- flex: 1;
335
- overflow-y: auto;
336
- padding: 16px;
337
- background: #fff;
338
- min-height: 690px;
339
- }
340
-
341
- .dialog-area {
342
- display: flex;
343
- flex-direction: column;
344
- }
345
-
346
- /* 底部输入框区域 */
347
- .bottom-input-wrapper {
348
- flex-shrink: 0;
349
- padding: 15px 11px 0 11px;
350
- background: #fff;
351
- }
352
-
353
- .input-container {
354
- width: 100%;
355
- height: 249px;
356
- margin: 0 auto;
357
- display: flex;
358
- flex-direction: column;
359
- border: 1px solid #E5E9F0;
360
- border-radius: 6px;
361
- background: #FFFFFF;
362
- box-sizing: border-box;
363
- padding: 12px;
364
- }
365
-
366
- .bottom-input {
367
- flex: 1 1 auto;
368
- min-height: 0;
369
- width: 100%;
370
- border: none;
371
- padding: 0;
372
- font-family: 'Source Han Sans', 'Microsoft YaHei', sans-serif;
373
- font-size: 16px;
374
- color: #313131;
375
- resize: none;
376
- outline: none;
377
- background: transparent;
378
- }
379
-
380
- .bottom-input::placeholder {
381
- color: #999;
382
- }
383
-
384
- .input-controls {
385
- flex-shrink: 0;
386
- display: flex;
387
- align-items: center;
388
- justify-content: space-between;
389
- padding: 8px 0;
390
- }
391
-
392
- .enter-tip {
393
- font-family: 'Inter', sans-serif;
394
- font-size: 14px;
395
- font-weight: 500;
396
- color: #9E9E9E;
397
- padding: 4px 8px;
398
- }
399
-
400
- .send-btn {
401
- width: 30px;
402
- height: 30px;
403
- background: #0057FE;
404
- border: none;
405
- border-radius: 50%;
406
- color: #fff;
407
- font-size: 14px;
408
- cursor: pointer;
409
- display: flex;
410
- align-items: center;
411
- justify-content: center;
412
- padding: 0;
413
- }
414
-
415
- .send-btn:hover {
416
- background: #0040cc;
417
- }
418
-
419
- .send-icon {
420
- font-size: 14px;
421
- font-weight: bold;
422
- }
423
-
424
- /* 对话区域样式 */
425
- .dialog-message {
426
- display: flex;
427
- margin-bottom: 16px;
428
- align-items: flex-start;
429
- }
430
-
431
- .dialog-message:last-child {
432
- margin-bottom: 0;
433
- }
434
-
435
- .dialog-message.ai {
436
- flex-direction: row;
437
- }
438
-
439
- .dialog-message.user {
440
- flex-direction: row-reverse;
441
- }
442
-
443
- .dialog-message.user .message-text {
444
- text-align: right;
445
- }
446
-
447
- .message-text {
448
- opacity: 1;
449
- font-family: Source Han Sans;
450
- font-size: 16px;
451
- font-weight: normal;
452
- line-height: normal;
453
- text-align: justify;
454
- letter-spacing: 0em;
455
- font-feature-settings: "kern" on;
456
- max-width: 100%;
457
- color: #313131;
458
- }
459
-
460
- .typing-cursor {
461
- display: inline-block;
462
- margin-left: 2px;
463
- color: #0057FE;
464
- font-size: 18px;
465
- animation: blink 1s step-end infinite;
466
- }
467
-
468
- @keyframes blink {
469
- 0%, 100% { opacity: 1; }
470
- 50% { opacity: 0; }
471
- }
472
- </style>