t20-common-lib 0.9.13 → 0.10.0

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 (41) hide show
  1. package/package.json +64 -85
  2. package/packages/branch-bank-select/index.js +8 -8
  3. package/packages/branch-bank-select/src/main.vue +179 -179
  4. package/packages/common-collapse/index.js +8 -8
  5. package/packages/common-collapse/src/main.vue +147 -147
  6. package/packages/form-page/index.js +8 -8
  7. package/packages/form-page/src/main.vue +55 -55
  8. package/packages/input-number/index.js +8 -0
  9. package/packages/input-number/src/main.vue +184 -0
  10. package/packages/main-page/index.js +8 -8
  11. package/packages/main-page/src/main.vue +43 -43
  12. package/packages/multi-currency-statistics/index.js +8 -8
  13. package/packages/multi-currency-statistics/src/main.vue +229 -229
  14. package/packages/page-header/index.js +8 -8
  15. package/packages/page-header/src/main.vue +95 -95
  16. package/packages/statis-card/index.js +8 -8
  17. package/packages/statis-card/src/main.vue +250 -250
  18. package/packages/tab-page/index.js +8 -8
  19. package/packages/tab-page/src/main.vue +101 -101
  20. package/packages/tab-pane/index.js +8 -8
  21. package/packages/tab-pane/src/main.vue +185 -185
  22. package/packages/table-page/index.js +8 -8
  23. package/packages/table-page/src/main.vue +42 -42
  24. package/packages/theme-chalk/src/common/element-variables.scss +1045 -1045
  25. package/packages/theme-chalk/src/common/normalize.scss +869 -869
  26. package/packages/theme-chalk/src/index.scss +8 -8
  27. package/src/api/common.js +20 -20
  28. package/src/i18n.json +4 -4
  29. package/src/index.js +75 -71
  30. package/src/store/index.js +25 -25
  31. package/src/store/modules/user.js +42 -42
  32. package/src/utils/asciiWidth.js +107 -107
  33. package/src/utils/common.js +12 -12
  34. package/src/utils/date.js +43 -43
  35. package/src/utils/exportFile.js +6 -6
  36. package/src/utils/i18n/cn2hk.json +1270 -1270
  37. package/src/utils/i18n/index.js +69 -69
  38. package/src/utils/repairElementUI.js +141 -141
  39. package/src/utils/tableCellUtils.js +54 -54
  40. package/src/utils/tableheaderFilterpanel.vue +257 -257
  41. package/style/index.css +26 -0
