vue2-client 1.16.49 → 1.16.51
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/package.json +112 -112
- package/src/assets/svg/female.svg +1 -0
- package/src/assets/svg/male.svg +1 -0
- package/src/base-client/components/common/HIS/HButtons/HButtons.vue +371 -371
- package/src/base-client/components/common/HIS/HFormGroup/HFormGroup.vue +120 -120
- package/src/base-client/components/common/HIS/HFormGroup/index.js +3 -3
- package/src/base-client/components/common/HIS/HFormTable/HFormTable.vue +379 -257
- package/src/base-client/components/common/HIS/demo.vue +61 -61
- package/src/base-client/components/common/XCollapse/XCollapse.vue +461 -461
- package/src/base-client/components/common/XInput/XInput.vue +147 -147
- package/src/base-client/components/common/XReportGrid/XReportTrGroup.vue +824 -824
- package/src/base-client/components/common/XTable/XTable.vue +1610 -1610
- package/src/base-client/components/common/XTimeline/XTimeline.vue +454 -454
- package/src/base-client/components/his/XHisEditor/XHisEditor.vue +705 -705
- package/src/base-client/components/his/XList/XList.vue +829 -607
- package/src/base-client/components/his/threeTestOrders/editor.vue +113 -113
- package/src/pages/WorkflowDetail/WorkFlowDemo3.vue +203 -225
- package/src/pages/userInfoDetailManage/ExceptionRecordQuery/index.vue +45 -45
- package/src/router/async/router.map.js +129 -129
- package/src/services/api/common.js +0 -2
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926145434.vue +0 -641
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926145453.vue +0 -641
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926145610.vue +0 -647
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926145629.vue +0 -647
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926145901.vue +0 -645
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926145907.vue +0 -651
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926145920.vue +0 -651
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926150047.vue +0 -651
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926151820.vue +0 -646
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926151827.vue +0 -646
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926152115.vue +0 -646
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926152212.vue +0 -653
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926152215.vue +0 -653
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926152337.vue +0 -657
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926152341.vue +0 -657
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926152826.vue +0 -657
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926152828.vue +0 -646
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926153121.vue +0 -654
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926153242.vue +0 -654
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926153318.vue +0 -646
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926153415.vue +0 -646
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926153435.vue +0 -655
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926153606.vue +0 -655
- package/.history/src/base-client/components/common/XDataCard/XDataCard_20250926153653.vue +0 -655
- package/src/base-client/components/common/XDataCard/test.vue +0 -367
@@ -1,454 +1,454 @@
|
|
1
|
-
<template>
|
2
|
-
<!-- 时间轴主容器 -->
|
3
|
-
<div class="x-timeline" :class="wrapperClassObject">
|
4
|
-
<!-- 时间轴导航栏 -->
|
5
|
-
<div class="x-timeline-nav">
|
6
|
-
<!-- 导航按钮:前一周、前一天 -->
|
7
|
-
<a-button type="link" @click="goToPrevWeek">
|
8
|
-
<a-icon type="double-left"/>
|
9
|
-
{{ config?.prevWeekText || '前一周' }}
|
10
|
-
</a-button>
|
11
|
-
<a-button type="link" @click="goToPrevDay">
|
12
|
-
<a-icon type="left"/>
|
13
|
-
{{ config?.prevDayText || '前一天' }}
|
14
|
-
</a-button>
|
15
|
-
<!-- 日期显示区域 -->
|
16
|
-
<div class="timeline-dates">
|
17
|
-
<div
|
18
|
-
v-for="(date, index) in displayDates"
|
19
|
-
:key="index"
|
20
|
-
class="date-item"
|
21
|
-
:class="{
|
22
|
-
'ant-btn-primary': isCurrentDate(date),
|
23
|
-
'date-weekend': isWeekend(date),
|
24
|
-
'ant-btn-disabled': isDisabled(date)
|
25
|
-
}"
|
26
|
-
@click="selectDate(date)"
|
27
|
-
>
|
28
|
-
<div class="weekday">{{ getWeekDay(date) }}</div>
|
29
|
-
<div class="date">{{ formatDate(date) }}</div>
|
30
|
-
</div>
|
31
|
-
</div>
|
32
|
-
<!-- 导航按钮:后一天、后一周 -->
|
33
|
-
<a-button type="link" @click="goToNextDay">
|
34
|
-
{{ config?.nextDayText || '后一天' }}
|
35
|
-
<a-icon type="right"/>
|
36
|
-
</a-button>
|
37
|
-
<a-button type="link" @click="goToNextWeek">
|
38
|
-
{{ config?.nextWeekText || '后一周' }}
|
39
|
-
<a-icon type="double-right"/>
|
40
|
-
</a-button>
|
41
|
-
</div>
|
42
|
-
</div>
|
43
|
-
</template>
|
44
|
-
|
45
|
-
<script>
|
46
|
-
import moment from 'moment'
|
47
|
-
import { getConfigByName, runLogic } from '@vue2-client/services/api/common'
|
48
|
-
|
49
|
-
// 设置 moment 为中文语言环境
|
50
|
-
moment.locale('zh-cn')
|
51
|
-
|
52
|
-
export default {
|
53
|
-
name: 'XTimeline',
|
54
|
-
components: {},
|
55
|
-
props: {
|
56
|
-
// 当前选中日期,默认为空(不选中)
|
57
|
-
modelValue: {
|
58
|
-
type: String,
|
59
|
-
default: ''
|
60
|
-
},
|
61
|
-
// 配置参数名称,用于获取时间轴配置
|
62
|
-
queryParamsName: {
|
63
|
-
type: String,
|
64
|
-
default: ''
|
65
|
-
}
|
66
|
-
},
|
67
|
-
|
68
|
-
// 定义组件事件
|
69
|
-
emits: ['update:modelValue', 'change', 'prev-week', 'next-week', 'prev-day', 'next-day', 'init'],
|
70
|
-
|
71
|
-
data () {
|
72
|
-
return {
|
73
|
-
currentDate: this.modelValue, // 当前选中日期
|
74
|
-
baseDate: moment().format('YYYY-MM-DD'), // 基准日期,默认今天,用于计算显示范围
|
75
|
-
config: null,
|
76
|
-
disabledDates: [] // 禁用日期列表
|
77
|
-
}
|
78
|
-
},
|
79
|
-
computed: {
|
80
|
-
// 动态样式开关(与 XHDescriptions 思路一致):布尔开关 + size 派生类
|
81
|
-
wrapperClassObject () {
|
82
|
-
const attrs = this.$attrs || {}
|
83
|
-
const classes = {}
|
84
|
-
|
85
|
-
const booleanStyleKeys = [
|
86
|
-
'compact',
|
87
|
-
'bordered',
|
88
|
-
'highlight-weekend',
|
89
|
-
'dark-theme',
|
90
|
-
'style1'
|
91
|
-
]
|
92
|
-
booleanStyleKeys.forEach(key => {
|
93
|
-
const val = attrs[key]
|
94
|
-
const truthy = val === true || val === '' || val === 'true'
|
95
|
-
if (truthy) classes[`xtimeline-${key}`] = true
|
96
|
-
})
|
97
|
-
const size = attrs.size
|
98
|
-
if (size && typeof size === 'string') classes[`xtimeline-size-${size}`] = true
|
99
|
-
return classes
|
100
|
-
},
|
101
|
-
// 计算需要显示的日期范围,固定显示周一到周日
|
102
|
-
displayDates () {
|
103
|
-
const dates = []
|
104
|
-
// 计算当前日期所在周的周一
|
105
|
-
const currentDay = moment(this.baseDate)
|
106
|
-
const dayOfWeek = currentDay.day() || 7 // 获取星期几,将周日的0转换为7
|
107
|
-
const mondayOfWeek = currentDay.clone().subtract(dayOfWeek - 1, 'day') // 减去相应的天数得到周一
|
108
|
-
|
109
|
-
// 从周一开始,生成一周的日期
|
110
|
-
dates.push(mondayOfWeek.format('YYYY-MM-DD')) // 周一
|
111
|
-
for (let i = 1; i <= 6; i++) {
|
112
|
-
dates.push(mondayOfWeek.clone().add(i, 'day').format('YYYY-MM-DD'))
|
113
|
-
}
|
114
|
-
|
115
|
-
return dates
|
116
|
-
}
|
117
|
-
},
|
118
|
-
|
119
|
-
watch: {
|
120
|
-
// 监听外部传入的选中日期变化
|
121
|
-
modelValue: {
|
122
|
-
handler (newVal) {
|
123
|
-
this.currentDate = newVal
|
124
|
-
if (newVal) {
|
125
|
-
this.baseDate = newVal
|
126
|
-
}
|
127
|
-
},
|
128
|
-
immediate: true
|
129
|
-
},
|
130
|
-
// 监听配置参数名称变化
|
131
|
-
queryParamsName: {
|
132
|
-
handler (newValue) {
|
133
|
-
this.getData(newValue)
|
134
|
-
},
|
135
|
-
immediate: true
|
136
|
-
}
|
137
|
-
},
|
138
|
-
|
139
|
-
created () {
|
140
|
-
// 组件创建时获取配置
|
141
|
-
this.getData(this.queryParamsName)
|
142
|
-
},
|
143
|
-
|
144
|
-
methods: {
|
145
|
-
// 获取时间轴配置数据
|
146
|
-
async getData (data) {
|
147
|
-
getConfigByName(data, 'af-his', res => {
|
148
|
-
this.config = res
|
149
|
-
// 触发初始化事件,传递配置和默认日期
|
150
|
-
this.$emit('init', this.baseDate)
|
151
|
-
if (res.defaultValue) {
|
152
|
-
// 如果有默认值,则设置当前选中日期和基准日期
|
153
|
-
this.currentDate = res.defaultValue
|
154
|
-
this.baseDate = res.defaultValue
|
155
|
-
this.$emit('update:modelValue', res.defaultValue)
|
156
|
-
} else {
|
157
|
-
// 如果没有默认值,则设置今天日期为基准日期
|
158
|
-
this.modelValue = this.baseDate
|
159
|
-
}
|
160
|
-
|
161
|
-
// 执行配置中指定的业务逻辑
|
162
|
-
if (res.logicName) {
|
163
|
-
runLogic(res.logicName, res.parameter, 'af-his').then(result => {
|
164
|
-
if (result) {
|
165
|
-
this.handleLogicResult(result)
|
166
|
-
}
|
167
|
-
})
|
168
|
-
}
|
169
|
-
})
|
170
|
-
},
|
171
|
-
|
172
|
-
// 处理业务逻辑返回结果
|
173
|
-
handleLogicResult (result) {
|
174
|
-
if (result.disabledDates) {
|
175
|
-
this.disabledDates = result.disabledDates
|
176
|
-
}
|
177
|
-
if (result.currentDate) {
|
178
|
-
this.currentDate = result.currentDate
|
179
|
-
this.baseDate = result.currentDate
|
180
|
-
this.$emit('update:modelValue', result.currentDate)
|
181
|
-
}
|
182
|
-
},
|
183
|
-
|
184
|
-
// 格式化日期显示
|
185
|
-
formatDate (date) {
|
186
|
-
const format = this.config?.dateFormat || 'MM/DD'
|
187
|
-
return moment(date).format(format)
|
188
|
-
},
|
189
|
-
|
190
|
-
// 获取星期显示
|
191
|
-
getWeekDay (date) {
|
192
|
-
const format = this.config?.weekFormat || '周dd'
|
193
|
-
return moment(date).format(format)
|
194
|
-
},
|
195
|
-
|
196
|
-
// 判断是否为周末
|
197
|
-
isWeekend (date) {
|
198
|
-
if (!this.config?.highlightWeekend) return false
|
199
|
-
const day = moment(date).day()
|
200
|
-
return day === 0 || day === 6
|
201
|
-
},
|
202
|
-
|
203
|
-
// 判断日期是否禁用
|
204
|
-
isDisabled (date) {
|
205
|
-
if (this.config?.minDate && moment(date).isBefore(this.config.minDate)) {
|
206
|
-
return true
|
207
|
-
}
|
208
|
-
if (this.config?.maxDate && moment(date).isAfter(this.config.maxDate)) {
|
209
|
-
return true
|
210
|
-
}
|
211
|
-
return this.disabledDates.includes(date)
|
212
|
-
},
|
213
|
-
|
214
|
-
// 判断是否为当前选中日期
|
215
|
-
isCurrentDate (date) {
|
216
|
-
if (!this.currentDate) return false
|
217
|
-
return moment(date).format('YYYY-MM-DD') === moment(this.currentDate).format('YYYY-MM-DD')
|
218
|
-
},
|
219
|
-
|
220
|
-
// 选择日期
|
221
|
-
selectDate (date) {
|
222
|
-
if (this.isDisabled(date)) return
|
223
|
-
this.currentDate = date
|
224
|
-
this.$emit('update:modelValue', date)
|
225
|
-
this.$emit('change', date)
|
226
|
-
},
|
227
|
-
|
228
|
-
// 前一天
|
229
|
-
goToPrevDay () {
|
230
|
-
const newDate = moment(this.currentDate).subtract(1, 'day')
|
231
|
-
if (this.config?.minDate && newDate.isBefore(this.config.minDate)) {
|
232
|
-
return
|
233
|
-
}
|
234
|
-
// 更新基准日期
|
235
|
-
this.baseDate = newDate.format('YYYY-MM-DD')
|
236
|
-
// 同时选中新的日期
|
237
|
-
this.currentDate = this.baseDate
|
238
|
-
this.$emit('update:modelValue', this.currentDate)
|
239
|
-
// 触发前一天事件
|
240
|
-
this.$emit('prev-day', this.baseDate)
|
241
|
-
// 触发变更事件
|
242
|
-
this.$emit('change', this.currentDate)
|
243
|
-
},
|
244
|
-
|
245
|
-
// 后一天
|
246
|
-
goToNextDay () {
|
247
|
-
const newDate = moment(this.currentDate).add(1, 'day')
|
248
|
-
if (this.config?.maxDate && newDate.isAfter(this.config.maxDate)) {
|
249
|
-
return
|
250
|
-
}
|
251
|
-
// 更新基准日期
|
252
|
-
this.baseDate = newDate.format('YYYY-MM-DD')
|
253
|
-
// 同时选中新的日期
|
254
|
-
this.currentDate = this.baseDate
|
255
|
-
this.$emit('update:modelValue', this.currentDate)
|
256
|
-
// 触发后一天事件
|
257
|
-
this.$emit('next-day', this.baseDate)
|
258
|
-
// 触发变更事件
|
259
|
-
this.$emit('change', this.currentDate)
|
260
|
-
},
|
261
|
-
|
262
|
-
// 前一周
|
263
|
-
goToPrevWeek () {
|
264
|
-
// 计算当前日期所在周的周一
|
265
|
-
const currentDay = moment(this.baseDate)
|
266
|
-
const dayOfWeek = currentDay.day() || 7 // 获取星期几,将周日的0转换为7
|
267
|
-
const mondayOfWeek = currentDay.clone().subtract(dayOfWeek - 1, 'day') // 减去相应的天数得到周一
|
268
|
-
|
269
|
-
// 前一周的周一
|
270
|
-
const newDate = mondayOfWeek.subtract(7, 'day')
|
271
|
-
|
272
|
-
if (this.config?.minDate && newDate.isBefore(this.config.minDate)) {
|
273
|
-
return
|
274
|
-
}
|
275
|
-
this.baseDate = newDate.format('YYYY-MM-DD')
|
276
|
-
this.$emit('prev-week', this.baseDate)
|
277
|
-
},
|
278
|
-
|
279
|
-
// 后一周
|
280
|
-
goToNextWeek () {
|
281
|
-
// 计算当前日期所在周的周一
|
282
|
-
const currentDay = moment(this.baseDate)
|
283
|
-
const dayOfWeek = currentDay.day() || 7 // 获取星期几,将周日的0转换为7
|
284
|
-
const mondayOfWeek = currentDay.clone().subtract(dayOfWeek - 1, 'day') // 减去相应的天数得到周一
|
285
|
-
// 后一周的周一
|
286
|
-
const newDate = mondayOfWeek.add(7, 'day')
|
287
|
-
if (this.config?.maxDate && newDate.isAfter(this.config.maxDate)) {
|
288
|
-
return
|
289
|
-
}
|
290
|
-
this.baseDate = newDate.format('YYYY-MM-DD')
|
291
|
-
this.$emit('next-week', this.baseDate)
|
292
|
-
}
|
293
|
-
}
|
294
|
-
}
|
295
|
-
</script>
|
296
|
-
|
297
|
-
<style scoped lang="less">
|
298
|
-
.x-timeline {
|
299
|
-
width: 100%;
|
300
|
-
border: 1px solid #f0f0f0;
|
301
|
-
border-radius: 2px;
|
302
|
-
}
|
303
|
-
|
304
|
-
.x-timeline-nav {
|
305
|
-
display: flex;
|
306
|
-
align-items: center;
|
307
|
-
padding: 16px;
|
308
|
-
border-bottom: 1px solid #f0f0f0;
|
309
|
-
width: 100%;
|
310
|
-
justify-content: space-between;
|
311
|
-
}
|
312
|
-
|
313
|
-
.timeline-dates {
|
314
|
-
display: flex;
|
315
|
-
flex: 1;
|
316
|
-
justify-content: space-around;
|
317
|
-
align-items: center;
|
318
|
-
margin: 0 16px;
|
319
|
-
}
|
320
|
-
|
321
|
-
.date-item {
|
322
|
-
padding: 8px 12px;
|
323
|
-
text-align: center;
|
324
|
-
cursor: pointer;
|
325
|
-
border-radius: 2px;
|
326
|
-
flex: 1;
|
327
|
-
margin: 0 8px;
|
328
|
-
transition: all 0.3s;
|
329
|
-
}
|
330
|
-
|
331
|
-
/* 非选中日期的悬浮效果 */
|
332
|
-
.date-item:hover:not(.ant-btn-disabled):not(.ant-btn-primary) {
|
333
|
-
background: #e6f7ff;
|
334
|
-
color: #1890ff;
|
335
|
-
}
|
336
|
-
|
337
|
-
/* 选中日期不需要悬浮效果 */
|
338
|
-
.date-item.ant-btn-primary:hover {
|
339
|
-
background: #1890ff;
|
340
|
-
}
|
341
|
-
|
342
|
-
.date-item.ant-btn-primary {
|
343
|
-
background: #0075FE !important;
|
344
|
-
color: #fff;
|
345
|
-
}
|
346
|
-
|
347
|
-
.date-item.ant-btn-primary .weekday,
|
348
|
-
.date-item.ant-btn-primary .date {
|
349
|
-
color: #ffffff !important;
|
350
|
-
}
|
351
|
-
|
352
|
-
/* 非选中日期悬浮时的字体颜色 */
|
353
|
-
.date-item:hover:not(.ant-btn-disabled):not(.ant-btn-primary) .weekday,
|
354
|
-
.date-item:hover:not(.ant-btn-disabled):not(.ant-btn-primary) .date {
|
355
|
-
color: #1890ff;
|
356
|
-
}
|
357
|
-
|
358
|
-
.date-item.date-weekend:not(.ant-btn-disabled):not(.ant-btn-primary) {
|
359
|
-
color: #ff4d4f;
|
360
|
-
}
|
361
|
-
|
362
|
-
.date-item.ant-btn-disabled {
|
363
|
-
color: rgba(0, 0, 0, 0.25);
|
364
|
-
background: #f5f5f5;
|
365
|
-
cursor: not-allowed;
|
366
|
-
}
|
367
|
-
|
368
|
-
.weekday {
|
369
|
-
font-size: 12px;
|
370
|
-
margin-bottom: 8px;
|
371
|
-
color: rgba(0, 0, 0, 0.45);
|
372
|
-
}
|
373
|
-
|
374
|
-
.date {
|
375
|
-
font-size: 14px;
|
376
|
-
color: rgba(0, 0, 0, 0.85);
|
377
|
-
}
|
378
|
-
|
379
|
-
/* Style1 样式配置 */
|
380
|
-
.xtimeline-style1 {
|
381
|
-
padding: 0px 4px;
|
382
|
-
|
383
|
-
.x-timeline-nav {
|
384
|
-
padding: 0px;
|
385
|
-
width: 100%;
|
386
|
-
height: 66px;
|
387
|
-
|
388
|
-
.timeline-dates {
|
389
|
-
margin: 0px;
|
390
|
-
width: 700px;
|
391
|
-
|
392
|
-
line-height: normal;
|
393
|
-
font-weight: 700;
|
394
|
-
letter-spacing: 0em;
|
395
|
-
|
396
|
-
}
|
397
|
-
|
398
|
-
.ant-btn {
|
399
|
-
border-radius: 6px;
|
400
|
-
border: 1px solid #CDCFD4;
|
401
|
-
font-weight: bold;
|
402
|
-
letter-spacing: 0em;
|
403
|
-
font-size: 16px;
|
404
|
-
font-family: "Source Han Sans";
|
405
|
-
line-height: normal;
|
406
|
-
opacity: 1;
|
407
|
-
box-sizing: border-box;
|
408
|
-
height: 75px;
|
409
|
-
width: 130px;
|
410
|
-
}
|
411
|
-
}
|
412
|
-
|
413
|
-
.date-item {
|
414
|
-
border-radius: 6px;
|
415
|
-
border: 1px solid #CDCFD4;
|
416
|
-
margin: 0px;
|
417
|
-
width: 100px;
|
418
|
-
opacity: 1;
|
419
|
-
box-sizing: border-box;
|
420
|
-
height: 66px;
|
421
|
-
|
422
|
-
.date {
|
423
|
-
font-weight: 400;
|
424
|
-
display: flex;
|
425
|
-
letter-spacing: 0px;
|
426
|
-
font-size: 16px;
|
427
|
-
font-family: "Source Han Sans";
|
428
|
-
align-items: center;
|
429
|
-
justify-content: center;
|
430
|
-
color: #313131;
|
431
|
-
}
|
432
|
-
|
433
|
-
.weekday {
|
434
|
-
font-weight: 700;
|
435
|
-
display: flex;
|
436
|
-
letter-spacing: 0px;
|
437
|
-
font-size: 20px;
|
438
|
-
font-family: "Source Han Sans";
|
439
|
-
align-items: center;
|
440
|
-
color: #313131;
|
441
|
-
justify-content: center;
|
442
|
-
margin-bottom: 0px !important;
|
443
|
-
}
|
444
|
-
.date-item.ant-btn-primary .weekday,
|
445
|
-
.date-item.ant-btn-primary .date {
|
446
|
-
color: #ffffff !important;
|
447
|
-
}
|
448
|
-
}
|
449
|
-
|
450
|
-
:deep(.ant-card-body) {
|
451
|
-
padding: 16px 8px 0px;
|
452
|
-
}
|
453
|
-
}
|
454
|
-
</style>
|
1
|
+
<template>
|
2
|
+
<!-- 时间轴主容器 -->
|
3
|
+
<div class="x-timeline" :class="wrapperClassObject">
|
4
|
+
<!-- 时间轴导航栏 -->
|
5
|
+
<div class="x-timeline-nav">
|
6
|
+
<!-- 导航按钮:前一周、前一天 -->
|
7
|
+
<a-button type="link" @click="goToPrevWeek">
|
8
|
+
<a-icon type="double-left"/>
|
9
|
+
{{ config?.prevWeekText || '前一周' }}
|
10
|
+
</a-button>
|
11
|
+
<a-button type="link" @click="goToPrevDay">
|
12
|
+
<a-icon type="left"/>
|
13
|
+
{{ config?.prevDayText || '前一天' }}
|
14
|
+
</a-button>
|
15
|
+
<!-- 日期显示区域 -->
|
16
|
+
<div class="timeline-dates">
|
17
|
+
<div
|
18
|
+
v-for="(date, index) in displayDates"
|
19
|
+
:key="index"
|
20
|
+
class="date-item"
|
21
|
+
:class="{
|
22
|
+
'ant-btn-primary': isCurrentDate(date),
|
23
|
+
'date-weekend': isWeekend(date),
|
24
|
+
'ant-btn-disabled': isDisabled(date)
|
25
|
+
}"
|
26
|
+
@click="selectDate(date)"
|
27
|
+
>
|
28
|
+
<div class="weekday">{{ getWeekDay(date) }}</div>
|
29
|
+
<div class="date">{{ formatDate(date) }}</div>
|
30
|
+
</div>
|
31
|
+
</div>
|
32
|
+
<!-- 导航按钮:后一天、后一周 -->
|
33
|
+
<a-button type="link" @click="goToNextDay">
|
34
|
+
{{ config?.nextDayText || '后一天' }}
|
35
|
+
<a-icon type="right"/>
|
36
|
+
</a-button>
|
37
|
+
<a-button type="link" @click="goToNextWeek">
|
38
|
+
{{ config?.nextWeekText || '后一周' }}
|
39
|
+
<a-icon type="double-right"/>
|
40
|
+
</a-button>
|
41
|
+
</div>
|
42
|
+
</div>
|
43
|
+
</template>
|
44
|
+
|
45
|
+
<script>
|
46
|
+
import moment from 'moment'
|
47
|
+
import { getConfigByName, runLogic } from '@vue2-client/services/api/common'
|
48
|
+
|
49
|
+
// 设置 moment 为中文语言环境
|
50
|
+
moment.locale('zh-cn')
|
51
|
+
|
52
|
+
export default {
|
53
|
+
name: 'XTimeline',
|
54
|
+
components: {},
|
55
|
+
props: {
|
56
|
+
// 当前选中日期,默认为空(不选中)
|
57
|
+
modelValue: {
|
58
|
+
type: String,
|
59
|
+
default: ''
|
60
|
+
},
|
61
|
+
// 配置参数名称,用于获取时间轴配置
|
62
|
+
queryParamsName: {
|
63
|
+
type: String,
|
64
|
+
default: ''
|
65
|
+
}
|
66
|
+
},
|
67
|
+
|
68
|
+
// 定义组件事件
|
69
|
+
emits: ['update:modelValue', 'change', 'prev-week', 'next-week', 'prev-day', 'next-day', 'init'],
|
70
|
+
|
71
|
+
data () {
|
72
|
+
return {
|
73
|
+
currentDate: this.modelValue, // 当前选中日期
|
74
|
+
baseDate: moment().format('YYYY-MM-DD'), // 基准日期,默认今天,用于计算显示范围
|
75
|
+
config: null,
|
76
|
+
disabledDates: [] // 禁用日期列表
|
77
|
+
}
|
78
|
+
},
|
79
|
+
computed: {
|
80
|
+
// 动态样式开关(与 XHDescriptions 思路一致):布尔开关 + size 派生类
|
81
|
+
wrapperClassObject () {
|
82
|
+
const attrs = this.$attrs || {}
|
83
|
+
const classes = {}
|
84
|
+
|
85
|
+
const booleanStyleKeys = [
|
86
|
+
'compact',
|
87
|
+
'bordered',
|
88
|
+
'highlight-weekend',
|
89
|
+
'dark-theme',
|
90
|
+
'style1'
|
91
|
+
]
|
92
|
+
booleanStyleKeys.forEach(key => {
|
93
|
+
const val = attrs[key]
|
94
|
+
const truthy = val === true || val === '' || val === 'true'
|
95
|
+
if (truthy) classes[`xtimeline-${key}`] = true
|
96
|
+
})
|
97
|
+
const size = attrs.size
|
98
|
+
if (size && typeof size === 'string') classes[`xtimeline-size-${size}`] = true
|
99
|
+
return classes
|
100
|
+
},
|
101
|
+
// 计算需要显示的日期范围,固定显示周一到周日
|
102
|
+
displayDates () {
|
103
|
+
const dates = []
|
104
|
+
// 计算当前日期所在周的周一
|
105
|
+
const currentDay = moment(this.baseDate)
|
106
|
+
const dayOfWeek = currentDay.day() || 7 // 获取星期几,将周日的0转换为7
|
107
|
+
const mondayOfWeek = currentDay.clone().subtract(dayOfWeek - 1, 'day') // 减去相应的天数得到周一
|
108
|
+
|
109
|
+
// 从周一开始,生成一周的日期
|
110
|
+
dates.push(mondayOfWeek.format('YYYY-MM-DD')) // 周一
|
111
|
+
for (let i = 1; i <= 6; i++) {
|
112
|
+
dates.push(mondayOfWeek.clone().add(i, 'day').format('YYYY-MM-DD'))
|
113
|
+
}
|
114
|
+
|
115
|
+
return dates
|
116
|
+
}
|
117
|
+
},
|
118
|
+
|
119
|
+
watch: {
|
120
|
+
// 监听外部传入的选中日期变化
|
121
|
+
modelValue: {
|
122
|
+
handler (newVal) {
|
123
|
+
this.currentDate = newVal
|
124
|
+
if (newVal) {
|
125
|
+
this.baseDate = newVal
|
126
|
+
}
|
127
|
+
},
|
128
|
+
immediate: true
|
129
|
+
},
|
130
|
+
// 监听配置参数名称变化
|
131
|
+
queryParamsName: {
|
132
|
+
handler (newValue) {
|
133
|
+
this.getData(newValue)
|
134
|
+
},
|
135
|
+
immediate: true
|
136
|
+
}
|
137
|
+
},
|
138
|
+
|
139
|
+
created () {
|
140
|
+
// 组件创建时获取配置
|
141
|
+
this.getData(this.queryParamsName)
|
142
|
+
},
|
143
|
+
|
144
|
+
methods: {
|
145
|
+
// 获取时间轴配置数据
|
146
|
+
async getData (data) {
|
147
|
+
getConfigByName(data, 'af-his', res => {
|
148
|
+
this.config = res
|
149
|
+
// 触发初始化事件,传递配置和默认日期
|
150
|
+
this.$emit('init', this.baseDate)
|
151
|
+
if (res.defaultValue) {
|
152
|
+
// 如果有默认值,则设置当前选中日期和基准日期
|
153
|
+
this.currentDate = res.defaultValue
|
154
|
+
this.baseDate = res.defaultValue
|
155
|
+
this.$emit('update:modelValue', res.defaultValue)
|
156
|
+
} else {
|
157
|
+
// 如果没有默认值,则设置今天日期为基准日期
|
158
|
+
this.modelValue = this.baseDate
|
159
|
+
}
|
160
|
+
|
161
|
+
// 执行配置中指定的业务逻辑
|
162
|
+
if (res.logicName) {
|
163
|
+
runLogic(res.logicName, res.parameter, 'af-his').then(result => {
|
164
|
+
if (result) {
|
165
|
+
this.handleLogicResult(result)
|
166
|
+
}
|
167
|
+
})
|
168
|
+
}
|
169
|
+
})
|
170
|
+
},
|
171
|
+
|
172
|
+
// 处理业务逻辑返回结果
|
173
|
+
handleLogicResult (result) {
|
174
|
+
if (result.disabledDates) {
|
175
|
+
this.disabledDates = result.disabledDates
|
176
|
+
}
|
177
|
+
if (result.currentDate) {
|
178
|
+
this.currentDate = result.currentDate
|
179
|
+
this.baseDate = result.currentDate
|
180
|
+
this.$emit('update:modelValue', result.currentDate)
|
181
|
+
}
|
182
|
+
},
|
183
|
+
|
184
|
+
// 格式化日期显示
|
185
|
+
formatDate (date) {
|
186
|
+
const format = this.config?.dateFormat || 'MM/DD'
|
187
|
+
return moment(date).format(format)
|
188
|
+
},
|
189
|
+
|
190
|
+
// 获取星期显示
|
191
|
+
getWeekDay (date) {
|
192
|
+
const format = this.config?.weekFormat || '周dd'
|
193
|
+
return moment(date).format(format)
|
194
|
+
},
|
195
|
+
|
196
|
+
// 判断是否为周末
|
197
|
+
isWeekend (date) {
|
198
|
+
if (!this.config?.highlightWeekend) return false
|
199
|
+
const day = moment(date).day()
|
200
|
+
return day === 0 || day === 6
|
201
|
+
},
|
202
|
+
|
203
|
+
// 判断日期是否禁用
|
204
|
+
isDisabled (date) {
|
205
|
+
if (this.config?.minDate && moment(date).isBefore(this.config.minDate)) {
|
206
|
+
return true
|
207
|
+
}
|
208
|
+
if (this.config?.maxDate && moment(date).isAfter(this.config.maxDate)) {
|
209
|
+
return true
|
210
|
+
}
|
211
|
+
return this.disabledDates.includes(date)
|
212
|
+
},
|
213
|
+
|
214
|
+
// 判断是否为当前选中日期
|
215
|
+
isCurrentDate (date) {
|
216
|
+
if (!this.currentDate) return false
|
217
|
+
return moment(date).format('YYYY-MM-DD') === moment(this.currentDate).format('YYYY-MM-DD')
|
218
|
+
},
|
219
|
+
|
220
|
+
// 选择日期
|
221
|
+
selectDate (date) {
|
222
|
+
if (this.isDisabled(date)) return
|
223
|
+
this.currentDate = date
|
224
|
+
this.$emit('update:modelValue', date)
|
225
|
+
this.$emit('change', date)
|
226
|
+
},
|
227
|
+
|
228
|
+
// 前一天
|
229
|
+
goToPrevDay () {
|
230
|
+
const newDate = moment(this.currentDate).subtract(1, 'day')
|
231
|
+
if (this.config?.minDate && newDate.isBefore(this.config.minDate)) {
|
232
|
+
return
|
233
|
+
}
|
234
|
+
// 更新基准日期
|
235
|
+
this.baseDate = newDate.format('YYYY-MM-DD')
|
236
|
+
// 同时选中新的日期
|
237
|
+
this.currentDate = this.baseDate
|
238
|
+
this.$emit('update:modelValue', this.currentDate)
|
239
|
+
// 触发前一天事件
|
240
|
+
this.$emit('prev-day', this.baseDate)
|
241
|
+
// 触发变更事件
|
242
|
+
this.$emit('change', this.currentDate)
|
243
|
+
},
|
244
|
+
|
245
|
+
// 后一天
|
246
|
+
goToNextDay () {
|
247
|
+
const newDate = moment(this.currentDate).add(1, 'day')
|
248
|
+
if (this.config?.maxDate && newDate.isAfter(this.config.maxDate)) {
|
249
|
+
return
|
250
|
+
}
|
251
|
+
// 更新基准日期
|
252
|
+
this.baseDate = newDate.format('YYYY-MM-DD')
|
253
|
+
// 同时选中新的日期
|
254
|
+
this.currentDate = this.baseDate
|
255
|
+
this.$emit('update:modelValue', this.currentDate)
|
256
|
+
// 触发后一天事件
|
257
|
+
this.$emit('next-day', this.baseDate)
|
258
|
+
// 触发变更事件
|
259
|
+
this.$emit('change', this.currentDate)
|
260
|
+
},
|
261
|
+
|
262
|
+
// 前一周
|
263
|
+
goToPrevWeek () {
|
264
|
+
// 计算当前日期所在周的周一
|
265
|
+
const currentDay = moment(this.baseDate)
|
266
|
+
const dayOfWeek = currentDay.day() || 7 // 获取星期几,将周日的0转换为7
|
267
|
+
const mondayOfWeek = currentDay.clone().subtract(dayOfWeek - 1, 'day') // 减去相应的天数得到周一
|
268
|
+
|
269
|
+
// 前一周的周一
|
270
|
+
const newDate = mondayOfWeek.subtract(7, 'day')
|
271
|
+
|
272
|
+
if (this.config?.minDate && newDate.isBefore(this.config.minDate)) {
|
273
|
+
return
|
274
|
+
}
|
275
|
+
this.baseDate = newDate.format('YYYY-MM-DD')
|
276
|
+
this.$emit('prev-week', this.baseDate)
|
277
|
+
},
|
278
|
+
|
279
|
+
// 后一周
|
280
|
+
goToNextWeek () {
|
281
|
+
// 计算当前日期所在周的周一
|
282
|
+
const currentDay = moment(this.baseDate)
|
283
|
+
const dayOfWeek = currentDay.day() || 7 // 获取星期几,将周日的0转换为7
|
284
|
+
const mondayOfWeek = currentDay.clone().subtract(dayOfWeek - 1, 'day') // 减去相应的天数得到周一
|
285
|
+
// 后一周的周一
|
286
|
+
const newDate = mondayOfWeek.add(7, 'day')
|
287
|
+
if (this.config?.maxDate && newDate.isAfter(this.config.maxDate)) {
|
288
|
+
return
|
289
|
+
}
|
290
|
+
this.baseDate = newDate.format('YYYY-MM-DD')
|
291
|
+
this.$emit('next-week', this.baseDate)
|
292
|
+
}
|
293
|
+
}
|
294
|
+
}
|
295
|
+
</script>
|
296
|
+
|
297
|
+
<style scoped lang="less">
|
298
|
+
.x-timeline {
|
299
|
+
width: 100%;
|
300
|
+
border: 1px solid #f0f0f0;
|
301
|
+
border-radius: 2px;
|
302
|
+
}
|
303
|
+
|
304
|
+
.x-timeline-nav {
|
305
|
+
display: flex;
|
306
|
+
align-items: center;
|
307
|
+
padding: 16px;
|
308
|
+
border-bottom: 1px solid #f0f0f0;
|
309
|
+
width: 100%;
|
310
|
+
justify-content: space-between;
|
311
|
+
}
|
312
|
+
|
313
|
+
.timeline-dates {
|
314
|
+
display: flex;
|
315
|
+
flex: 1;
|
316
|
+
justify-content: space-around;
|
317
|
+
align-items: center;
|
318
|
+
margin: 0 16px;
|
319
|
+
}
|
320
|
+
|
321
|
+
.date-item {
|
322
|
+
padding: 8px 12px;
|
323
|
+
text-align: center;
|
324
|
+
cursor: pointer;
|
325
|
+
border-radius: 2px;
|
326
|
+
flex: 1;
|
327
|
+
margin: 0 8px;
|
328
|
+
transition: all 0.3s;
|
329
|
+
}
|
330
|
+
|
331
|
+
/* 非选中日期的悬浮效果 */
|
332
|
+
.date-item:hover:not(.ant-btn-disabled):not(.ant-btn-primary) {
|
333
|
+
background: #e6f7ff;
|
334
|
+
color: #1890ff;
|
335
|
+
}
|
336
|
+
|
337
|
+
/* 选中日期不需要悬浮效果 */
|
338
|
+
.date-item.ant-btn-primary:hover {
|
339
|
+
background: #1890ff;
|
340
|
+
}
|
341
|
+
|
342
|
+
.date-item.ant-btn-primary {
|
343
|
+
background: #0075FE !important;
|
344
|
+
color: #fff;
|
345
|
+
}
|
346
|
+
|
347
|
+
.date-item.ant-btn-primary .weekday,
|
348
|
+
.date-item.ant-btn-primary .date {
|
349
|
+
color: #ffffff !important;
|
350
|
+
}
|
351
|
+
|
352
|
+
/* 非选中日期悬浮时的字体颜色 */
|
353
|
+
.date-item:hover:not(.ant-btn-disabled):not(.ant-btn-primary) .weekday,
|
354
|
+
.date-item:hover:not(.ant-btn-disabled):not(.ant-btn-primary) .date {
|
355
|
+
color: #1890ff;
|
356
|
+
}
|
357
|
+
|
358
|
+
.date-item.date-weekend:not(.ant-btn-disabled):not(.ant-btn-primary) {
|
359
|
+
color: #ff4d4f;
|
360
|
+
}
|
361
|
+
|
362
|
+
.date-item.ant-btn-disabled {
|
363
|
+
color: rgba(0, 0, 0, 0.25);
|
364
|
+
background: #f5f5f5;
|
365
|
+
cursor: not-allowed;
|
366
|
+
}
|
367
|
+
|
368
|
+
.weekday {
|
369
|
+
font-size: 12px;
|
370
|
+
margin-bottom: 8px;
|
371
|
+
color: rgba(0, 0, 0, 0.45);
|
372
|
+
}
|
373
|
+
|
374
|
+
.date {
|
375
|
+
font-size: 14px;
|
376
|
+
color: rgba(0, 0, 0, 0.85);
|
377
|
+
}
|
378
|
+
|
379
|
+
/* Style1 样式配置 */
|
380
|
+
.xtimeline-style1 {
|
381
|
+
padding: 0px 4px;
|
382
|
+
|
383
|
+
.x-timeline-nav {
|
384
|
+
padding: 0px;
|
385
|
+
width: 100%;
|
386
|
+
height: 66px;
|
387
|
+
|
388
|
+
.timeline-dates {
|
389
|
+
margin: 0px;
|
390
|
+
width: 700px;
|
391
|
+
|
392
|
+
line-height: normal;
|
393
|
+
font-weight: 700;
|
394
|
+
letter-spacing: 0em;
|
395
|
+
|
396
|
+
}
|
397
|
+
|
398
|
+
.ant-btn {
|
399
|
+
border-radius: 6px;
|
400
|
+
border: 1px solid #CDCFD4;
|
401
|
+
font-weight: bold;
|
402
|
+
letter-spacing: 0em;
|
403
|
+
font-size: 16px;
|
404
|
+
font-family: "Source Han Sans";
|
405
|
+
line-height: normal;
|
406
|
+
opacity: 1;
|
407
|
+
box-sizing: border-box;
|
408
|
+
height: 75px;
|
409
|
+
width: 130px;
|
410
|
+
}
|
411
|
+
}
|
412
|
+
|
413
|
+
.date-item {
|
414
|
+
border-radius: 6px;
|
415
|
+
border: 1px solid #CDCFD4;
|
416
|
+
margin: 0px;
|
417
|
+
width: 100px;
|
418
|
+
opacity: 1;
|
419
|
+
box-sizing: border-box;
|
420
|
+
height: 66px;
|
421
|
+
|
422
|
+
.date {
|
423
|
+
font-weight: 400;
|
424
|
+
display: flex;
|
425
|
+
letter-spacing: 0px;
|
426
|
+
font-size: 16px;
|
427
|
+
font-family: "Source Han Sans";
|
428
|
+
align-items: center;
|
429
|
+
justify-content: center;
|
430
|
+
color: #313131;
|
431
|
+
}
|
432
|
+
|
433
|
+
.weekday {
|
434
|
+
font-weight: 700;
|
435
|
+
display: flex;
|
436
|
+
letter-spacing: 0px;
|
437
|
+
font-size: 20px;
|
438
|
+
font-family: "Source Han Sans";
|
439
|
+
align-items: center;
|
440
|
+
color: #313131;
|
441
|
+
justify-content: center;
|
442
|
+
margin-bottom: 0px !important;
|
443
|
+
}
|
444
|
+
.date-item.ant-btn-primary .weekday,
|
445
|
+
.date-item.ant-btn-primary .date {
|
446
|
+
color: #ffffff !important;
|
447
|
+
}
|
448
|
+
}
|
449
|
+
|
450
|
+
:deep(.ant-card-body) {
|
451
|
+
padding: 16px 8px 0px;
|
452
|
+
}
|
453
|
+
}
|
454
|
+
</style>
|