vue2-client 1.16.48 → 1.16.49

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 (39) hide show
  1. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926145434.vue +641 -0
  2. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926145453.vue +641 -0
  3. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926145610.vue +647 -0
  4. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926145629.vue +647 -0
  5. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926145901.vue +645 -0
  6. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926145907.vue +651 -0
  7. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926145920.vue +651 -0
  8. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926150047.vue +651 -0
  9. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926151820.vue +646 -0
  10. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926151827.vue +646 -0
  11. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926152115.vue +646 -0
  12. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926152212.vue +653 -0
  13. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926152215.vue +653 -0
  14. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926152337.vue +657 -0
  15. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926152341.vue +657 -0
  16. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926152826.vue +657 -0
  17. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926152828.vue +646 -0
  18. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926153121.vue +654 -0
  19. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926153242.vue +654 -0
  20. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926153318.vue +646 -0
  21. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926153415.vue +646 -0
  22. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926153435.vue +655 -0
  23. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926153606.vue +655 -0
  24. package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926153653.vue +655 -0
  25. package/package.json +1 -1
  26. package/src/base-client/components/common/XAddNativeForm/XAddNativeForm.vue +1178 -1178
  27. package/src/base-client/components/common/XDataCard/XDataCard.vue +44 -18
  28. package/src/base-client/components/common/XDataCard/test.vue +367 -0
  29. package/src/pages/WorkflowDetail/WorkFlowDemo3.vue +225 -203
  30. package/src/router/async/router.map.js +1 -4
  31. package/src/services/api/common.js +2 -0
  32. package/src/assets/img/paymentMethod/icon1.png +0 -0
  33. package/src/assets/img/paymentMethod/icon2.png +0 -0
  34. package/src/assets/img/paymentMethod/icon3.png +0 -0
  35. package/src/assets/img/paymentMethod/icon4.png +0 -0
  36. package/src/assets/img/paymentMethod/icon5.png +0 -0
  37. package/src/assets/img/paymentMethod/icon6.png +0 -0
  38. package/src/base-client/components/common/XReport/XReportHospitalizationDemo.vue +0 -45
  39. package/src/base-client/components/his/XCharge/testConfig.js +0 -149
