xt-element-ui 1.2.3 → 1.2.4

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.
@@ -0,0 +1,93 @@
1
+ <template>
2
+ <FlexBox
3
+ v-if="iconType=='border'"
4
+ class="xt-card-item is-border"
5
+ :class="[iconType=='border'?`is-${type}`:'']"
6
+ :style="cardItemStyle"
7
+ content="between"
8
+ >
9
+ <span class="item__label" v-if="title">
10
+ <slot name="label">{{ label }}</slot>
11
+ </span>
12
+ <span class="item__value">
13
+ <slot name="value">{{ value }}</slot>
14
+ </span>
15
+ <span class="item__unit">
16
+ <slot name="unit">{{ unit }}</slot>
17
+ </span>
18
+ </FlexBox>
19
+ <FlexBox
20
+ v-else
21
+ class="xt-card-item"
22
+ :direction="direction"
23
+ :content="contentAlign"
24
+ >
25
+ <slot name="icon">
26
+ <el-button :type="type" :circle="circle" :round="round" plain :icon="icon"></el-button>
27
+ </slot>
28
+ <div class="item__value">
29
+ <span class="value" :style="valueStyle">
30
+ <slot name="value">{{ label }}</slot>
31
+ </span>
32
+ <div class="unit">{{ value }}</div>
33
+ </div>
34
+ </FlexBox>
35
+ </template>
36
+ <script>
37
+ import FlexBox from '../xt-flex-box/index.vue'
38
+ export default {
39
+ name: "XtCardItem",
40
+ components: {
41
+ FlexBox
42
+ },
43
+ props: {
44
+ iconType: { default: "border" },
45
+ type: { default: "primary" },
46
+ label: {},
47
+ value: {},
48
+ unit: {},
49
+ icon: {},
50
+ iconAt: { default: "right" },
51
+ color: {
52
+ type: String,
53
+ default: ''
54
+ }
55
+ },
56
+ data() {
57
+ return {
58
+ circle: false,
59
+ round: false
60
+ }
61
+ },
62
+ computed: {
63
+ contentAlign() {
64
+ return this.iconAt == 'center' ? 'center' : 'start'
65
+ },
66
+ direction() {
67
+ const iconAtMap = {
68
+ left: 'row',
69
+ right: 'row-reverse',
70
+ top: 'column',
71
+ bottom: 'column-reverse'
72
+ }
73
+ return iconAtMap[this.iconAt]
74
+ },
75
+ cardItemStyle() {
76
+ if (this.iconType === 'border' && this.type === 'primary' && this.color) {
77
+ return {
78
+ '--xt-card-item-color': this.color
79
+ }
80
+ }
81
+ return {}
82
+ },
83
+ valueStyle() {
84
+ if (this.iconType !== 'border' && this.type === 'primary' && this.color) {
85
+ return {
86
+ color: this.color
87
+ }
88
+ }
89
+ return {}
90
+ }
91
+ }
92
+ }
93
+ </script>
@@ -1,93 +1,33 @@
1
1
  <template>
