xt-element-ui 1.1.0 → 1.1.2

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 (74) hide show
  1. package/lib/css/2.3f7aa432.css +1 -0
  2. package/lib/css/3.ffcc175d.css +1 -0
  3. package/lib/css/4.9abd1f2b.css +1 -0
  4. package/lib/css/5.1a31ed8a.css +1 -0
  5. package/lib/css/6.c2d0d77e.css +1 -0
  6. package/lib/index.common.0.js +120208 -0
  7. package/lib/index.common.2.js +1053 -0
  8. package/lib/index.common.3.js +996 -0
  9. package/lib/index.common.4.js +1108 -0
  10. package/lib/index.common.5.js +1009 -0
  11. package/lib/index.common.6.js +973 -0
  12. package/lib/index.common.js +8003 -211
  13. package/lib/index.css +1 -1
  14. package/lib/index.umd.0.js +120208 -0
  15. package/lib/index.umd.2.js +1053 -0
  16. package/lib/index.umd.3.js +996 -0
  17. package/lib/index.umd.4.js +1108 -0
  18. package/lib/index.umd.5.js +1009 -0
  19. package/lib/index.umd.6.js +973 -0
  20. package/lib/index.umd.js +8003 -211
  21. package/lib/index.umd.min.0.js +34 -0
  22. package/lib/index.umd.min.2.js +1 -0
  23. package/lib/index.umd.min.3.js +1 -0
  24. package/lib/index.umd.min.4.js +1 -0
  25. package/lib/index.umd.min.5.js +1 -0
  26. package/lib/index.umd.min.6.js +1 -0
  27. package/lib/index.umd.min.js +1 -1
  28. package/package.json +7 -3
  29. package/src/components/button/index.vue +5 -5
  30. package/src/components/button/style/index.scss +743 -90
  31. package/src/components/chart/ExBar.vue +203 -0
  32. package/src/components/chart/ExLine.vue +146 -0
  33. package/src/components/chart/ExMulti.vue +257 -0
  34. package/src/components/chart/ExPie.vue +159 -0
  35. package/src/components/chart/ExTrend.vue +121 -0
  36. package/src/components/chart/index.js +2 -0
  37. package/src/components/chart/index.vue +51 -0
  38. package/src/components/chart/pieList.vue +110 -0
  39. package/src/components/chart/theme/blue.js +91 -0
  40. package/src/components/chart/theme/dark.js +91 -0
  41. package/src/components/chart/theme/orange.js +92 -0
  42. package/src/components/chart/theme/starry.js +106 -0
  43. package/src/components/chart/theme/white.js +110 -0
  44. package/src/components/chart/utils.js +273 -0
  45. package/src/components/config-provider/index.vue +150 -51
  46. package/src/components/config-provider/style/index.scss +2 -2
  47. package/src/components/date-picker/SearchDate.vue +45 -0
  48. package/src/components/date-picker/index.js +2 -0
  49. package/src/components/date-picker/index.vue +131 -0
  50. package/src/components/date-picker/quarter.vue +152 -0
  51. package/src/components/grid-box/index.js +2 -0
  52. package/src/components/grid-box/index.vue +42 -0
  53. package/src/components/layout/BaseCollapse.vue +48 -0
  54. package/src/components/layout/ExFieldset.vue +204 -0
  55. package/src/components/page/index.js +0 -0
  56. package/src/components/page/index.vue +109 -0
  57. package/src/components/select-tree/index.js +0 -0
  58. package/src/components/select-tree/index.vue +386 -0
  59. package/src/components/table/ExCell.vue +27 -0
  60. package/src/components/table/ExColumn.vue +36 -0
  61. package/src/components/table/index.js +2 -0
  62. package/src/components/table/index.vue +731 -0
  63. package/src/components/table/processor.js +380 -0
  64. package/src/components/text/index.vue +79 -2
  65. package/src/components/text/style/index.scss +28 -6
  66. package/src/components/upload/index.js +2 -0
  67. package/src/components/upload/index.vue +225 -0
  68. package/src/components/upload/preview.vue +333 -0
  69. package/src/index.js +11 -2
  70. package/src/styles/css-variables.scss +238 -148
  71. package/src/styles/theme/background.scss +1 -1
  72. package/src/styles/theme/colors.scss +90 -1
  73. package/src/styles/variables.scss +1 -1
  74. package/src/components/button/style/index copy.scss +0 -221