@@ -0,0 +1,641 @@
1
+ <template>
2
+ <div>
3
+ <div v-if="render" class="XCard">
4
+ <template v-for="(card, itemIndex) in data">
5
+ <a-card
6
+ :key="'card' + itemIndex"
7
+ class="data-card"
8
+ :class="{ 'card-clicked': card.isClicked }"
9
+ :headStyle="{ backgroundColor: '#f9f9f9' }"
10
+ >
11
+ <div
12
+ v-if="config && card[config.ribbon]"
13
+ class="ribbon"
14
+ :style="{ backgroundColor: getRibbonColor(card[config.ribbonColor]) }">
15
+ {{ card[config.ribbon] }}
16
+ </div>
17
+ <!-- 自定义标题 -->
18
+ <template #title>
19
+ <div class="custom-title" @click="cardClick(card, 'cardclick', itemIndex)">
20
+ <a-tooltip placement="top">
21
+ <template #title>{{ card[config.id] }}</template>
22
+ <div class="title-id" v-if="card[config.id]">{{ card[config.id] }}</div>
23
+ </a-tooltip>
24
+ <div class="title-basic">
25
+ <div class="title-main">
26
+ <span class="title-name">{{ card[config.title] }}</span>
27
+ <span class="title-info">{{ card[config.title2] }}</span>
28
+ <span class="title-title3">{{ card[config.title3] }}</span>
29
+ </div>
30
+ <div class="additional-info" v-if="card[config.subtitle2] || card[config.subtitle3] || card[config.subtitle4]">
31
+ <a-tooltip placement="top" v-if="card[config.subtitle2]">
32
+ <template #title>{{ card[config.subtitle2] }}</template>
33
+ <span class="subtitle2">{{ card[config.subtitle2] }}</span>
34
+ </a-tooltip>
35
+ <a-tooltip placement="top" v-if="card[config.subtitle3]">
36
+ <template #title>{{ card[config.subtitle3] }}</template>
37
+ <span class="subtitle3">{{ card[config.subtitle3] }}</span>
38
+ </a-tooltip>
39
+ <span class="subtitle4" v-if="card[config.subtitle4]">{{ card[config.subtitle4] }}</span>
40
+ </div>
41
+ </div>
42
+ </div>
43
+ </template>
44
+ <!-- 主体 -->
45
+ <div class="body" v-if="card[config.text] || (config.content && config.content.length > 0)">
46
+ <div class="body-text" v-if="card[config.text]">
47
+ <a-tooltip :title="card[config.text]">
48
+ <span class="text-ellipsis">{{ card[config.text] }}</span>
49
+ </a-tooltip>
50
+ </div>
51
+ <template v-for="(item, bodyIndex) in config.content" v-if="bodyIndex < 6">
52
+ <div :key="'body' + bodyIndex" class="body-item">
53
+ <span class="body-item-label">{{ item.label }}:</span>
54
+ <template v-if="item.type === 'progress'">
55
+ <div class="progress">
56
+ <div class="progress-bar">
57
+ <div class="progress-done" :style="'width:' + card[item.key] * 100 + '%;backgroundColor: ' + determineRatioColor(card[item.key] * 100)"></div>
58
+ </div>
59
+ </div>
60
+ <a-progress :percent="card[item.key]" :stroke-color="{ '0%': '#108ee9', '100%': '#87d068' }" strokeWidth="10" :style="{ width: '95%' }" />
61
+ </template>
62
+ <template v-else-if="item.type === 'custom' && tableColumns">
63
+ <!-- 根据 tableColumns 显示自定义内容 -->
64
+ <span v-for="column in tableColumns" v-if="column.dataIndex === item.key" :key="column.dataIndex">
65
+ <template v-if="column.slotType === 'badge'">
66
+ <x-badge
67
+ :service-name="serviceName"
68
+ :env="env"
69
+ :dataCard="true"
70
+ :badge-key="column.slotKeyMap"
71
+ :value="card[item.key]" />
72
+ </template>
73
+ <template v-else>
74
+ <slot :name="column.slots.customRender">{{ card[item.key] }}</slot>
75
+ </template>
76
+ </span>
77
+ </template>
78
+ <template v-else>
79
+ <span class="body-item-value" style="float: right;">{{ card[item.key] }}</span>
80
+ </template>
81
+ </div>
82
+ <a-divider
83
+ v-if="bodyIndex !== config.content.length - 1"
84
+ dashed
85
+ :key="'body' + bodyIndex + 'after'"
86
+ class="body-split" />
87
+ </template>
88
+ </div>
89
+ <!-- 下方按钮 -->
90
+ <template #actions>
91
+ <a-row align="middle" class="custom-actions" v-if="config && config.footer && config.footer.length > 0">
92
+ <template v-for="(item, footerIndex) in config.footer">
93
+ <a-col :key="'footer_' + footerIndex" class="footer-item" :span="24 / config.footer.length" @click="clickFooter(card, item.emit, itemIndex)">
94
+ <span>
95
+ <a-icon :type="item.icon" class="footer-icon" />
96
+ <span>{{ item.label }}</span>
97
+ </span>
98
+ </a-col>
99
+ <a-divider
100
+ v-if="footerIndex !== config.footer.length - 1"
101
+ :key="'footer_' + footerIndex + 'after'"
102
+ type="vertical"
103
+ class="footer-item-split" />
104
+ </template>
105
+ </a-row>
106
+ </template>
107
+ </a-card>
108
+ </template>
109
+ </div>
110
+ <div v-else>
111
+ <a-skeleton />
112
+ </div>
113
+ <div v-if="this.showPagination">
114
+ <a-divider />
115
+ <a-pagination
116
+ v-model="pageNum"
117
+ style="float: right"
118
+ :total="total"
119
+ show-less-items
120
+ :page-size="pageSize"
121
+ :page-size-options="pageSizeOptions"
122
+ show-size-changer
123
+ @change="pageNumChange"
124
+ :showTotal="paginationShowTotal"
125
+ @showSizeChange="pageSizeChange">
126
+ </a-pagination>
127
+ </div>
128
+ </div>
129
+ </template>
130
+
131
+ <script>
132
+ import XBadge from '@vue2-client/base-client/components/common/XBadge'
133
+
134
+ export default {
135
+ name: 'XDataCard',
136
+ components: {
137
+ XBadge,
138
+ },
139
+ props: {
140
+ // 卡片数据更新方法
141
+ cardData: {
142
+ type: Function,
143
+ default: undefined
144
+ },
145
+ // 卡片的配置
146
+ cardConfig: {
147
+ type: Object,
148
+ default: undefined
149
+ },
150
+ showPagination: {
151
+ type: Boolean,
152
+ default: false
153
+ },
154
+ // 临时
155
+ testData: {
156
+ type: Array,
157
+ default: undefined
158
+ },
159
+ tableColumns: {
160
+ type: Array,
161
+ default: undefined
162
+ },
163
+ // 服务名称
164
+ serviceName: undefined,
165
+ // 当前环境
166
+ env: {
167
+ type: String,
168
+ default: 'prod'
169
+ },
170
+ // pageSize参数
171
+ prePageSize: {
172
+ type: Number,
173
+ default: undefined
174
+ },
175
+ // 初始是否加载数据
176
+ createdQuery: {
177
+ type: Boolean,
178
+ default: false
179
+ }
180
+ },
181
+ inject: ['getConfigByName'],
182
+ data () {
183
+ return {
184
+ // 配置
185
+ config: {},
186
+ // 数据
187
+ data: {},
188
+ // 当前页码
189
+ pageNum: 1,
190
+ // 控制渲染
191
+ render: true,
192
+ // 分页大小
193
+ pageSize: 10,
194
+ // 分页大小选项
195
+ pageSizeOptions: ['4', '6', '8', '10'],
196
+ // 数据总数
197
+ total: 0,
198
+ activeCardIndex: null, // 新增:记录当前激活的卡片索引
199
+ // 混入插槽组件的数据
200
+ mixinData: {},
201
+ }
202
+ },
203
+ created () {
204
+ // 根据参数初始化数据值
205
+ if (this.prePageSize) {
206
+ this.pageSize = this.prePageSize
207
+ }
208
+ },
209
+ mounted () {
210
+ console.log('cardData------', this.cardData)
211
+ console.log('cardConfig-----', this.cardConfig)
212
+ console.log('showPagination-----', this.showPagination)
213
+ console.log('testData----', this.testData)
214
+ console.log('tableColumns------', this.tableColumns)
215
+ console.log('data-----', this.data)
216
+ // 配置初始化
217
+ if (this.cardConfig) {
218
+ this.config = this.cardConfig
219
+ } else {
220
+ this.config = {
221
+ id: '未获取到配置',
222
+ title: '未获取到配置',
223
+ title2: '未获取到配置',
224
+ title3: '未获取到配置',
225
+ subtitle2: '未获取到配置',
226
+ subtitle3: '未获取到配置',
227
+ subtitle4: '未获取到配置',
228
+ text: '未获取到配置',
229
+ ribbon: '未获取到配置',
230
+ ribbonColor: '未获取到配置',
231
+ content: [
232
+ {
233
+ label: '未获取到配置',
234
+ key: 'one'
235
+ },
236
+ {
237
+ label: '未获取到配置',
238
+ key: 'two'
239
+ },
240
+ {
241
+ label: '未获取到配置',
242
+ key: 'three'
243
+ },
244
+ {
245
+ label: '未获取到配置',
246
+ key: 'four'
247
+ },
248
+ {
249
+ label: '未获取到配置',
250
+ key: 'five'
251
+ },
252
+ {
253
+ label: '未获取到配置',
254
+ key: 'six',
255
+ type: 'progress'
256
+ }
257
+ ],
258
+ footer: [
259
+ {
260
+ icon: 'edit',
261
+ label: '未获取到配置',
262
+ emit: 'planEdit'
263
+ },
264
+ {
265
+ icon: 'user',
266
+ label: '未获取到配置',
267
+ emit: 'user'
268
+ }
269
+ ]
270
+ }
271
+ console.warn(this.config)
272
+ }
273
+
274
+ // 数据初始化
275
+ if (this.cardData) {
276
+ // if (this.createdQuery) {
277
+ // this.loadData()
278
+ // }
279
+ } else {
280
+ this.data = {
281
+ one: '未获取到配置',
282
+ two: '未获取到配置',
283
+ three: '未获取到配置',
284
+ four: '未获取到配置',
285
+ five: '未获取到配置',
286
+ six: 70,
287
+ }
288
+ }
289
+ // 测试数据初始化
290
+ if (this.testData) {
291
+ this.data = this.testData
292
+ }
293
+ },
294
+ methods: {
295
+ // 根据比例计算出颜色
296
+ determineRatioColor (ratio, isNum = false) {
297
+ let result
298
+ // 如果是数字,并且比例大于79,则将数字显示为黑色
299
+ if (isNum && ratio > 79) {
300
+ return 'rgb(0,0,0)'
301
+ }
302
+ if (ratio >= 90) {
303
+ result = 'rgb( 1,245, 38 )'
304
+ } else if (ratio >= 75) {
305
+ result = 'rgb( 139,245, 0)'
306
+ } else if (ratio >= 40) {
307
+ result = 'rgb(245,163, 0)'
308
+ } else if (ratio >= 20) {
309
+ result = 'rgb(244, 96, 0)'
310
+ } else {
311
+ result = 'rgb(255, 0, 0)'
312
+ }
313
+ return result
314
+ },
315
+ async cardClick (card, itemIndex) {
316
+ try {
317
+ // 等待 beforeSwitch 完全执行完成
318
+ const result = await this.beforeSwitch(card, 'beforeSwitch', itemIndex)
319
+ // 如果返回 undefined 说明没有监听器,或者返回 true 说明检查通过
320
+ if (result === undefined || result === true) {
321
+ await this.clickFooter(card, 'cardclick', itemIndex)
322
+ }
323
+ } catch (error) {
324
+ }
325
+ },
326
+ // 点击按钮
327
+ async clickFooter (data, eventName, index) {
328
+ if (eventName === 'cardclick') {
329
+ // 清除所有卡片的点击状态
330
+ if (this.data && Array.isArray(this.data)) {
331
+ this.data.forEach(item => {
332
+ if (item.isClicked) {
333
+ this.$set(item, 'isClicked', false)
334
+ }
335
+ })
336
+ }
337
+ // 设置当前卡片的点击状态
338
+ this.$set(data, 'isClicked', true)
339
+ }
340
+ this.$emit('cardEmit', data, eventName)
341
+ },
342
+ async beforeSwitch (data, eventName, index) {
343
+ return new Promise((resolve) => {
344
+ // 检查是否有其他卡片已经被点击
345
+ const hasClickedCard = this.data.some(item => item.isClicked)
346
+ // 如果没有任何卡片被点击过,直接通过
347
+ if (!hasClickedCard) {
348
+ resolve(true)
349
+ return
350
+ }
351
+ // 检查是否有监听器
352
+ const hasListeners = this._events?.cardEmit?.length > 0
353
+
354
+ // 如果没有监听器,返回 undefined 表示继续执行
355
+ if (!hasListeners) {
356
+ resolve(undefined)
357
+ return
358
+ }
359
+ // 如果有监听器,执行事件检查
360
+ try {
361
+ this.$emit('cardEmit', data, eventName)
362
+ resolve(true)
363
+ } catch (error) {
364
+ resolve(false)
365
+ }
366
+ })
367
+ },
368
+ // 获取数据
369
+ loadData () {
370
+ this.render = false
371
+ const parameter = Object.assign({
372
+ querySummary: false, // 分页查询的情况不重新获取汇总数据
373
+ pageNo: this.pageNum,
374
+ pageSize: this.pageSize
375
+ }
376
+ )
377
+ this.cardData(parameter).then(res => {
378
+ this.data = res.data
379
+ this.total = res.totalCount
380
+ this.render = true
381
+ })
382
+ },
383
+ // 页码改变
384
+ pageNumChange (page, pageSize) {
385
+ this.pageNum = page
386
+ this.pageSize = pageSize
387
+ this.loadData()
388
+ },
389
+ // 分页大小改变
390
+ pageSizeChange (current, pageSize) {
391
+ this.pageSize = pageSize
392
+ this.loadData()
393
+ },
394
+ // 刷新
395
+ refresh () {
396
+ this.loadData()
397
+ },
398
+ // 分页前展示当前项和总数
399
+ paginationShowTotal () {
400
+ return `${(this.pageNum - 1) * this.pageSize + 1 } - ${ this.pageNum * this.pageSize } | 共 ${ this.total } 项`
401
+ },
402
+ getRibbonColor (color) {
403
+ switch (color) {
404
+ case 'red':
405
+ return '#ff4d4f'
406
+ case 'blue':
407
+ return '#1890ff'
408
+ case 'yellow':
409
+ return '#fadb14'
410
+ default:
411
+ return '#ff4d4f' // 默认红色
412
+ }
413
+ }
414
+ }
415
+ }
416
+ </script>
417
+
418
+ <style lang="less" scoped>
419
+ .hide-page-numbers /deep/ .ant-pagination-item,
420
+ .hide-page-numbers /deep/ .ant-pagination-jump-next {
421
+ display: none !important; /* 隐藏数字页码和多页跳转 */
422
+ }
423
+ .hide-page-numbers /deep/ .ant-pagination-prev,
424
+ .hide-page-numbers /deep/ .ant-pagination-next {
425
+ display: inline-block !important; /* 保留左右跳转按钮 */
426
+ }
427
+
428
+ .XCard {
429
+ display: flex;
430
+ flex-wrap: wrap;
431
+ justify-content: flex-start;
432
+ overflow-y: auto;
433
+ overflow-x: hidden;
434
+ max-height: 85vh;
435
+ .data-card {
436
+ width: 100%;
437
+ max-width: 300px;
438
+ border: 2px solid rgb(244,244,244);
439
+ border-radius: 5px;
440
+ margin: 2px;
441
+ overflow: hidden;
442
+
443
+ ::v-deep .ant-card-body {
444
+ padding: 15px !important; // 使用 !important 确保样式覆盖
445
+ }
446
+
447
+ .header {
448
+ width: 100%;
449
+ background-color: rgb(244,244,244);
450
+ padding: 5px 15px;
451
+
452
+ span {
453
+ font-weight: bold;
454
+ font-size: 1.1em;
455
+ }
456
+ }
457
+
458
+ .body {
459
+ .body-text{
460
+ width: 500px;
461
+ font-weight: bold;
462
+ font-size: 1.1em;
463
+ .text-ellipsis{
464
+ display: inline-block;
465
+ max-width: 260px; /* 控制文本的最大宽度 */
466
+ white-space: nowrap;
467
+ overflow: hidden;
468
+ text-overflow: ellipsis;
469
+ }
470
+ }
471
+
472
+ .body-item {
473
+ padding: 3px 5px;
474
+ }
475
+
476
+ .body-split {
477
+ margin: 1px 0;
478
+ }
479
+
480
+ .body-item-label {
481
+ color: rgba(117, 117, 117, 0.8);
482
+ font-size: 0.95em;
483
+ }
484
+
485
+ .body-item-value {
486
+ color: black;
487
+ }
488
+
489
+ .progress {
490
+ display: inline-block;
491
+ width: 60%;
492
+ height: 60%;
493
+ float: right;
494
+ padding-right: 1.5%;
495
+ margin-top: 0.5%;
496
+
497
+ .progress-bar {
498
+ width: 100%;
499
+ height: 90%;
500
+ display: inline-block;
501
+ border-radius: 10%;
502
+ background-color: rgba(212,217,218, 0.6);
503
+
504
+ .progress-done {
505
+ float: left;
506
+ display: inline-block;
507
+ height: 100%;
508
+ border-radius: 10%;
509
+ }
510
+ }
511
+ }
512
+ .progress-num {
513
+ position: relative;
514
+ top: -83%;
515
+ left: -3%;
516
+ text-align: end;
517
+ font-size: 0.9em;
518
+ color: black;
519
+ }
520
+ }
521
+
522
+ &.card-clicked {
523
+ :deep(.ant-card-head) {
524
+ background-color: #e6f7ff;
525
+ transition: background-color 0.3s ease;
526
+ }
527
+ }
528
+ }
529
+
530
+ .custom-title {
531
+ display: flex;
532
+ align-items: center;
533
+ gap: 12px;
534
+
535
+ &:hover {
536
+ cursor: pointer;
537
+ }
538
+
539
+ .title-id {
540
+ flex-shrink: 0;
541
+ width: 65px;
542
+ color: #1890ff;
543
+ font-size: 16px;
544
+ font-weight: bold;
545
+ padding: 4px 8px;
546
+ border: 1px solid #1890ff;
547
+ border-radius: 4px;
548
+ line-height: 1.4;
549
+ text-align: center;
550
+ white-space: nowrap;
551
+ overflow: hidden;
552
+ text-overflow: ellipsis;
553
+ }
554
+
555
+ .title-basic {
556
+ display: flex;
557
+ flex-direction: column;
558
+ flex-grow: 1;
559
+
560
+ .subtitle2, .subtitle3 {
561
+ display: inline-block;
562
+ max-width: 50px; /* 固定宽度 */
563
+ white-space: nowrap;
564
+ overflow: hidden;
565
+ text-overflow: ellipsis;
566
+ }
567
+
568
+ .title-main {
569
+ display: flex;
570
+ align-items: center;
571
+ gap: 8px;
572
+ .title-info {
573
+ margin-left: 6px;
574
+ color: #808080;
575
+ }
576
+ .title-name {
577
+ font-weight: bold;
578
+ }
579
+ .title-title3 {
580
+ color: #808080;
581
+ }
582
+ }
583
+
584
+ .additional-info {
585
+ display: flex;
586
+ gap: 8px;
587
+ font-size: 13px;
588
+ color: #808080;
589
+ .subtitle4 {
590
+ color: rgba(0, 0, 255, 0.8);
591
+ }
592
+ }
593
+ }
594
+ }
595
+
596
+ .ribbon {
597
+ position: absolute;
598
+ top: 16px;
599
+ right: -6px;
600
+ background-color: #ff4d4f;
601
+ color: white;
602
+ padding: 5px 25px;
603
+ font-size: 12px;
604
+ transform: rotate(45deg) translateX(30%);
605
+ transform-origin: top right;
606
+ z-index: 1;
607
+ }
608
+
609
+ .custom-actions {
610
+ .footer-icon {
611
+ margin-right: 5px;
612
+ }
613
+
614
+ .footer-item-split {
615
+ color: rgba(220, 220, 220, 0.59);
616
+ }
617
+
618
+ .footer-item {
619
+ color: rgba(117, 117, 117, 0.8);
620
+ font-size: 1em;
621
+ white-space: nowrap;
622
+ display: inline-flex;
623
+ align-items: center;
624
+ justify-content: center;
625
+ }
626
+
627
+ .footer-item:hover {
628
+ color: rgb( 24,144,255 );
629
+ cursor: pointer;
630
+ }
631
+ }
632
+ }
633
+
634
+ .ellipsis {
635
+ display: inline-block;
636
+ max-width: 60px;
637
+ white-space: nowrap;
638
+ overflow: hidden;
639
+ text-overflow: ellipsis;
640
+ }
641
+ </style>