2
- <FlexBox
3
- v-if="iconType=='border'"
4
- class="xt-card-item is-border"
5
- :class="[iconType=='border'?`is-${type}`:'']"
6
- :style="cardItemStyle"
7
- content="between"
8
- >
9
- <span class="item__label" v-if="title">
10
- <slot name="label">{{ label }}</slot>
11
- </span>
12
- <span class="item__value">
13
- <slot name="value">{{ value }}</slot>
14
- </span>
15
- <span class="item__unit">
16
- <slot name="unit">{{ unit }}</slot>
17
- </span>
18
- </FlexBox>
19
- <FlexBox
20
- v-else
21
- class="xt-card-item"
22
- :direction="direction"
23
- :content="contentAlign"
24
- >
25
- <slot name="icon">
26
- <el-button :type="type" :circle="circle" :round="round" plain :icon="icon"></el-button>
27
- </slot>
28
- <div class="item__value">
29
- <span class="value" :style="valueStyle">
30
- <slot name="value">{{ label }}</slot>
31
- </span>
32
- <div class="unit">{{ value }}</div>
33
- </div>
34
- </FlexBox>
2
+ <ex-card class="xt-card-item" :bordered="false" :class="{ [`is-${type}`]: type ? true : false}">
3
+ <xt-text bold size="medium">{{ title }}</xt-text>
4
+ <xt-flex-box>
5
+ <div style="width: 50%;margin-bottom: 5px;">
6
+ <xt-text bold size="large" v-model="value" format="thousand" :type="type" :decimals="0"></xt-text>
7
+ <div style="margin: 5px 0;">
8
+ <xt-text size="small">较昨日</xt-text>
9
+ <xt-text v-model="change" format="normal" :type="diff > 0 ? 'success' : 'danger'" :suffix="diff > 0 ? '↑' : '↓'"></xt-text>
10
+ </div>
11
+ </div>
12
+ <div style="flex: 1; height: 100%;">
13
+ <xt-text size="extra-large" :type="type"><i class="el-icon-user"></i></xt-text>
14
+ </div>
15
+ </xt-flex-box>
16
+ </ex-card>
35
17
  </template>
36
18
  <script>