@@ -1,251 +1,251 @@
1
- <template>
2
- <div class="statis-card flex-box">
3
- <div class="card-item flex-column" v-for="(item, index) in cardList" :key="item.id" :style="{
4
- '--bg': cardConfig[index].background,
5
- '--flex': cardConfig[index].flex
6
- }">
7
- <div class="header flex-box flex-lr">
8
- <!-- 动态判断:如果是图片路径则用 img,否则用 iconfont -->
9
- <div class="flex-box flex-v">
10
- <img
11
- class="icon"
12
- v-if="isImagePath(item.icon)"
13
- :src="resolveImagePath(item.icon)"
14
- alt="icon"
15
- >
16
- <i class="icon" v-else :class="item.icon"></i>
17
- <div class="title">{{ item.title }}</div>
18
- <div class="slot-dropdown">
19
- <slot :name="item.slotName" :item="item"></slot>
20
- </div>
21
- </div>
22
- <div class="slot-tab">
23
- <slot :name="item.slotTabName" :item="item"></slot>
24
- </div>
25
- </div>
26
- <div class="content flex-box">
27
- <template v-for="(conItem, index) in item.subList">
28
- <div class="content-item" :key="conItem.subId">
29
- <div class="content-item-title">{{ conItem.title }}
30
- <i v-if="conItem.tips" v-title="conItem.tips" class="n20-icon-xinxitishi"></i>
31
- </div>
32
- <!-- 支持三种情况:
33
- 1) 同时存在金额和笔数(优先使用 conItem.amount,如无则使用 conItem.value) -> 在一行显示:金额(格式化) / 笔数(单位)
34
- 2) 只有金额(conItem.amountFormat 为 true 或 amount/value 为数字) -> 使用过滤器格式化
35
- 3) 只有普通值 -> 直接显示 value + unit
36
- -->
37
- <div class="content-item-val" @click="$emit('click', conItem)">
38
- <template v-if="hasAmountAndCount(conItem)">
39
- <span class="count-val">{{ conItem.count }}<span class="content-item-unit">{{ conItem.countUnit || conItem.unit || '笔' }}</span></span>
40
- <span class="divider-inline"></span>
41
- {{ formatAmount(conItem, 'value') }}<span class="content-item-unit">{{ formatAmount(conItem, 'unit') }}</span>
42
- </template>
43
- <template v-else-if="conItem.amountFormat">
44
- {{ formatAmount(conItem, 'value') }}<span class="content-item-unit">{{ formatAmount(conItem, 'unit') }}</span>
45
- </template>
46
- <template v-else>
47
- {{ conItem.value }}<span class="content-item-unit">{{ conItem.unit }}</span>
48
- </template>
49
- </div>
50
- </div>
51
- <div
52
- v-if="index !== item.subList.length - 1"
53
- class="divider"
54
- :key="'divider-' + conItem.subId">
55
- </div>
56
- </template>
57
- </div>
58
- </div>
59
- </div>
60
- </template>
61
-
62
- <script>
63
- export default {
64
- name: 'StatisCard',
65
- props: {
66
- cardList: {
67
- type: Array,
68
- default: () => []
69
- },
70
- cardConfig: {
71
- type: Array,
72
- default: () => []
73
- }
74
- },
75
- filters: {
76
- /**
77
- * 格式化金额或返回原始值
78
- * @param {Number|String} value - 原始值
79
- * @param {String} type - 'value' 或 'unit'
80
- * @param {Boolean} isAmount - 是否作为金额处理
81
- */
82
- cardFormatAmount(value, type = 'value') {
83
- const language = 'zh'
84
- const unitMap = {
85
- 'en': {
86
- 'thousand': 'K',
87
- 'million': 'M',
88
- },
89
- 'zh': {
90
- 'thousand': '万元',
91
- 'million': '亿元',
92
- }
93
- }
94
-
95
- // 非数字直接返回原值(单位返回空字符串)
96
- if (typeof value !== 'number' || isNaN(value)) {
97
- return type === 'value' ? value || 0 : unitMap[language].thousand;
98
- }
99
-
100
- const amountInTenThousand = value / 10000;
101
-
102
- if (type === 'value') {
103
- // 返回格式化后的数值
104
- return amountInTenThousand >= 1000
105
- ? parseFloat((amountInTenThousand / 10000).toFixed(2))
106
- : parseFloat(amountInTenThousand.toFixed(2));
107
- } else {
108
- // 返回单位
109
- return amountInTenThousand >= 1000 ? unitMap[language].million : unitMap[language].thousand;
110
- }
111
- }
112
- },
113
- data() {
114
- return {
115
-
116
- }
117
- },
118
- methods: {
119
- isImagePath(icon) {
120
- return typeof icon === 'string' &&
121
- (icon.endsWith('.png') || icon.endsWith('.jpg') || icon.startsWith('@/') || icon.endsWith('.svg'));
122
- },
123
- // 解析Webpack别名路径(需配合require或import)
124
- resolveImagePath(path) {
125
- try {
126
- return require(`@/assets/${path}`);
127
- } catch (e) {
128
- console.warn('图片加载失败', path);
129
- return '';
130
- }
131
- }
132
- ,
133
- /**
134
- * 判断是否同时包含金额和笔数
135
- * 支持两种字段表示:优先使用 item.amount,其次使用 item.value
136
- */
137
- hasAmountAndCount(item) {
138
- if (!item) return false;
139
- const amount = item.amount !== undefined && item.amount !== null ? item.amount : item.value;
140
- // amount 必须是数字(或能被转为数字),count 存在(0 也认为有效)
141
- const hasAmount = amount !== undefined && amount !== null && !isNaN(Number(amount));
142
- const hasCount = item.count !== undefined && item.count !== null;
143
- return hasAmount && hasCount;
144
- },
145
- /**
146
- * 统一走过滤器来格式化金额/单位(保持与现有过滤器行为一致)
147
- */
148
- formatAmount(item, type = 'value') {
149
- const amount = item.amount !== undefined && item.amount !== null ? item.amount : item.value;
150
- // 通过 this.$options.filters 调用组件内定义的过滤器
151
- // 如果是请求单位并且调用方显式传了 unit 且标记了 amountFormat,优先返回该 unit(恢复原先逻辑)
152
- if (type === 'unit' && item && item.amountFormat && item.unit) {
153
- return item.unit;
154
- }
155
-
156
- if (this.$options && this.$options.filters && typeof this.$options.filters.cardFormatAmount === 'function') {
157
- try {
158
- return this.$options.filters.cardFormatAmount(amount, type);
159
- } catch (e) {
160
- // 兜底返回原值或空字符串
161
- return type === 'value' ? amount : '';
162
- }
163
- }
164
- return type === 'value' ? amount : '';
165
- }
166
- }
167
- }
168
- </script>
169
-
170
- <style lang="scss" scoped>
171
- .statis-card {
172
- width: 100%;
173
- gap: 10px;
174
- .card-item {
175
- padding: 16px;
176
- border-radius: 4px;
177
- position: relative;
178
- box-sizing: border-box;
179
- overflow: hidden;
180
- flex: var(--flex);
181
- background: var(--bg);
182
- .header {
183
- display: flex;
184
- align-items: center;
185
- margin-bottom: 16px;
186
-
187
- .icon {
188
- width: 14px;
189
- height: 14px;
190
- margin-right: 8px;
191
- }
192
-
193
- .title {
194
- font-size: 16px;
195
- color: #fff;
196
- white-space: nowrap;
197
- }
198
- .slot-dropdown {
199
- white-space: nowrap;
200
- cursor: pointer;
201
- ::v-deep .el-dropdown {
202
- font-size: 12px !important;
203
- color: #fff !important;
204
- }
205
-
206
- }
207
- }
208
-
209
- .content {
210
- padding: 0 22px;
211
- color: #fff;
212
- .content-item {
213
- &-title {
214
- font-size: 14px;
215
- margin-block: 8px;
216
- }
217
-
218
- &-val {
219
- cursor: pointer;
220
- font-size: 20px;
221
- text-align: center;
222
- }
223
-
224
- .divider-inline {
225
- margin: 0 6px;
226
- color: rgba(255,255,255,0.9);
227
- }
228
-
229
- .count-val {
230
- font-size: 20px;
231
- }
232
-
233
- &-unit {
234
- font-size: 14px;
235
- margin-left: 4px;
236
- }
237
- }
238
- .divider {
239
- height: 32px;
240
- width: 1px;;
241
- background-color: #fff;
242
- margin: auto;
243
- }
244
- }
245
- }
246
- .n20-icon-xinxitishi {
247
- color: #fff;
248
- }
249
- }
250
-
1
+ <template>
2
+ <div class="statis-card flex-box">
3
+ <div class="card-item flex-column" v-for="(item, index) in cardList" :key="item.id" :style="{
4
+ '--bg': cardConfig[index].background,
5
+ '--flex': cardConfig[index].flex
6
+ }">
7
+ <div class="header flex-box flex-lr">
8
+ <!-- 动态判断:如果是图片路径则用 img,否则用 iconfont -->
9
+ <div class="flex-box flex-v">
10
+ <img
11
+ class="icon"
12
+ v-if="isImagePath(item.icon)"
13
+ :src="resolveImagePath(item.icon)"
14
+ alt="icon"
15
+ >
16
+ <i class="icon" v-else :class="item.icon"></i>
17
+ <div class="title">{{ item.title }}</div>
18
+ <div class="slot-dropdown">
19
+ <slot :name="item.slotName" :item="item"></slot>
20
+ </div>
21
+ </div>
22
+ <div class="slot-tab">
23
+ <slot :name="item.slotTabName" :item="item"></slot>
24
+ </div>
25
+ </div>
26
+ <div class="content flex-box">
27
+ <template v-for="(conItem, index) in item.subList">
28
+ <div class="content-item" :key="conItem.subId">
29
+ <div class="content-item-title">{{ conItem.title }}
30
+ <i v-if="conItem.tips" v-title="conItem.tips" class="n20-icon-xinxitishi"></i>
31
+ </div>
32
+ <!-- 支持三种情况:
33
+ 1) 同时存在金额和笔数(优先使用 conItem.amount,如无则使用 conItem.value) -> 在一行显示:金额(格式化) / 笔数(单位)
34
+ 2) 只有金额(conItem.amountFormat 为 true 或 amount/value 为数字) -> 使用过滤器格式化
35
+ 3) 只有普通值 -> 直接显示 value + unit
36
+ -->
37
+ <div class="content-item-val" @click="$emit('click', conItem)">
38
+ <template v-if="hasAmountAndCount(conItem)">
39
+ <span class="count-val">{{ conItem.count }}<span class="content-item-unit">{{ conItem.countUnit || conItem.unit || '笔' }}</span></span>
40
+ <span class="divider-inline"></span>
41
+ {{ formatAmount(conItem, 'value') }}<span class="content-item-unit">{{ formatAmount(conItem, 'unit') }}</span>
42
+ </template>
43
+ <template v-else-if="conItem.amountFormat">
44
+ {{ formatAmount(conItem, 'value') }}<span class="content-item-unit">{{ formatAmount(conItem, 'unit') }}</span>
45
+ </template>
46
+ <template v-else>
47
+ {{ conItem.value }}<span class="content-item-unit">{{ conItem.unit }}</span>
48
+ </template>
49
+ </div>
50
+ </div>
51
+ <div
52
+ v-if="index !== item.subList.length - 1"
53
+ class="divider"
54
+ :key="'divider-' + conItem.subId">
55
+ </div>
56
+ </template>
57
+ </div>
58
+ </div>
59
+ </div>
60
+ </template>
61
+
62
+ <script>
63
+ export default {
64
+ name: 'StatisCard',
65
+ props: {
66
+ cardList: {
67
+ type: Array,
68
+ default: () => []
69
+ },
70
+ cardConfig: {
71
+ type: Array,
72
+ default: () => []
73
+ }
74
+ },
75
+ filters: {
76
+ /**
77
+ * 格式化金额或返回原始值
78
+ * @param {Number|String} value - 原始值
79
+ * @param {String} type - 'value' 或 'unit'
80
+ * @param {Boolean} isAmount - 是否作为金额处理
81
+ */
82
+ cardFormatAmount(value, type = 'value') {
83
+ const language = 'zh'
84
+ const unitMap = {
85
+ 'en': {
86
+ 'thousand': 'K',
87
+ 'million': 'M',
88
+ },
89
+ 'zh': {
90
+ 'thousand': '万元',
91
+ 'million': '亿元',
92
+ }
93
+ }
94
+
95
+ // 非数字直接返回原值(单位返回空字符串)
96
+ if (typeof value !== 'number' || isNaN(value)) {
97
+ return type === 'value' ? value || 0 : unitMap[language].thousand;
98
+ }
99
+
100
+ const amountInTenThousand = value / 10000;
101
+
102
+ if (type === 'value') {
103
+ // 返回格式化后的数值
104
+ return amountInTenThousand >= 1000
105
+ ? parseFloat((amountInTenThousand / 10000).toFixed(2))
106
+ : parseFloat(amountInTenThousand.toFixed(2));
107
+ } else {
108
+ // 返回单位
109
+ return amountInTenThousand >= 1000 ? unitMap[language].million : unitMap[language].thousand;
110
+ }
111
+ }
112
+ },
113
+ data() {
114
+ return {
115
+
116
+ }
117
+ },
118
+ methods: {
119
+ isImagePath(icon) {
120
+ return typeof icon === 'string' &&
121
+ (icon.endsWith('.png') || icon.endsWith('.jpg') || icon.startsWith('@/') || icon.endsWith('.svg'));
122
+ },
123
+ // 解析Webpack别名路径(需配合require或import)
124
+ resolveImagePath(path) {
125
+ try {
126
+ return require(`@/assets/${path}`);
127
+ } catch (e) {
128
+ console.warn('图片加载失败', path);
129
+ return '';
130
+ }
131
+ }
132
+ ,
133
+ /**
134
+ * 判断是否同时包含金额和笔数
135
+ * 支持两种字段表示:优先使用 item.amount,其次使用 item.value
136
+ */
137
+ hasAmountAndCount(item) {
138
+ if (!item) return false;
139
+ const amount = item.amount !== undefined && item.amount !== null ? item.amount : item.value;
140
+ // amount 必须是数字(或能被转为数字),count 存在(0 也认为有效)
141
+ const hasAmount = amount !== undefined && amount !== null && !isNaN(Number(amount));
142
+ const hasCount = item.count !== undefined && item.count !== null;
143
+ return hasAmount && hasCount;
144
+ },
145
+ /**
146
+ * 统一走过滤器来格式化金额/单位(保持与现有过滤器行为一致)
147
+ */
148
+ formatAmount(item, type = 'value') {
149
+ const amount = item.amount !== undefined && item.amount !== null ? item.amount : item.value;
150
+ // 通过 this.$options.filters 调用组件内定义的过滤器
151
+ // 如果是请求单位并且调用方显式传了 unit 且标记了 amountFormat,优先返回该 unit(恢复原先逻辑)
152
+ if (type === 'unit' && item && item.amountFormat && item.unit) {
153
+ return item.unit;
154
+ }
155
+
156
+ if (this.$options && this.$options.filters && typeof this.$options.filters.cardFormatAmount === 'function') {
157
+ try {
158
+ return this.$options.filters.cardFormatAmount(amount, type);
159
+ } catch (e) {
160
+ // 兜底返回原值或空字符串
161
+ return type === 'value' ? amount : '';
162
+ }
163
+ }
164
+ return type === 'value' ? amount : '';
165
+ }
166
+ }
167
+ }
168
+ </script>
169
+
170
+ <style lang="scss" scoped>
171
+ .statis-card {
172
+ width: 100%;
173
+ gap: 10px;
174
+ .card-item {
175
+ padding: 16px;
176
+ border-radius: 4px;
177
+ position: relative;
178
+ box-sizing: border-box;
179
+ overflow: hidden;
180
+ flex: var(--flex);
181
+ background: var(--bg);
182
+ .header {
183
+ display: flex;
184
+ align-items: center;
185
+ margin-bottom: 16px;
186
+
187
+ .icon {
188
+ width: 14px;
189
+ height: 14px;
190
+ margin-right: 8px;
191
+ }
192
+
193
+ .title {
194
+ font-size: 16px;
195
+ color: #fff;
196
+ white-space: nowrap;
197
+ }
198
+ .slot-dropdown {
199
+ white-space: nowrap;
200
+ cursor: pointer;
201
+ ::v-deep .el-dropdown {
202
+ font-size: 12px !important;
203
+ color: #fff !important;
204
+ }
205
+
206
+ }
207
+ }
208
+
209
+ .content {
210
+ padding: 0 22px;
211
+ color: #fff;
212
+ .content-item {
213
+ &-title {
214
+ font-size: 14px;
215
+ margin-block: 8px;
216
+ }
217
+
218
+ &-val {
219
+ cursor: pointer;
220
+ font-size: 20px;
221
+ text-align: center;
222
+ }
223
+
224
+ .divider-inline {
225
+ margin: 0 6px;
226
+ color: rgba(255,255,255,0.9);
227
+ }
228
+
229
+ .count-val {
230
+ font-size: 20px;
231
+ }
232
+
233
+ &-unit {
234
+ font-size: 14px;
235
+ margin-left: 4px;
236
+ }
237
+ }
238
+ .divider {
239
+ height: 32px;
240
+ width: 1px;;
241
+ background-color: #fff;
242
+ margin: auto;
243
+ }
244
+ }
245
+ }
246
+ .n20-icon-xinxitishi {
247
+ color: #fff;
248
+ }
249
+ }
250
+
251
251
  </style>
@@ -1,8 +1,8 @@
1
- import TabPage from './src/main';
2
-
3
- /* istanbul ignore next */
4
- TabPage.install = function(Vue) {
5
- Vue.component(TabPage.name, TabPage);
6
- };
7
-
8
- export default TabPage;
1
+ import TabPage from './src/main';
2
+
3
+ /* istanbul ignore next */
4
+ TabPage.install = function(Vue) {
5
+ Vue.component(TabPage.name, TabPage);
6
+ };
7
+
8
+ export default TabPage;