@@ -1,23 +1,50 @@
1
- <template>
2
- <!-- 根据 tag 属性选择渲染的标签 -->
3
- <component
4
- :is="tag"
5
- :style="mergedStyle"
6
- :class="computedClass"
7
- v-bind="customAttrs"
8
- >
9
- <slot></slot>
10
- </component>
11
- </template>
12
-
13
1
  <script>
14
2
  export default {
15
3
  name: 'XtConfigProvider',
16
4
  inheritAttrs: false,
5
+ render(h) {
6
+ // Vue 2 不支持 Fragment,当 tag="template" 时需要特殊处理
7
+ // 如果设置了 proxyElement,则不渲染包裹元素,只渲染 slot 内容
8
+ if (this.tag === 'template' || this.proxyElement) {
9
+ // 渲染 slot 内容,如果只有一个元素则直接返回,否则包裹一个 div
10
+ const slotContent = this.$slots.default
11
+
12
+ if (!slotContent || slotContent.length === 0) {
13
+ return h('div')
14
+ }
15
+
16
+ // 如果 slot 只有一个元素,直接返回该元素
17
+ if (slotContent.length === 1) {
18
+ return slotContent[0]
19
+ }
20
+
21
+ // Vue 2 不支持多根节点,需要包裹一个 div
22
+ // 使用普通的 div 包裹,避免 display: contents 的兼容性问题
23
+ return h('div', {
24
+ class: 'xt-config-provider-wrapper',
25
+ attrs: {
26
+ 'data-theme': this.theme
27
+ }
28
+ }, slotContent)
29
+ }
30
+
31
+ // 正常渲染包裹元素
32
+ return h(this.tag, {
33
+ style: this.mergedStyle,
34
+ class: this.computedClass,
35
+ attrs: {
36
+ ...this.customAttrs,
37
+ 'data-theme': this.theme
38
+ }
39
+ }, this.$slots.default)
40
+ },
17
41
  props: {
18
42
  theme: {
19
43
  type: String,
20
- default: 'white'
44
+ default: 'light',
45
+ validator: (value) => {
46
+ return ['light', 'dark', 'auto'].includes(value)
47
+ }
21
48
  },
22
49
  size: {
23
50
  type: String,
@@ -25,7 +52,7 @@ export default {
25
52
  },
26
53
  primaryColor: {
27
54
  type: String,
28
- default: '#409EFF'
55
+ default: '#1890ff'
29
56
  },
30
57
  vars: {
31
58
  type: Object,
@@ -45,6 +72,11 @@ export default {
45
72
  injectColor: {
46
73
  type: Boolean,
47
74
  default: false
75
+ },
76
+ proxyElement: {
77
+ type: [HTMLElement, String, Object],
78
+ default: null,
79
+ description: '代理元素,将样式应用到该元素上。支持 HTMLElement、CSS选择器字符串或 ref 对象'
48
80
  }
49
81
  },
50
82
  computed: {
@@ -54,11 +86,14 @@ export default {
54
86
  if (this.primaryColor) {
55
87
  const color = this.normalizeColor(this.primaryColor)
56
88
  result['--xt-color-primary'] = color
89
+ // 浅色系列(与 css-variables.scss 保持一致)
57
90
  result['--xt-color-primary-light-3'] = this.lightenColor(color, 30)
58
91
  result['--xt-color-primary-light-5'] = this.lightenColor(color, 50)
59
92
  result['--xt-color-primary-light-7'] = this.lightenColor(color, 70)
60
93
  result['--xt-color-primary-light-8'] = this.lightenColor(color, 80)
61
94
  result['--xt-color-primary-light-9'] = this.lightenColor(color, 90)
95
+ // 深色系列
96
+ result['--xt-color-primary-dark-2'] = this.darkenColor(color, 20)
62
97
  }
63
98
 
64
99
  const sizeMap = {
@@ -71,37 +106,19 @@ export default {
71
106
  }
72
107
 
73
108
  if (this.theme === 'dark') {
74
- result['--xt-color-text-primary'] = 'rgba(255, 255, 255, 0.95)'
75
- result['--xt-color-text-regular'] = 'rgba(255, 255, 255, 0.8)'
76
- result['--xt-color-text-secondary'] = 'rgba(255, 255, 255, 0.6)'
77
- result['--xt-color-bg-primary'] = '#1f1f1f'
78
- result['--xt-color-bg-secondary'] = '#2d2d2d'
79
- result['--xt-color-bg-container'] = '#1f1f1f'
80
- result['--xt-color-border'] = '#434343'
81
- result['--xt-color-border-light'] = '#3d3d3d'
82
-
83
109
  if (this.injectBackground) {
84
- result.backgroundColor = result['--xt-color-bg-primary']
110
+ result.backgroundColor = result['--xt-color-bg-primary'] || '#141414'
85
111
  }
86
112
  if (this.injectColor) {
87
- result.color = result['--xt-color-text-primary']
113
+ result.color = result['--xt-color-text-primary'] || '#E5EAF3'
88
114
  }
89
115
  } else {
90
- // 恢复默认主题颜色(white 主题)
91
- result['--xt-color-text-primary'] = '#303133'
92
- result['--xt-color-text-regular'] = '#606266'
93
- result['--xt-color-text-secondary'] = '#909399'
94
- result['--xt-color-bg-primary'] = '#ffffff'
95
- result['--xt-color-bg-secondary'] = '#f5f7fa'
96
- result['--xt-color-bg-container'] = '#f5f7fa'
97
- result['--xt-color-border'] = '#DCDFE6'
98
- result['--xt-color-border-light'] = '#E4E7ED'
99
-
116
+ // 恢复默认主题颜色(light 主题)
100
117
  if (this.injectBackground) {
101
- result.backgroundColor = result['--xt-color-bg-primary']
118
+ result.backgroundColor = result['--xt-color-bg-primary'] || '#ffffff'
102
119
  }
103
120
  if (this.injectColor) {
104
- result.color = result['--xt-color-text-primary']
121
+ result.color = result['--xt-color-text-primary'] || '#2c3e50'
105
122
  }
106
123
  }
107
124
 
@@ -112,30 +129,35 @@ export default {
112
129
 
113
130
  if (this.tag !== 'template') {
114
131
  classes.push('xt-config-provider')
115
-
116
- if (this.theme === 'dark') {
117
- classes.push('xt-config-provider--dark')
118
- }
119
132
  }
120
133
 
121
134
  return classes
122
135
  },
123
136
  customAttrs() {
124
- const props = ['theme', 'size', 'primaryColor', 'vars', 'tag', 'injectBackground', 'injectColor']
137
+ const props = ['theme', 'size', 'primaryColor', 'vars', 'tag', 'injectBackground', 'injectColor', 'proxyElement']
125
138
  const attrs = {}
126
-
139
+
127
140
  for (const key in this.$attrs) {
128
141
  if (!props.includes(key)) {
129
142
  attrs[key] = this.$attrs[key]
130
143
  }
131
144
  }
132
-
145
+
133
146
  return attrs
134
147
  }
135
148
  },
149
+ mounted() {
150
+ this.applyProxyElementStyle()
151
+ },
152
+ updated() {
153
+ this.applyProxyElementStyle()
154
+ },
155
+ beforeUnmount() {
156
+ this.clearProxyElementStyle()
157
+ },
136
158
  methods: {
137
159
  normalizeColor(color) {
138
- if (!color) return '#409EFF'
160
+ if (!color) return '#1890ff'
139
161
 
140
162
  if (/^#[0-9A-Fa-f]{6}$/.test(color)) {
141
163
  return color
@@ -158,7 +180,7 @@ export default {
158
180
  }
159
181
 
160
182
  console.warn('[XtConfigProvider] 无法识别的颜色格式:', color)
161
- return '#409EFF'
183
+ return '#1890ff'
162
184
  },
163
185
 
164
186
  hexToRgb(hex) {
@@ -181,13 +203,90 @@ export default {
181
203
  const rgb = this.hexToRgb(hex)
182
204
  if (!rgb) return hex
183
205
 
184
- const amount = Math.round(2.55 * percent)
185
- const r = Math.min(255, rgb.r + amount)
186
- const g = Math.min(255, rgb.g + amount)
187
- const b = Math.min(255, rgb.b + amount)
206
+ // 使用与 Element Plus 一致的算法:将颜色与白色按比例混合
207
+ // percent 表示混合白色的比例(0-100),即 (1 - percent/100) 是原色比例
208
+ const ratio = percent / 100
209
+ const r = Math.round(rgb.r * (1 - ratio) + 255 * ratio)
210
+ const g = Math.round(rgb.g * (1 - ratio) + 255 * ratio)
211
+ const b = Math.round(rgb.b * (1 - ratio) + 255 * ratio)
188
212
 
189
213
  return this.rgbToHex(r, g, b)
214
+ },
215
+
216
+ darkenColor(hex, percent) {
217
+ const rgb = this.hexToRgb(hex)
218
+ if (!rgb) return hex
219
+
220
+ // 使用按比例混合黑色的方式变暗
221
+ // percent 表示混合黑色的比例(0-100)
222
+ const ratio = percent / 100
223
+ const r = Math.max(0, Math.round(rgb.r * (1 - ratio)))
224
+ const g = Math.max(0, Math.round(rgb.g * (1 - ratio)))
225
+ const b = Math.max(0, Math.round(rgb.b * (1 - ratio)))
226
+
227
+ return this.rgbToHex(r, g, b)
228
+ },
229
+
230
+ getProxyElement() {
231
+ const { proxyElement } = this
232
+
233
+ if (!proxyElement) return null
234
+
235
+ if (proxyElement instanceof HTMLElement) {
236
+ return proxyElement
237
+ }
238
+
239
+ if (typeof proxyElement === 'string') {
240
+ return document.querySelector(proxyElement)
241
+ }
242
+
243
+ if (proxyElement.$el) {
244
+ return proxyElement.$el
245
+ }
246
+
247
+ if (proxyElement.value && proxyElement.value instanceof HTMLElement) {
248
+ return proxyElement.value
249
+ }
250
+
251
+ console.warn('[XtConfigProvider] 无法解析 proxyElement:', proxyElement)
252
+ return null
253
+ },
254
+
255
+ applyProxyElementStyle() {
256
+ const element = this.getProxyElement()
257
+ if (!element) return
258
+
259
+ const style = this.mergedStyle
260
+
261
+ for (const key in style) {
262
+ element.style.setProperty(key, style[key])
263
+ }
264
+
265
+ // 设置 data-theme 属性
266
+ element.setAttribute('data-theme', this.theme)
267
+ },
268
+
269
+ clearProxyElementStyle() {
270
+ const element = this.getProxyElement()
271
+ if (!element) return
272
+
273
+ const style = this.mergedStyle
274
+
275
+ for (const key in style) {
276
+ element.style.removeProperty(key)
277
+ }
278
+
279
+ // 移除 data-theme 属性
280
+ element.removeAttribute('data-theme')
190
281
  }
191
282
  }
192
283
  }
193
- </script>
284
+ </script>
285
+
286
+ <style scoped>
287
+ /* 包裹容器样式 - 最小化影响布局 */
288
+ .xt-config-provider-wrapper {
289
+ width: 100%;
290
+ height: 100%;
291
+ }
292
+ </style>
@@ -6,7 +6,7 @@
6
6
  .xt-config-provider--dark {
7
7
  }
8
8
 
9
- .xt-config-provider--dark.xt-config-provider--with-bg {
10
- background-color: var(--xt-color-bg-primary, #1f1f1f);
9
+ .xt-config-provider--dark {
10
+ background-color: var(--xt-color-bg-primary, #0b141d);
11
11
  color: var(--xt-color-text-primary, rgba(255, 255, 255, 0.95));
12
12
  }
@@ -0,0 +1,45 @@
1
+ <template>
2
+ <el-form-item label="日期类型">
3
+ <el-select v-model="params.SearchCondition" style="width:120px;">
4
+ <el-option label="建档日期" value="建档日期"></el-option>
5
+ <el-option label="更新日期" value="更新日期"></el-option>
6
+ </el-select>
7
+ <el-select v-model="params.SearchType" style="width:120px;">
8
+ <el-option v-for="item in searchList" :key="item.value" :label="item.name" :value="item.value"></el-option>
9
+ </el-select>
10
+ <el-date-picker v-model="params.SearchValue" :style="'width:'+txtInputWidth+'px;'" value-format="yyyy-MM-dd" placeholder=""></el-date-picker>
11
+ </el-form-item>
12
+ </template>
13
+ <script>
14
+ export default {
15
+ name: "SearchDate",
16
+ props: {
17
+ searchList: {
18
+ type: Array,
19
+ default() {
20
+ return [];
21
+ }
22
+ },
23
+ params: {
24
+ type: Object,
25
+ default() {
26
+ return {
27
+ SearchType: "",
28
+ SearchCondition: "建档日期",
29
+ SearchValue: ""
30
+ };
31
+ }
32
+ },
33
+ /** 查询文本输入框宽度 */
34
+ txtInputWidth: {
35
+ type: Number,
36
+ default: 130
37
+ }
38
+ },
39
+ created() {
40
+ if (this.searchList.length > 0 && !this.params.SearchType) {
41
+ this.params.SearchType = this.searchList[0].value;
42
+ }
43
+ }
44
+ };
45
+ </script>
@@ -0,0 +1,2 @@
1
+ import XtDatePicker from './index.vue'
2
+ export default XtDatePicker
@@ -0,0 +1,131 @@
1
+ <template>
2
+ <div style="display:inline-block">
3
+ <FlexBox v-if="dateType=='quarter'" type="inline-flex" class="xt-date-picker" :class="{focus: isfocus}" :style="width?{width: `${width}px`}:{}">
4
+ <Quarter v-model="timeStart" :format="format" placeholder="开始时间" quarter-type="quarter-start" clearable></Quarter>
5
+ <span class="separator">{{ separator }}</span>
6
+ <Quarter v-model="timeEnd" :format="format" placeholder="结束时间" quarter-type="quarter-end" clearable></Quarter>
7
+ </FlexBox>
8
+ <FlexBox v-else type="inline-flex" class="xt-date" :class="{focus: isfocus}" :style="width?{width: `${width}px`}:{}">
9
+ <el-date-picker ref="timeStart" key="startSelect" v-model="timeStart" size="small" :disabled="disabled" append-to-body :picker-options="startTimeRange" :format="format" :type="dateType" placeholder="开始时间" clearable @blur="$emit('blur')" @focus="$emit('focus')"></el-date-picker>
10
+ <span class="separator">{{ separator }}</span>
11
+ <el-date-picker ref="timeEnd" key="endSelect" v-model="timeEnd" size="small" :disabled="disabled" append-to-body :picker-options="endTimeRange" :format="format" :type="dateType" placeholder="结束时间" clearable @blur="$emit('blur')" @focus="$emit('focus')"></el-date-picker>
12
+ </FlexBox>
13
+ </div>
14
+ </template>
15
+ <script>
16
+ const typeFormatEnum = {
17
+ datetime: "yyyy-MM-dd HH:mm", month: "yyyy-MM", year: "yyyy", date: "yyyy-MM-dd", quarter: "yyyy-Qq", week: "yyyy-WW"
18
+ };
19
+
20
+ import FlexBox from '../flex-box/index.vue'
21
+ import Quarter from "./quarter.vue";
22
+ export default {
23
+ name: "XtDatePicker",
24
+ components: {
25
+ FlexBox,
26
+ Quarter
27
+ },
28
+ model: {
29
+ prop: "value",
30
+ event: "change"
31
+ },
32
+ props: {
33
+ value: {},
34
+ dateType: {
35
+ type: String,
36
+ default: "date"
37
+ },
38
+ separator: {
39
+ type: String,
40
+ default: "至"
41
+ },
42
+ disabled: {
43
+ type: Boolean,
44
+ default: false
45
+ },
46
+ immediate: { // 是否直接初始化 参数
47
+ type: Boolean,
48
+ default: true
49
+ },
50
+ placeholder: {},
51
+ width: {
52
+ type: Number,
53
+ default: 280
54
+ }
55
+ },
56
+ data() {
57
+ return {
58
+ isfocus: false
59
+ };
60
+ },
61
+ computed: {
62
+ format() {
63
+ return typeFormatEnum[this.dateType] || "yyyy-MM-dd";
64
+ },
65
+ timeStart: {
66
+ get() {
67
+ return this.value && this.value[0];
68
+ },
69
+ set(v) {
70
+ this.$emit("update:value", [v, this.timeEnd]);
71
+ this.$emit("change", [v, this.timeEnd]);
72
+ }
73
+ },
74
+ timeEnd: {
75
+ get() {
76
+ return this.value && this.value[1];
77
+ },
78
+ set(v) {
79
+ this.$emit("update:value", [this.timeStart, v]);
80
+ this.$emit("change", [this.timeStart, v]);
81
+ }
82
+ },
83
+ startTimeRange() {
84
+ if (!this.timeEnd) return {};
85
+ const endTime = this.timeEnd.getTime();
86
+ return {
87
+ disabledDate: (time) => {
88
+ return time.getTime() > (endTime);
89
+ }
90
+ };
91
+ },
92
+ endTimeRange() {
93
+ if (!this.timeStart) return {};
94
+ const startTime = this.timeStart.getTime();
95
+ return {
96
+ disabledDate: (time) => {
97
+ return time.getTime() < (startTime);
98
+ }
99
+ };
100
+ }
101
+ },
102
+ methods: {
103
+ }
104
+ };
105
+ </script>
106
+ <style lang="scss" scoped>
107
+ .xt-date-picker{
108
+ width: 100%;
109
+ border-radius: 4px;
110
+ border: 1px solid #DCDFE6;
111
+
112
+ &.focus{
113
+ border-color: #1890FF;
114
+ }
115
+
116
+ ::v-deep .el-picker-panel{
117
+ position: absolute;
118
+ z-index: 401;
119
+ }
120
+
121
+ ::v-deep .el-input__inner{
122
+ border: none;
123
+ padding: 0;
124
+ text-align: center;
125
+ }
126
+
127
+ ::v-deep .el-input__prefix{
128
+ display: none;
129
+ }
130
+ }
131
+ </style>
@@ -0,0 +1,152 @@
1
+ <template>
2
+ <el-popover v-model="popoverVisible" trigger="click" :disabled="disabled" transition="el-zoom-in-top" :placement="placement" :width="popoverWidth" @hide="handleBlur">
3
+ <div class="quarter-wrapper">
4
+ <BaseFlexBox content="between">
5
+ <i class="el-icon-d-arrow-left" @click="prev"></i>
6
+ <span>{{ selectYear }}</span>
7
+ <i class="el-icon-d-arrow-right" @click="after"></i>
8
+ </BaseFlexBox>
9
+ <BaseFlexBox content="between" style="margin-top: 10px">
10
+ <el-button v-for="item in quarterList" :key="item.value" :disabled="getDisable(item)" :type="currentyear==selectYear&&item.value == currentQuarter ?'primary':''" size="mini" round @click="setCurrent(item)">{{ item.label }}</el-button>
11
+ </BaseFlexBox>
12
+ </div>
13
+ <el-input slot="reference" ref="reference" size="small" :value="quarterLabel" readonly :title="value" :placeholder="placeholder" prefix-icon="el-icon-date" clearable />
14
+ </el-popover>
15
+ </template>
16
+
17
+ <script>
18
+ import BaseFlexBox from "../flex-box/index.vue";
19
+ import dateFns from "date-fns";
20
+ export default {
21
+ name: "DateQuarter",
22
+ components: {
23
+ BaseFlexBox
24
+ },
25
+ model: {
26
+ props: "value",
27
+ event: "change"
28
+ },
29
+ props: {
30
+ value: {},
31
+ quarterType: { // value绑定值类型 1.quarter为时返回当前时间 2.quarter-start时返回季的开始时间 3. quarter-end时返回季的结束时间
32
+ type: String,
33
+ default: "quarter"
34
+ },
35
+ placement: {
36
+ type: String,
37
+ default: "bottom-start"
38
+ },
39
+ // valueFormat: {
40
+ // type: String,
41
+ // default: "yyyy-Qq"
42
+ // },
43
+ format: { // 同时支持字符串 "yyyy-Qq" 使用小写q进行格式化数据
44
+ type: String,
45
+ default: "yy-Qq"
46
+ },
47
+ popoverWidth: Number,
48
+ placeholder: {},
49
+ pickerOptions: {
50
+ type: Object,
51
+ default: () => {
52
+ return {
53
+ disabledDate: () => {
54
+ return false;
55
+ }
56
+ };
57
+ }
58
+ },
59
+ disabled: {}
60
+ },
61
+ data() {
62
+ const dateVal = this.getQuarterDate(this.value);
63
+ const currentyear = dateVal ? dateVal.getFullYear() : "";
64
+ const month = dateVal ? dateVal.getMonth() : "";
65
+ const selectYear = dateVal ? dateVal.getFullYear() : new Date().getFullYear();
66
+ return {
67
+ dateVal: dateVal,
68
+ currentyear: currentyear,
69
+ currentQuarter: dateFns.getQuarter(dateVal),
70
+ selectYear: selectYear,
71
+ currentMonth: month,
72
+ popoverVisible: false,
73
+ quarterList: [
74
+ { label: "Q1", value: 1 },
75
+ { label: "Q2", value: 2 },
76
+ { label: "Q3", value: 3 },
77
+ { label: "Q4", value: 4 }
78
+ ]
79
+ };
80
+ },
81
+ computed: {
82
+ diffQuarter() {
83
+ return (this.selectYear - this.currentyear) * 4 - this.currentQuarter;
84
+ },
85
+ quarterLabel: {
86
+ get() {
87
+ if (!this.currentyear || !this.currentQuarter) {
88
+ return "";
89
+ }
90
+ return this.getFormatVal();
91
+ }
92
+ }
93
+ },
94
+ methods: {
95
+ getQuarterDate(val) {
96
+ if (!val) return null;
97
+ if (this.quarterType == "quarter-start") {
98
+ return dateFns.startOfQuarter(val);
99
+ } else if (this.quarterType == "quarter-end") {
100
+ return dateFns.endOfQuarter(val);
101
+ } else {
102
+ const currentQuarter = dateFns.getQuarter(val);
103
+ return dateFns.setQuarter(this.value, currentQuarter);
104
+ }
105
+ },
106
+ getDisable(it) {
107
+ },
108
+ handleChangeVal(v) {
109
+ },
110
+ getFormatVal() {
111
+ if (!this.format) {
112
+ return `${this.currentyear}-Q${this.currentQuarter}`;
113
+ }
114
+ const formatMap = {
115
+ y: this.currentyear,
116
+ q: this.currentQuarter
117
+ };
118
+ const val = this.format.replace(/(y|q)+/g, (result, key) => {
119
+ const value = formatMap[key];
120
+ return value || "";
121
+ });
122
+ return val;
123
+ },
124
+ setCurrent(item) {
125
+ if (!this.dateVal) {
126
+ this.dateVal = new Date();
127
+ }
128
+ this.dateVal.setFullYear(this.selectYear);
129
+ this.dateVal = dateFns.setQuarter(this.dateVal, item.value);
130
+ this.$emit("change", this.dateVal);
131
+ this.currentQuarter = item.value;
132
+ this.currentyear = this.selectYear;
133
+ this.popoverVisible = false;
134
+ },
135
+ after() {
136
+ this.dateVal.setFullYear(this.dateVal.getFullYear() + 1);
137
+ this.selectYear = this.dateVal.getFullYear();
138
+ },
139
+ prev() {
140
+ this.dateVal.setFullYear(this.dateVal.getFullYear() - 1);
141
+ this.selectYear = this.dateVal.getFullYear();
142
+ },
143
+ handleBlur() {
144
+ this.$refs.reference.blur();
145
+ }
146
+ }
147
+ };
148
+ </script>
149
+
150
+ <style>
151
+
152
+ </style>
@@ -0,0 +1,2 @@
1
+ import XtGridBox from './index.vue'
2
+ export default XtGridBox
@@ -0,0 +1,42 @@
1
+ <template>
2
+ <div class="ex-grid-box" :style="styleAttrs">
3
+ <slot></slot>
4
+ </div>
5
+ </template>
6
+
7
+ <script>
8
+ export default {
9
+ name: "XtGridBox",
10
+ props: {
11
+ columns: {
12
+ type: [String, Array], // ["1fr","2fr", "20%"]
13
+ default: "1fr"
14
+ },
15
+ rows: { // 1
16
+ type: [String, Array], // ["1fr","2fr", "20%"]
17
+ default: "1fr"
18
+ },
19
+ gap: { type: String, default: "" }
20
+ },
21
+ computed: {
22
+ styleAttrs() {
23
+ const gridTemplateRows = (typeof this.rows !== "string") ? this.rows.join(" ") : this.rows;
24
+ const gridTemplateColumns = (typeof this.columns !== "string") ? this.columns.join(" ") : this.columns;
25
+ return this.gap ? {
26
+ gridTemplateColumns,
27
+ gridTemplateRows,
28
+ gap: this.gap.toString().split(" ").map(_getGap).join(" ")
29
+ } : {
30
+ gridTemplateColumns,
31
+ gridTemplateRows
32
+ };
33
+ }
34
+ }
35
+ };
36
+ </script>
37
+
38
+ <style lang="scss">
39
+ .ex-grid-box{
40
+ display: grid;
41
+ }
42
+ </style>