chain-saasui 1.0.12-alpha.5 → 1.0.12
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/COMPONENTS.md +76 -11
- package/components/css/form.scss +60 -4
- package/components/css/group.scss +7 -18
- package/components/css/index.scss +1 -0
- package/components/css/itemlist.scss +5 -2
- package/components/css/pagetable.scss +8 -0
- package/components/css/scroll.scss +25 -0
- package/components/css/stepsNew.scss +7 -1
- package/components/css/tooltipWrap.scss +4 -4
- package/components/src/SForm/SDatePicker/index.vue +34 -6
- package/components/src/SForm/SInputSelect/index.vue +141 -0
- package/components/src/SForm/SRadio/index.vue +1 -1
- package/components/src/SForm/index.js +1 -0
- package/components/src/SGroup/index.vue +1 -1
- package/components/src/SInputDialog/InputDialog.vue +7 -2
- package/components/src/SPage/PageButtons/index.vue +89 -0
- package/components/src/SPage/Pagetable.vue +15 -2
- package/components/src/SPage/index.js +1 -0
- package/components/src/SStepsNew/index.vue +5 -1
- package/components/src/STable/STablecolumn.vue +117 -3
- package/components/src/STable/SUtable.vue +5 -4
- package/components/src/STooltipWrap/index.vue +6 -20
- package/components/src/directives/thinScroll.js +43 -0
- package/components/src/index.js +10 -2
- package/lib/css/index.css +1 -1
- package/lib/saasui.common.js +1 -1
- package/lib/styles/main.css +1 -0
- package/package.json +1 -1
- package/components/src/STable/SUtableColumn.vue +0 -177
package/COMPONENTS.md
CHANGED
|
@@ -47,21 +47,43 @@
|
|
|
47
47
|
|
|
48
48
|
### `<s-table-buttons>`
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
行内操作按钮组,**表格操作列强制使用**(禁止手写 `el-button` 列表)。默认把操作收进「操作 ⏷」下拉,`mode="flat"` 则平铺展示。点击 emit `@action(action, row)`,页面在一个 `handleAction` 里按 `action` 分发。
|
|
51
|
+
|
|
52
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
53
|
+
| -------- | ------- | ---------------------- | ----------------------------------------------------------- |
|
|
54
|
+
| list | Array | [] | 按钮配置数组,见下方字段 |
|
|
55
|
+
| row | Object | {} | 当前行,透传给 `show/tip/disabled` 等函数,并随 `@action` 带出(含 `row._index`) |
|
|
56
|
+
| index | Number | 0 | 行下标,点击时写入 `row._index` |
|
|
57
|
+
| mode | String | 'dropdown' | `dropdown`=收进「操作」下拉;`flat`=平铺展示所有按钮 |
|
|
58
|
+
| text | String | $t('TableData.action') | `mode='dropdown'` 时下拉触发按钮的文案 |
|
|
59
|
+
| showIcon | Boolean | true | 下拉触发按钮是否带 ⏷ 箭头 |
|
|
60
|
+
| btnProps | Object | { type: 'text' } | 触发按钮 / 各按钮的默认属性 |
|
|
61
|
+
|
|
62
|
+
**`list` 项字段:**
|
|
63
|
+
|
|
64
|
+
| 字段 | 类型 | 说明 |
|
|
65
|
+
| ------- | --------------------------- | -------------------------------------------------------------- |
|
|
66
|
+
| label | String | 按钮文案 |
|
|
67
|
+
| action | String | 点击 emit 的命令(`@action` 第一个参数),页面按它分发 |
|
|
68
|
+
| show | Boolean \| (row) => boolean | 是否显示,省略默认显示;函数入参当前行 |
|
|
69
|
+
| tip | String \| (row) => string | 悬浮提示内容(`dropdown` 模式);函数入参当前行 |
|
|
70
|
+
| showTip | Boolean \| (row) => boolean | 是否显示 tip(配合 `tip`) |
|
|
71
|
+
| attrs | Object | 透传到按钮/下拉项(`type`/`icon` 等);`attrs.disabled` 支持 Boolean 或 `(row) => boolean` |
|
|
51
72
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
`list` 项:`{ label, onClick, show?, tip?, attrs? }`,`show` 支持布尔或函数。
|
|
73
|
+
```js
|
|
74
|
+
// 配置示例:show / attrs.disabled 支持函数入参 row,按权限/行状态动态控制
|
|
75
|
+
actionList: [
|
|
76
|
+
{ label: this.$t('buttonGroup.edit'), action: 'edit', show: () => this.checkPermi(['xxx:edit']) },
|
|
77
|
+
{ label: this.$t('buttonGroup.del'), action: 'del', show: row => row.editable, attrs: { disabled: row => row.locked } },
|
|
78
|
+
]
|
|
79
|
+
```
|
|
60
80
|
|
|
61
81
|
```vue
|
|
62
|
-
<s-table-buttons :list="actionList" :row="row" @action="handleAction" />
|
|
82
|
+
<s-table-buttons :list="actionList" :row="row" :index="$index" @action="handleAction" />
|
|
63
83
|
```
|
|
64
84
|
|
|
85
|
+
`handleAction(action, row)` 里 `switch (action)` 分发到各方法。
|
|
86
|
+
|
|
65
87
|
---
|
|
66
88
|
|
|
67
89
|
## 二、分页 / 布局 / 容器
|
|
@@ -120,7 +142,50 @@
|
|
|
120
142
|
|
|
121
143
|
### `<s-page-button>`
|
|
122
144
|
|
|
123
|
-
|
|
145
|
+
页面级按钮区**布局容器**(底层):`gap`(默认 8) / `direction`(`horizontal`\|`vertical`) / `align`(默认 center) / `wrap`。只管间距对齐,内容全走插槽。一般不直接用,优先用下面的 `s-page-buttons`。
|
|
146
|
+
|
|
147
|
+
### `<s-page-buttons>`
|
|
148
|
+
|
|
149
|
+
列表页操作栏的 **JSON 配置版**(内部包了 `s-page-button` + `s-space`):左侧主操作 `buttons`、右侧次操作 `rightButtons`。权限写进 `show`;上传/徽标等复杂按钮用插槽兜底。
|
|
150
|
+
|
|
151
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
152
|
+
| ------------ | ----- | --- | ---------------------------------------------- |
|
|
153
|
+
| buttons | Array | [] | 左侧主操作,渲染 `el-button`;见下方 item 字段 |
|
|
154
|
+
| rightButtons | Array | [] | 右侧次操作,渲染 `s-button-text`(有 `path` 则渲染成跳转 link) |
|
|
155
|
+
|
|
156
|
+
**item 字段:**`{ label, click, show, icon, type, disabled, loading, id, path, children }`
|
|
157
|
+
|
|
158
|
+
| 字段 | 类型 | 说明 |
|
|
159
|
+
| -------- | -------------------------- | ------------------------------------------------------------- |
|
|
160
|
+
| label | String | 按钮文案 |
|
|
161
|
+
| click | Function | 点击回调(`() => vm.xxx()`) |
|
|
162
|
+
| show | Boolean \| () => boolean | 是否显示,缺省显示;**权限写这里**:`show: () => vm.checkPermi(['xxx:add'])` |
|
|
163
|
+
| icon | String | 图标 class |
|
|
164
|
+
| type | String | `el-button` 的 type |
|
|
165
|
+
| disabled | Boolean | 禁用 |
|
|
166
|
+
| loading | Boolean | 加载态(仅左侧 `buttons`) |
|
|
167
|
+
| id | String | dom id(埋点等) |
|
|
168
|
+
| path | String | 仅 `rightButtons`:跳转路由,渲染成 link |
|
|
169
|
+
| children | Array | 传了则该项渲染成**下拉**,children 项:`{ label, click, disabled, show }`;可见子项为空(空数组或全被 `show` 过滤)则整项隐藏 |
|
|
170
|
+
|
|
171
|
+
**插槽:** 默认插槽(替代 `buttons`,放上传/徽标等复杂左侧按钮)、`#right`(追加在 `rightButtons` 之后)。传了插槽就用插槽。
|
|
172
|
+
|
|
173
|
+
```js
|
|
174
|
+
// 配置示例:show 收口权限,children 渲染下拉
|
|
175
|
+
buttons: [
|
|
176
|
+
{ label: this.$t('buttonGroup.add'), type: 'primary', icon: 'smart-add', show: () => this.checkPermi(['xxx:add']), click: () => this.handleAdd() },
|
|
177
|
+
{ label: this.$t('buttonGroup.import'), show: () => this.checkPermi(['xxx:import']), children: [
|
|
178
|
+
{ label: this.$t('saasmenu.xxx'), click: () => this.handleImport() },
|
|
179
|
+
] },
|
|
180
|
+
]
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
```vue
|
|
184
|
+
<s-page-buttons :buttons="buttons" :right-buttons="rightButtons">
|
|
185
|
+
<!-- 复杂左侧按钮(上传等)用默认插槽;右侧追加用 #right -->
|
|
186
|
+
<template #right><!-- 自定义右侧内容 --></template>
|
|
187
|
+
</s-page-buttons>
|
|
188
|
+
```
|
|
124
189
|
|
|
125
190
|
### `<s-card>`
|
|
126
191
|
|
package/components/css/form.scss
CHANGED
|
@@ -23,6 +23,45 @@
|
|
|
23
23
|
width: 100%;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
// input-select 可输入可选择
|
|
27
|
+
.el-input-group__prepend {
|
|
28
|
+
.saas-input-select {
|
|
29
|
+
.el-input__inner {
|
|
30
|
+
border-top: none;
|
|
31
|
+
border-bottom: none;
|
|
32
|
+
height: 30px;
|
|
33
|
+
line-height: 30px;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
.saas-input-select {
|
|
38
|
+
width: 100%;
|
|
39
|
+
|
|
40
|
+
.saas-input-select-dropdown {
|
|
41
|
+
display: block;
|
|
42
|
+
width: 100%;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.el-input__inner {
|
|
46
|
+
height: 32px;
|
|
47
|
+
line-height: 32px;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 下拉菜单挂载在 body 上,非 scoped
|
|
52
|
+
.saas-input-select-menu {
|
|
53
|
+
max-height: 274px;
|
|
54
|
+
overflow-y: auto;
|
|
55
|
+
|
|
56
|
+
.saas-input-select-empty {
|
|
57
|
+
padding: 10px 0;
|
|
58
|
+
margin: 0;
|
|
59
|
+
text-align: center;
|
|
60
|
+
color: #909399;
|
|
61
|
+
font-size: 14px;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
26
65
|
// 文本
|
|
27
66
|
.saas-text-mode {
|
|
28
67
|
display: inline;
|
|
@@ -149,10 +188,19 @@
|
|
|
149
188
|
}
|
|
150
189
|
}
|
|
151
190
|
|
|
152
|
-
.saas-radio
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
191
|
+
.saas-radio {
|
|
192
|
+
&.saas-radio-vertical {
|
|
193
|
+
.el-radio-group {
|
|
194
|
+
display: flex;
|
|
195
|
+
flex-direction: column;
|
|
196
|
+
gap: 8px;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
.saas-radio-group {
|
|
200
|
+
display: flex;
|
|
201
|
+
flex-wrap: wrap;
|
|
202
|
+
row-gap: 8px;
|
|
203
|
+
}
|
|
156
204
|
}
|
|
157
205
|
|
|
158
206
|
// SDatePicker 弹框(挂在 body,作用域 class 由组件 popperClass 注入)。
|
|
@@ -164,4 +212,12 @@
|
|
|
164
212
|
padding: 4px 4px;
|
|
165
213
|
padding-left: 12px;
|
|
166
214
|
}
|
|
215
|
+
// 佛历年份表:隐藏公历原文本(保留供 element 取值),伪元素显示佛历年
|
|
216
|
+
.el-year-table td .cell.be-cell {
|
|
217
|
+
font-size: 0;
|
|
218
|
+
&::after {
|
|
219
|
+
content: attr(data-be);
|
|
220
|
+
font-size: 14px;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
167
223
|
}
|
|
@@ -1,33 +1,22 @@
|
|
|
1
1
|
.saas-group {
|
|
2
2
|
display: flex;
|
|
3
|
+
align-items: stretch; /* 各组等高:把行高拉到最高一组 */
|
|
3
4
|
overflow-x: auto;
|
|
4
5
|
min-height: 50px;
|
|
5
6
|
padding-bottom: 4px;
|
|
6
7
|
div {
|
|
7
8
|
box-sizing: border-box;
|
|
8
9
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
background-color: #fff;
|
|
14
|
-
cursor: pointer;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
&::-webkit-scrollbar-thumb {
|
|
18
|
-
background: rgba(144, 147, 153, 0.2);
|
|
19
|
-
|
|
20
|
-
&:hover {
|
|
21
|
-
background: rgba(144, 147, 153, 0.5);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
/* 修改滚动条滑道的颜色 */
|
|
25
|
-
&::-webkit-scrollbar-track {
|
|
26
|
-
background-color: #fff; /* 设置滑道背景颜色 */
|
|
10
|
+
/* 每组外层 wrapper(v-for 的裸 div):改列布局,好让内部 sort-group 撑满被拉伸的高度 */
|
|
11
|
+
> div {
|
|
12
|
+
display: flex;
|
|
13
|
+
flex-direction: column;
|
|
27
14
|
}
|
|
15
|
+
/* 细滚动条外观由通用类 .saas-scroll 提供(配合 v-thin-scroll 现出),此处只管布局 */
|
|
28
16
|
}
|
|
29
17
|
.saas-sort-group {
|
|
30
18
|
display: flex;
|
|
19
|
+
flex: 1; /* 填满 wrapper(标题下方)剩余高度,其内卡片再随之 stretch 等高 */
|
|
31
20
|
border-radius: 6px 6px 6px 6px;
|
|
32
21
|
margin-right: 8px;
|
|
33
22
|
background: #f7f9fb;
|
|
@@ -25,12 +25,14 @@
|
|
|
25
25
|
margin-bottom: 4px;
|
|
26
26
|
cursor: pointer;
|
|
27
27
|
|
|
28
|
+
// 悬浮只变绿字;选中浅绿底 + 绿字
|
|
28
29
|
&:hover {
|
|
29
|
-
|
|
30
|
+
color: var(--saas-success);
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
&.active {
|
|
33
|
-
background-color: var(--saas-
|
|
34
|
+
background-color: var(--saas-success-50);
|
|
35
|
+
color: var(--saas-success);
|
|
34
36
|
}
|
|
35
37
|
}
|
|
36
38
|
|
|
@@ -42,6 +44,7 @@
|
|
|
42
44
|
|
|
43
45
|
&:hover {
|
|
44
46
|
background-color: transparent;
|
|
47
|
+
color: inherit;
|
|
45
48
|
}
|
|
46
49
|
}
|
|
47
50
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/* 通用细滚动条:横竖通用,平时隐藏,hover/滚动时现出(轨道恒占 6px,无布局位移)。
|
|
2
|
+
现出靠指令 v-thin-scroll 切 .is-scroll-active(类切换强制重绘,稳)——
|
|
3
|
+
不用容器 :hover 伪类:子内容铺满时鼠标压在子元素上、容器 :hover 虽真但滚动条不重绘会漏显。
|
|
4
|
+
⚠️ 要 hover 显隐必须同时:class 加 saas-scroll + 指令加 v-thin-scroll;只加 class 平时全隐。
|
|
5
|
+
只管滚动条外观;各处自行设 overflow-x/y 和 padding。 */
|
|
6
|
+
.saas-scroll {
|
|
7
|
+
&::-webkit-scrollbar {
|
|
8
|
+
width: 6px;
|
|
9
|
+
height: 6px;
|
|
10
|
+
}
|
|
11
|
+
/* 默认:thumb 有真颜色,但被 3px 透明边 + content-box 裁剪把可见部分收成 0 → 隐藏 */
|
|
12
|
+
&::-webkit-scrollbar-thumb {
|
|
13
|
+
background: var(--saas-gray-200);
|
|
14
|
+
background-clip: content-box;
|
|
15
|
+
border: 3px solid transparent;
|
|
16
|
+
border-radius: 6px;
|
|
17
|
+
}
|
|
18
|
+
/* v-thin-scroll 在 hover/滚动时加这个类 → 去掉透明边,thumb 现出 */
|
|
19
|
+
&.is-scroll-active::-webkit-scrollbar-thumb {
|
|
20
|
+
border-width: 0;
|
|
21
|
+
}
|
|
22
|
+
&.is-scroll-active::-webkit-scrollbar-thumb:hover {
|
|
23
|
+
background-color: var(--saas-gray-300);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -3,12 +3,15 @@
|
|
|
3
3
|
display: inline-flex;
|
|
4
4
|
align-items: center;
|
|
5
5
|
font-size: 14px;
|
|
6
|
+
// 不超过容器宽度:放不下时步骤项按标签收缩(标签省略 + tooltip),图标与连接线不缩
|
|
7
|
+
max-width: 100%;
|
|
6
8
|
|
|
7
9
|
.s-steps-new-item {
|
|
8
10
|
display: flex;
|
|
9
11
|
align-items: center;
|
|
10
12
|
gap: 8px;
|
|
11
|
-
flex-shrink:
|
|
13
|
+
flex-shrink: 1;
|
|
14
|
+
min-width: 0;
|
|
12
15
|
|
|
13
16
|
&__icon {
|
|
14
17
|
width: 24px;
|
|
@@ -27,6 +30,9 @@
|
|
|
27
30
|
&__label {
|
|
28
31
|
color: #7c808a;
|
|
29
32
|
white-space: nowrap;
|
|
33
|
+
// STooltipWrap 溢出省略需要可收缩的宿主
|
|
34
|
+
min-width: 0;
|
|
35
|
+
overflow: hidden;
|
|
30
36
|
}
|
|
31
37
|
|
|
32
38
|
&--active {
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
.saas-tooltip-wrap {
|
|
2
2
|
}
|
|
3
3
|
.saas-tooltip-wrap__content {
|
|
4
|
-
|
|
4
|
+
/* 必须块级:inline 下 overflow/text-overflow 不生效、clientWidth 为 0,会导致省略号不出/溢出检测失效 */
|
|
5
|
+
display: block;
|
|
5
6
|
overflow: hidden;
|
|
6
7
|
white-space: nowrap;
|
|
7
8
|
text-overflow: ellipsis;
|
|
8
|
-
word-break:
|
|
9
|
-
overflow-wrap: break-word;
|
|
9
|
+
word-break: normal;
|
|
10
10
|
}
|
|
11
11
|
.saas-tooltip-wrap__content-more {
|
|
12
|
-
word-break:
|
|
12
|
+
word-break: normal;
|
|
13
13
|
text-overflow: ellipsis;
|
|
14
14
|
display: -webkit-box;
|
|
15
15
|
-webkit-box-orient: vertical;
|
|
@@ -72,6 +72,11 @@ export default {
|
|
|
72
72
|
type: Object,
|
|
73
73
|
default: null,
|
|
74
74
|
},
|
|
75
|
+
isShortcuts: {
|
|
76
|
+
//是否需要快捷选项
|
|
77
|
+
type: Boolean,
|
|
78
|
+
default: true,
|
|
79
|
+
},
|
|
75
80
|
},
|
|
76
81
|
computed: {
|
|
77
82
|
// 是否显示佛历(泰语)
|
|
@@ -101,7 +106,7 @@ export default {
|
|
|
101
106
|
},
|
|
102
107
|
dateAttrs() {
|
|
103
108
|
const pickerOptions = this.attrs.pickerOptions || {};
|
|
104
|
-
if (!pickerOptions.disabledDate && this.type.indexOf('range') > 0 && !pickerOptions.shortcuts) {
|
|
109
|
+
if (!pickerOptions.disabledDate && this.type.indexOf('range') > 0 && !pickerOptions.shortcuts && this.isShortcuts) {
|
|
105
110
|
pickerOptions.shortcuts = this.buildShortcuts();
|
|
106
111
|
}
|
|
107
112
|
return {
|
|
@@ -149,17 +154,40 @@ export default {
|
|
|
149
154
|
patchPanel() {
|
|
150
155
|
const root = this.$refs.picker && this.$refs.picker.picker && this.$refs.picker.picker.$el;
|
|
151
156
|
if (!root) return;
|
|
152
|
-
const
|
|
157
|
+
const isRange = this.type.indexOf('range') > -1;
|
|
158
|
+
// 年份表:element 靠 cell 的 textContent 取值。直接改文本会让选中值也 +543,
|
|
159
|
+
// 所以保留公历文本供取值,用伪元素显示佛历(见 form.scss .be-cell)。
|
|
160
|
+
root.querySelectorAll('.el-year-table td .cell').forEach(cell => {
|
|
161
|
+
const raw = cell.textContent.trim();
|
|
162
|
+
if (/^\d{4}$/.test(raw)) {
|
|
163
|
+
cell.dataset.be = offsetYearStr(raw);
|
|
164
|
+
cell.classList.add('be-cell');
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
// 跳过年份表内的文本节点,避免污染其取值来源
|
|
168
|
+
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
|
|
169
|
+
acceptNode: n => (n.parentElement && n.parentElement.closest('.el-year-table') ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT),
|
|
170
|
+
});
|
|
153
171
|
let node;
|
|
154
172
|
while ((node = walker.nextNode())) {
|
|
155
173
|
let next = offsetYearStr(node.nodeValue);
|
|
156
|
-
//
|
|
174
|
+
// 区间面板表头是拼好的单节点 "2569 ปี กรกฎาคม"(年+"ปี"+月,写死一个字符串)。
|
|
157
175
|
// 泰语里 "2569 ปี" 读作"2569 年(数量)",且应月在前 —— 重排成 "กรกฎาคม 2569",并去掉误导的 "ปี"。
|
|
158
|
-
|
|
159
|
-
.replace(/^(\d{4})\s*ปี\s+([-][-.]*)\s*$/, '$2 $1') //
|
|
160
|
-
|
|
176
|
+
if (isRange) {
|
|
177
|
+
next = next.replace(/^(\d{4})\s*ปี\s+([-][-.]*)\s*$/, '$2 $1'); // 区间表头:月 年(月可含缩写点 ก.ค.)
|
|
178
|
+
}
|
|
179
|
+
next = next.replace(/\s*ปี/g, ''); // 去掉误导的 "ปี"(单选年份格、十年视图等)
|
|
161
180
|
if (next !== node.nodeValue) node.nodeValue = next;
|
|
162
181
|
}
|
|
182
|
+
// 单选面板表头是「年 span + 月 span」两个独立节点,文本改不了顺序,把「月」DOM 移到「年」前面。
|
|
183
|
+
// 幂等:仅当第 1 个 label 含 4 位年、第 2 个不含数字(月名)时交换;交换后条件不再成立。
|
|
184
|
+
if (!isRange) {
|
|
185
|
+
const header = root.querySelector('.el-date-picker__header');
|
|
186
|
+
const labels = header ? header.querySelectorAll('.el-date-picker__header-label') : [];
|
|
187
|
+
if (labels.length === 2 && /\d{4}/.test(labels[0].textContent) && !/\d/.test(labels[1].textContent)) {
|
|
188
|
+
header.insertBefore(labels[1], labels[0]);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
163
191
|
},
|
|
164
192
|
onPickerFocus() {
|
|
165
193
|
// 父组件绑定的 focus 由 v-on="onEvents" 自行触发;这里只给面板挂 observer(懒建一次)
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="saas-input-select" :class="{ 'saas-text-mode': from === 'text' }">
|
|
3
|
+
<!-- text 展示模式 -->
|
|
4
|
+
<span v-if="from === 'text'" class="saas-input-text">
|
|
5
|
+
<STooltipWrap :text="getTextValue" />
|
|
6
|
+
</span>
|
|
7
|
+
|
|
8
|
+
<!-- 可输入 + 可选择模式 -->
|
|
9
|
+
<el-dropdown
|
|
10
|
+
v-else
|
|
11
|
+
ref="dropdown"
|
|
12
|
+
class="saas-input-select-dropdown"
|
|
13
|
+
trigger="click"
|
|
14
|
+
placement="bottom-start"
|
|
15
|
+
:disabled="disabled"
|
|
16
|
+
@command="handleSelect"
|
|
17
|
+
@visible-change="handleVisibleChange">
|
|
18
|
+
<el-input v-model="newValue" v-bind="attrs" v-on="onEvents" autocomplete="new-password" @keyup.native="forwardKeyup">
|
|
19
|
+
<template v-if="$slots.prepend" slot="prepend">
|
|
20
|
+
<slot name="prepend"></slot>
|
|
21
|
+
</template>
|
|
22
|
+
</el-input>
|
|
23
|
+
<el-dropdown-menu slot="dropdown" class="saas-input-select-menu" :style="menuStyle">
|
|
24
|
+
<template v-if="optionsList.length">
|
|
25
|
+
<el-dropdown-item v-for="item in optionsList" :key="item.value" :command="item" :disabled="item.disabled">
|
|
26
|
+
{{ item.label }}
|
|
27
|
+
</el-dropdown-item>
|
|
28
|
+
</template>
|
|
29
|
+
<li v-else class="saas-input-select-empty">
|
|
30
|
+
<slot name="empty">{{ emptyText }}</slot>
|
|
31
|
+
</li>
|
|
32
|
+
</el-dropdown-menu>
|
|
33
|
+
</el-dropdown>
|
|
34
|
+
</div>
|
|
35
|
+
</template>
|
|
36
|
+
|
|
37
|
+
<script>
|
|
38
|
+
import { Input } from 'element-ui';
|
|
39
|
+
import { isEmpty, omit, formatIfJson } from 'chain-lodash';
|
|
40
|
+
import attrsMixin from '../mixins/attrsMixin';
|
|
41
|
+
export default {
|
|
42
|
+
name: 'SInputSelect',
|
|
43
|
+
mixins: [attrsMixin],
|
|
44
|
+
props: {
|
|
45
|
+
...omit(Input.props, ['value', 'clearable']),
|
|
46
|
+
value: {
|
|
47
|
+
type: [String, Number],
|
|
48
|
+
default: '',
|
|
49
|
+
},
|
|
50
|
+
mode: {
|
|
51
|
+
type: String, // FORM | SEARCH
|
|
52
|
+
default: 'FORM',
|
|
53
|
+
},
|
|
54
|
+
clearable: {
|
|
55
|
+
type: Boolean,
|
|
56
|
+
default: true,
|
|
57
|
+
},
|
|
58
|
+
from: {
|
|
59
|
+
type: String, // 'input' | 'text'
|
|
60
|
+
default: 'input',
|
|
61
|
+
},
|
|
62
|
+
placeholder: {
|
|
63
|
+
type: String,
|
|
64
|
+
default() {
|
|
65
|
+
return this.$t('InputPlaceholder.pleasemsg');
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
options: {
|
|
69
|
+
type: Array,
|
|
70
|
+
default: () => [],
|
|
71
|
+
},
|
|
72
|
+
props: {
|
|
73
|
+
type: Object,
|
|
74
|
+
default() {
|
|
75
|
+
return {
|
|
76
|
+
label: 'label',
|
|
77
|
+
value: 'value',
|
|
78
|
+
};
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
emptyText: {
|
|
82
|
+
type: String,
|
|
83
|
+
default() {
|
|
84
|
+
return this.$t('selectGroup.noData');
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
data() {
|
|
89
|
+
return {
|
|
90
|
+
menuWidth: 0,
|
|
91
|
+
};
|
|
92
|
+
},
|
|
93
|
+
computed: {
|
|
94
|
+
defaultAttrs() {
|
|
95
|
+
return {
|
|
96
|
+
maxlength: 120,
|
|
97
|
+
};
|
|
98
|
+
},
|
|
99
|
+
menuStyle() {
|
|
100
|
+
// 弹出框宽度与输入框保持一致
|
|
101
|
+
return this.menuWidth ? { width: `${this.menuWidth}px` } : {};
|
|
102
|
+
},
|
|
103
|
+
optionsList() {
|
|
104
|
+
const valueKey = (this.props && this.props.value) || 'value';
|
|
105
|
+
const labelKey = (this.props && this.props.label) || 'label';
|
|
106
|
+
return this.options
|
|
107
|
+
.filter(item => item && item.show !== false)
|
|
108
|
+
.map(item => {
|
|
109
|
+
const value = item[valueKey];
|
|
110
|
+
return {
|
|
111
|
+
...item,
|
|
112
|
+
value: !isEmpty(value) ? String(value) : '',
|
|
113
|
+
label: formatIfJson(item[labelKey]),
|
|
114
|
+
};
|
|
115
|
+
});
|
|
116
|
+
},
|
|
117
|
+
getTextValue() {
|
|
118
|
+
const matched = this.optionsList.find(f => f.value === this.newValue);
|
|
119
|
+
return (matched && matched.label) || this.newValue || '-';
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
methods: {
|
|
123
|
+
handleSelect(item) {
|
|
124
|
+
this.newValue = item.value;
|
|
125
|
+
this.$emit('select', item);
|
|
126
|
+
this.$emit('change', item.value, { options: this.optionsList });
|
|
127
|
+
},
|
|
128
|
+
handleVisibleChange(visible) {
|
|
129
|
+
// 打开时同步触发器(输入框)宽度到弹出框
|
|
130
|
+
if (visible && this.$refs.dropdown) {
|
|
131
|
+
this.menuWidth = this.$refs.dropdown.$el.getBoundingClientRect().width;
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
forwardKeyup(e) {
|
|
135
|
+
this.$emit('keyup', e);
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
</script>
|
|
140
|
+
|
|
141
|
+
<style lang="scss" scoped></style>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="saas-
|
|
2
|
+
<div class="saas-radio" :class="[{ 'saas-text-mode': from === 'text' }, `saas-radio-${direction}`]">
|
|
3
3
|
<span v-if="from === 'text'" class="saas-input-text">
|
|
4
4
|
<STooltipWrap :text="textValue" />
|
|
5
5
|
</span>
|
|
@@ -9,3 +9,4 @@ export { default as SRadioGroup } from './SRadio/index';
|
|
|
9
9
|
export { default as SCheckboxGroup } from './SCheckbox/index';
|
|
10
10
|
export { default as FieldGroup } from './FieldGroup/index';
|
|
11
11
|
export { default as SMaskInput } from './SMaskInput/index';
|
|
12
|
+
export { default as SInputSelect } from './SInputSelect/index';
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
:rows="rows"
|
|
12
12
|
:placeholder="placeholder"
|
|
13
13
|
:maxlength="maxlength"
|
|
14
|
-
:autosize="autosize"
|
|
14
|
+
:autosize="autosize"
|
|
15
|
+
:resize="resize" />
|
|
15
16
|
</el-form-item>
|
|
16
17
|
</el-form>
|
|
17
18
|
</SDialog>
|
|
@@ -36,6 +37,8 @@ export default {
|
|
|
36
37
|
rows: 5,
|
|
37
38
|
maxlength: 500,
|
|
38
39
|
autosize: false,
|
|
40
|
+
// textarea 缩放手柄(el-input resize:none/both/horizontal/vertical),缺省浏览器默认
|
|
41
|
+
resize: undefined,
|
|
39
42
|
formData: {
|
|
40
43
|
value: '',
|
|
41
44
|
},
|
|
@@ -53,7 +56,9 @@ export default {
|
|
|
53
56
|
this.width = options.width || '500px';
|
|
54
57
|
this.rows = options.rows || 5;
|
|
55
58
|
this.maxlength = options.maxlength || 500;
|
|
56
|
-
|
|
59
|
+
// ?? 保留显式传入的 false(固定 rows 高度)
|
|
60
|
+
this.autosize = options.autosize ?? { minRows: 5, maxRows: 10 };
|
|
61
|
+
this.resize = options.resize;
|
|
57
62
|
this.formData.value = options.defaultValue || '';
|
|
58
63
|
|
|
59
64
|
// 设置校验规则
|