37
- import FlexBox from '../xt-flex-box/index.vue'
38
19
  export default {
39
- name: "XtCardItem",
40
- components: {
41
- FlexBox
42
- },
43
- props: {
44
- iconType: { default: "border" },
45
- type: { default: "primary" },
46
- label: {},
47
- value: {},
48
- unit: {},
49
- icon: {},
50
- iconAt: { default: "right" },
51
- color: {
52
- type: String,
53
- default: ''
54
- }
55
- },
56
- data() {
57
- return {
58
- circle: false,
59
- round: false
60
- }
61
- },
62
- computed: {
63
- contentAlign() {
64
- return this.iconAt == 'center' ? 'center' : 'start'
65
- },
66
- direction() {
67
- const iconAtMap = {
68
- left: 'row',
69
- right: 'row-reverse',
70
- top: 'column',
71
- bottom: 'column-reverse'
72
- }
73
- return iconAtMap[this.iconAt]
74
- },
75
- cardItemStyle() {
76
- if (this.iconType === 'border' && this.type === 'primary' && this.color) {
77
- return {
78
- '--xt-card-item-color': this.color
79
- }
80
- }
81
- return {}
20
+ name: "XtCardItem",
21
+ props: {
22
+ type: { type: String, default: "primary" },
23
+ title: { type: String, default: '' },
24
+ diff: { type: Number, default: 0 },
25
+ value: { type: Number, default: 0 },
26
+ change: { type: Number, default: 0 },
82
27
  },
83
- valueStyle() {
84
- if (this.iconType !== 'border' && this.type === 'primary' && this.color) {
28
+ data() {
85
29
  return {
86
- color: this.color
87
30
  }
88
- }
89
- return {}
90
31
  }
91
- }
92
32
  }
93
33
  </script>
@@ -0,0 +1,72 @@
1
+ @import '../../../styles/variables.scss';
2
+
3
+ .xt-card-item {
4
+ --xt-card-item-color: var(--xt-color-primary, #1890ff);
5
+
6
+ min-height: var(--xt-card-item-min-height, 40px);
7
+ }
8
+
9
+ .xt-card-item + .xt-card-item {
10
+ margin-top: var(--xt-card-item-gap, 10px);
11
+ }
12
+
13
+ .xt-card-item.is-border {
14
+ border-right: var(--xt-card-item-border-width, 3px) solid transparent;
15
+ background-color: var(--xt-color-bg-secondary, #f5f7fa);
16
+ }
17
+
18
+ .xt-card-item.is-border.is-primary {
19
+ border-right-color: var(--xt-card-item-color);
20
+ }
21
+
22
+ .xt-card-item.is-border.is-primary .item__value .value {
23
+ color: var(--xt-card-item-color);
24
+ }
25
+
26
+ .xt-card-item.is-border.is-success {
27
+ border-right-color: var(--xt-color-success, #67C23A);
28
+ }
29
+
30
+ .xt-card-item.is-border.is-success .item__value .value {
31
+ color: var(--xt-color-success, #67C23A);
32
+ }
33
+
34
+ .xt-card-item.is-border.is-warning {
35
+ border-right-color: var(--xt-color-warning, #E6A23C);
36
+ }
37
+
38
+ .xt-card-item.is-border.is-warning .item__value .value {
39
+ color: var(--xt-color-warning, #E6A23C);
40
+ }
41
+
42
+ .xt-card-item.is-border.is-danger {
43
+ border-right-color: var(--xt-color-danger, #F56C6C);
44
+ }
45
+
46
+ .xt-card-item.is-border.is-danger .item__value .value {
47
+ color: var(--xt-color-danger, #F56C6C);
48
+ }
49
+
50
+ .xt-card-item .item__value {
51
+ padding-right: 10px;
52
+ }
53
+
54
+ .xt-card-item .item__value .value {
55
+ font-weight: 600;
56
+ font-size: var(--xt-font-size-base, 14px);
57
+ }
58
+
59
+ .xt-card-item .item__value .unit {
60
+ font-size: var(--xt-font-size-small, 13px);
61
+ color: var(--xt-color-text-secondary, #909399);
62
+ }
63
+
64
+ .xt-card-item .item__label {
65
+ padding-left: 10px;
66
+ color: var(--xt-color-text-secondary, #909399);
67
+ }
68
+
69
+ .xt-card-item .item__unit {
70
+ padding-left: 5px;
71
+ color: var(--xt-color-text-secondary, #909399);
72
+ }
@@ -1,72 +1,83 @@
1
1
  @import '../../../styles/variables.scss';
2
2
 
3
3
  .xt-card-item {
4
- --xt-card-item-color: var(--xt-color-primary, #1890ff);
4
+ --xt-card-bg-color: var(--xt-card-bg-color, #ffffff);
5
+ --xt-card-border-color: var(--xt-card-border-color, #EBEEF5);
6
+ --xt-card-text-color: var(--xt-color-text-primary, #303133);
5
7
 
6
- min-height: var(--xt-card-item-min-height, 40px);
8
+ border-radius: var(--xt-card-border-radius, 4px);
9
+ box-shadow: var(--xt-card-shadow, 0 2px 12px 0 rgba(0, 0, 0, 0.1));
10
+ background-color: var(--xt-card-bg-color);
11
+ overflow: hidden;
12
+ color: var(--xt-card-text-color);
13
+ transition: var(--xt-transition-duration, 0.3s);
7
14
  }
8
15
 
9
- .xt-card-item + .xt-card-item {
10
- margin-top: var(--xt-card-item-gap, 10px);
16
+ .xt-card-item.is-primary {
17
+ --xt-card-bg-color: var(--xt-color-primary, #1890ff);
18
+ .card__header {
19
+ color: var(--xt-color-white, #ffffff);
20
+ }
11
21
  }
12
22
 
13
- .xt-card-item.is-border {
14
- border-right: var(--xt-card-item-border-width, 3px) solid transparent;
15
- background-color: var(--xt-color-bg-secondary, #f5f7fa);
16
- }
17
23
 
18
- .xt-card-item.is-border.is-primary {
19
- border-right-color: var(--xt-card-item-color);
24
+ .xt-card-item.is-success {
25
+ --xt-card-bg-color: var(--xt-color-success, #67c039);
26
+ .card__header {
27
+ color: var(--xt-color-white, #ffffff);
28
+ }
20
29
  }
21
30
 
22
- .xt-card-item.is-border.is-primary .item__value .value {
23
- color: var(--xt-card-item-color);
24
- }
25
31
 
26
- .xt-card-item.is-border.is-success {
27
- border-right-color: var(--xt-color-success, #67C23A);
28
- }
29
32
 
30
- .xt-card-item.is-border.is-success .item__value .value {
31
- color: var(--xt-color-success, #67C23A);
33
+ .xt-card-item.is-danger {
34
+ --xt-card-bg-color: var(--xt-color-danger, #f56c6c);
35
+ .card__header {
36
+ color: var(--xt-color-white, #ffffff);
37
+ }
32
38
  }
33
39
 
34
- .xt-card-item.is-border.is-warning {
35
- border-right-color: var(--xt-color-warning, #E6A23C);
36
- }
37
40
 
38
- .xt-card-item.is-border.is-warning .item__value .value {
39
- color: var(--xt-color-warning, #E6A23C);
40
- }
41
41
 
42
- .xt-card-item.is-border.is-danger {
43
- border-right-color: var(--xt-color-danger, #F56C6C);
42
+ .xt-card-item.is-warning {
43
+ --xt-card-bg-color: var(--xt-color-warning, #e6a23c);
44
+ .card__header {
45
+ color: var(--xt-color-white, #ffffff);
46
+ }
44
47
  }
45
48
 
46
- .xt-card-item.is-border.is-danger .item__value .value {
47
- color: var(--xt-color-danger, #F56C6C);
49
+
50
+ .xt-card-item .card__header {
51
+ padding: var(--xt-card-header-padding, 18px 20px);
52
+ box-sizing: border-box;
53
+ font-weight: 600;
54
+ font-size: var(--xt-font-size-medium, 16px);
48
55
  }
49
56
 
50
- .xt-card-item .item__value {
51
- padding-right: 10px;
57
+ .xt-card-item .card__body {
58
+ padding: var(--xt-card-padding, 20px);
52
59
  }
53
60
 
54
- .xt-card-item .item__value .value {
61
+ .xt-card-item .card__body .value {
62
+ font-size: var(--xt-font-size-large, 18px);
55
63
  font-weight: 600;
56
- font-size: var(--xt-font-size-base, 14px);
64
+ color: var(--xt-color-primary, #1890ff);
57
65
  }
58
66
 
59
- .xt-card-item .item__value .unit {
60
- font-size: var(--xt-font-size-small, 13px);
67
+ .xt-card-item .card__body .unit {
68
+ font-size: var(--xt-font-size-base, 14px);
61
69
  color: var(--xt-color-text-secondary, #909399);
70
+ margin-left: 4px;
62
71
  }
63
72
 
64
- .xt-card-item .item__label {
65
- padding-left: 10px;
66
- color: var(--xt-color-text-secondary, #909399);
73
+ .xt-card-item .value {
74
+ font-weight: 600;
67
75
  }
68
76
 
69
- .xt-card-item .item__unit {
70
- padding-left: 5px;
71
- color: var(--xt-color-text-secondary, #909399);
77
+ .xt-card-item .card__header + .card__body {
78
+ padding-top: 0;
79
+ }
80
+
81
+ .xt-card-item.noPadding .card__body {
82
+ padding: 0;
72
83
  }
@@ -74,9 +74,9 @@ export default {
74
74
  props: {
75
75
  theme: {
76
76
  type: String,
77
- default: 'light',
77
+ default: 'white',
78
78
  validator: (value) => {
79
- return ['light', 'dark', 'auto'].includes(value)
79
+ return ['white', 'dark', 'auto'].includes(value)
80
80
  }
81
81
  },
82
82
  size: {
@@ -5,13 +5,15 @@
5
5
  type ? 'xt-text--' + type : '',
6
6
  'xt-text--' + size,
7
7
  { 'xt-text--bold': bold },
8
- { 'xt-text--money': money }
8
+ { 'xt-text--money': format === 'money' }
9
9
  ]"
10
10
  :style="customStyle"
11
11
  >
12
+ <slot name="prefix">{{ prefix }}</slot>
12
13
  <slot>
13
- <template v-if="money && displayValue !== undefined">{{ displayValue }}</template>
14
+ <template v-if="formattedValue !== undefined">{{ formattedValue }}</template>
14
15
  </slot>
16
+ <slot name="suffix">{{ suffix }}</slot>
15
17
  </span>
16
18
  </template>
17
19
 
@@ -41,7 +43,15 @@ export default {
41
43
  type: [String, Number],
42
44
  default: ''
43
45
  },
44
- // 金额格式化相关属性
46
+
47
+ // 格式化模式:normal 普通 | thousand 千分位 | money 金额
48
+ format: {
49
+ type: String,
50
+ default: 'normal',
51
+ validator: (val) => ['normal', 'thousand', 'money'].includes(val)
52
+ },
53
+
54
+ // 兼容旧属性 money(老项目继续使用)
45
55
  money: {
46
56
  type: Boolean,
47
57
  default: false
@@ -78,6 +88,11 @@ export default {
78
88
  }
79
89
  },
80
90
  computed: {
91
+ // 兼容旧 money 属性:如果传了 money=true,自动切为金额模式
92
+ realFormat() {
93
+ return this.money ? 'money' : this.format
94
+ },
95
+
81
96
  customStyle() {
82
97
  const style = {}
83
98
  if (this.letterSpacing) {
@@ -85,41 +100,55 @@ export default {
85
100
  }
86
101
  return style
87
102
  },
88
- displayValue() {
89
- if (!this.money || this.value === '' || this.value === undefined || this.value === null) {
103
+
104
+ formattedValue() {
105
+ const fmt = this.realFormat
106
+ const { value } = this
107
+
108
+ if (value === '' || value === undefined || value === null) {
90
109
  return undefined
91
110
  }
92
-
93
- const numValue = typeof this.value === 'string' ? parseFloat(this.value) : this.value
94
-
111
+
112
+ const numValue = typeof value === 'string' ? parseFloat(value) : value
95
113
  if (isNaN(numValue)) {
96
- return this.value
114
+ return value
97
115
  }
98
-
116
+
99
117
  try {
100
- const formatter = new Intl.NumberFormat(this.locale, {
101
- style: 'currency',
102
- currency: this.currency,
103
- minimumFractionDigits: this.decimals,
104
- maximumFractionDigits: this.decimals,
105
- signDisplay: this.showSign ? 'always' : 'auto'
106
- })
107
-
108
- let result = formatter.format(numValue)
109
-
110
- // 处理前缀和后缀
111
- if (this.prefix) {
112
- result = this.prefix + result
113
- }
114
- if (this.suffix) {
115
- result = result + this.suffix
118
+ let result = ''
119
+ const signOpt = this.showSign ? 'always' : 'auto'
120
+
121
+ switch (fmt) {
122
+ // 千分位格式化(纯数字)
123
+ case 'thousand':
124
+ result = new Intl.NumberFormat(this.locale, {
125
+ minimumFractionDigits: this.decimals,
126
+ maximumFractionDigits: this.decimals,
127
+ signDisplay: signOpt
128
+ }).format(numValue)
129
+ break
130
+
131
+ // 金额格式化(原有逻辑)
132
+ case 'money':
133
+ result = new Intl.NumberFormat(this.locale, {
134
+ style: 'currency',
135
+ currency: this.currency,
136
+ minimumFractionDigits: this.decimals,
137
+ maximumFractionDigits: this.decimals,
138
+ signDisplay: signOpt
139
+ }).format(numValue)
140
+ break
141
+
142
+ // 普通文本,直接返回原值
143
+ default:
144
+ return undefined
116
145
  }
117
-
146
+
118
147
  return result
119
148
  } catch (e) {
120
- return this.value
149
+ return value
121
150
  }
122
151
  }
123
152
  }
124
153
  }
125
- </script>
154
+ </script>ss