jobdone-shared-files 1.0.44 → 1.0.46
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/ModuleInfo/LayoutNav.vue +1 -1
- package/README.md +2 -0
- package/autocompleteSelect.vue +1 -1
- package/package.json +1 -1
- package/style/scss/Common/Tree.scss +282 -0
- package/treeItemV2.vue +79 -0
- package/treeV2.vue +71 -0
package/ModuleInfo/LayoutNav.vue
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
</a>
|
|
17
17
|
</div>
|
|
18
18
|
</div>
|
|
19
|
-
<a :href="finalRootDomain + moduleInfoData.isPersonal ? '/
|
|
19
|
+
<a :href="finalRootDomain + (moduleInfoData.isPersonal ? '/PersonalPlan' : '/CompanyOrderDetail')" class="d-block a-reset-color a-hover-gradient border-bottom px-4 py-3 lh-1">
|
|
20
20
|
<small>
|
|
21
21
|
<div class="mb-2">
|
|
22
22
|
<b class="text-line-clamp-1">{{ moduleInfoData.isPersonal ? userDisplayName : orgName }}</b>
|
package/README.md
CHANGED
|
@@ -139,6 +139,7 @@ import OOXX from '../../node_modules/jobdone-shared-files/OOXX.vue';
|
|
|
139
139
|
| 1 | `update-auto-complete-option` | 文字輸入時呼叫,value為當前輸入的值,可用於刷新autoCompleteOption。 |
|
|
140
140
|
### .
|
|
141
141
|
## 05.Tree - 樹狀結構
|
|
142
|
+
需另外引入 `../../node_modules/jobdone-shared-files/style/scss/Tree.scss` 檔案
|
|
142
143
|
### 範例
|
|
143
144
|
```
|
|
144
145
|
<template>
|
|
@@ -463,6 +464,7 @@ import OOXX from '../../node_modules/jobdone-shared-files/OOXX.vue';
|
|
|
463
464
|
- SelectableTable:勾選 tr focus style
|
|
464
465
|
- thumbnail-group:方形大頭貼與小大頭貼相疊 style
|
|
465
466
|
- filepond:客製化 filepond 樣式
|
|
467
|
+
- Tree:Tree Component 樣式
|
|
466
468
|
|
|
467
469
|
|
|
468
470
|
|
package/autocompleteSelect.vue
CHANGED
|
@@ -264,7 +264,7 @@ function previewAdjust(itemObj) {
|
|
|
264
264
|
const selectedPreviewText = computed(() => {
|
|
265
265
|
|
|
266
266
|
|
|
267
|
-
if (!selectedItem.value || Object.keys(selectedItem.value).length === 0) {
|
|
267
|
+
if (!selectedItem.value || (typeof selectedItem.value === 'object' && Object.keys(selectedItem.value).length === 0)) {
|
|
268
268
|
return props.placeholder
|
|
269
269
|
}
|
|
270
270
|
return previewAdjust(selectedItem.value)
|
package/package.json
CHANGED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
@import "../../../../bootstrap/scss/functions";
|
|
2
|
+
@import "../Settings/bs-variables";
|
|
3
|
+
@import "../../../../bootstrap/scss/mixins";
|
|
4
|
+
@import "../Settings/custom-variables";
|
|
5
|
+
@import "../Settings/Mixins";
|
|
6
|
+
|
|
7
|
+
li {
|
|
8
|
+
list-style-type: none;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// 基本 sizes
|
|
12
|
+
.tree-item {
|
|
13
|
+
.btn {
|
|
14
|
+
--bs-btn-padding-x: 0.75em;
|
|
15
|
+
--bs-btn-padding-y: 0.375em;
|
|
16
|
+
--bs-btn-font-size: 1em;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.card {
|
|
20
|
+
--bs-card-spacer-y: 1em;
|
|
21
|
+
--bs-card-spacer-x: 1em;
|
|
22
|
+
--bs-card-title-spacer-y: 0.5em;
|
|
23
|
+
--bs-card-cap-padding-y: 0.5em;
|
|
24
|
+
--bs-card-cap-padding-x: 1em;
|
|
25
|
+
--bs-card-img-overlay-padding: 1em;
|
|
26
|
+
--bs-card-group-margin: 0.75em;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.material-icons {
|
|
30
|
+
font-size: 1.5em;
|
|
31
|
+
|
|
32
|
+
&.icon-14 {
|
|
33
|
+
font-size: 0.875em;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
&.icon-18 {
|
|
37
|
+
font-size: 1.125em;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
&.icon-28 {
|
|
41
|
+
font-size: 1.75em;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
&.icon-32 {
|
|
45
|
+
font-size: 2em;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// hover效果與優化
|
|
51
|
+
// firefox 暫不支援 has
|
|
52
|
+
.tree-item:has([data-bs-toggle="collapse"]:hover)+.collapse {
|
|
53
|
+
will-change: height;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.tree-item:hover>.card,
|
|
57
|
+
.tree-item .card:focus-within {
|
|
58
|
+
background-color: lighten($primary, 32%);
|
|
59
|
+
border-color: rgba($primary, .4);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.tree-item {
|
|
63
|
+
.btn-title .material-icons:is(:empty):before {
|
|
64
|
+
content: "\e836";
|
|
65
|
+
display: inline-block;
|
|
66
|
+
font-family: inherit;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// active效果
|
|
70
|
+
&.active {
|
|
71
|
+
>.card {
|
|
72
|
+
background-color: lighten($primary, 30%);
|
|
73
|
+
border-color: rgba($primary, .5);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
>.card .btn-title .material-icons:is(:empty):before {
|
|
77
|
+
content: "\e837";
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.btn-title {
|
|
81
|
+
color: $primary;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.btn-title {
|
|
87
|
+
cursor: pointer;
|
|
88
|
+
|
|
89
|
+
.btn {
|
|
90
|
+
border-radius: 0;
|
|
91
|
+
|
|
92
|
+
&:focus,
|
|
93
|
+
&:active {
|
|
94
|
+
border-color: transparent;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.btn-text {
|
|
99
|
+
width: 100%;
|
|
100
|
+
text-align: left;
|
|
101
|
+
overflow-wrap: anywhere;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
// 刪除子層標示 UI
|
|
107
|
+
.tree-item:has(.btn.text-danger:hover) {
|
|
108
|
+
.card {
|
|
109
|
+
background-color: lighten($danger, 43%);
|
|
110
|
+
border-color: rgba($danger, .5);
|
|
111
|
+
|
|
112
|
+
.btn {
|
|
113
|
+
color: $danger;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// 刪除子層標示 UI (含子層)
|
|
119
|
+
// .tree-child:has(.btn.text-danger:hover){
|
|
120
|
+
// .card, + .content-children .card{
|
|
121
|
+
// background-color: lighten( $danger, 43% );
|
|
122
|
+
// border-color: rgba( $danger, .5 );
|
|
123
|
+
// .btn{
|
|
124
|
+
// color: $danger;
|
|
125
|
+
// }
|
|
126
|
+
// }
|
|
127
|
+
// }
|
|
128
|
+
|
|
129
|
+
.btn-no-children {
|
|
130
|
+
cursor: auto;
|
|
131
|
+
|
|
132
|
+
&:focus {
|
|
133
|
+
border-color: transparent;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// 基本 style
|
|
138
|
+
$card-margin: .2em;
|
|
139
|
+
$line-padding: .7em;
|
|
140
|
+
|
|
141
|
+
.tree-item {
|
|
142
|
+
display: flex;
|
|
143
|
+
flex-direction: column;
|
|
144
|
+
width: 100%;
|
|
145
|
+
margin-top: $card-margin;
|
|
146
|
+
|
|
147
|
+
.card {
|
|
148
|
+
position: relative;
|
|
149
|
+
flex-grow: 1;
|
|
150
|
+
transition: $transition-base;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.col-action {
|
|
155
|
+
@include flex-center;
|
|
156
|
+
width: 2.8rem;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
// 開合 style
|
|
161
|
+
.btn[data-bs-toggle="collapse"] {
|
|
162
|
+
.material-icons {
|
|
163
|
+
transition: $transition-base;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
&[aria-expanded="false"] .material-icons {
|
|
167
|
+
transform: rotate(-90deg);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
&:disabled,
|
|
171
|
+
&.disabled {
|
|
172
|
+
border-color: transparent;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// 畫線 style
|
|
177
|
+
.content-children {
|
|
178
|
+
padding-left: 1.5rem;
|
|
179
|
+
--tree-border-color: #fff;
|
|
180
|
+
position: relative;
|
|
181
|
+
|
|
182
|
+
&:before {
|
|
183
|
+
content: "";
|
|
184
|
+
position: absolute;
|
|
185
|
+
display: block;
|
|
186
|
+
left: -$line-padding;
|
|
187
|
+
bottom: 24px;
|
|
188
|
+
width: 1px;
|
|
189
|
+
height: 100%;
|
|
190
|
+
z-index: 1;
|
|
191
|
+
background-color: var(--tree-border-color);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// // line color
|
|
195
|
+
&:before,
|
|
196
|
+
.tree-item .card:before,
|
|
197
|
+
.tree-item .card:after {
|
|
198
|
+
background-color: var(--tree-border-color);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.tree-item {
|
|
203
|
+
&:last-child>.content-children:before {
|
|
204
|
+
display: none;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.card {
|
|
208
|
+
position: relative;
|
|
209
|
+
|
|
210
|
+
&:before,
|
|
211
|
+
&:after {
|
|
212
|
+
content: "";
|
|
213
|
+
position: absolute;
|
|
214
|
+
left: calc(-#{$line-padding} - #{$border-width});
|
|
215
|
+
z-index: 1;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
&:before {
|
|
219
|
+
bottom: 50%;
|
|
220
|
+
width: 1px;
|
|
221
|
+
height: calc(100% + #{$card-margin}*2 + #{$border-width}*2);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
&:after {
|
|
225
|
+
top: 0;
|
|
226
|
+
bottom: 0;
|
|
227
|
+
width: $line-padding;
|
|
228
|
+
height: 1px;
|
|
229
|
+
margin: auto;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
&:nth-child(1)>.card:before {
|
|
234
|
+
height: calc(50% + #{$card-margin} + #{$border-width});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
// 小版本
|
|
240
|
+
.tree-item-sm {
|
|
241
|
+
>.card {
|
|
242
|
+
font-size: 86%;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.content-children {
|
|
246
|
+
padding-left: 1rem;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.content-children:before {
|
|
250
|
+
left: -10px;
|
|
251
|
+
bottom: 19px;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// .tree-item-sm + .content-children{
|
|
256
|
+
// > .children-box{
|
|
257
|
+
// padding-left: 1rem;
|
|
258
|
+
// }
|
|
259
|
+
// }
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
// 白背景版本
|
|
263
|
+
.tree-item-in-white {
|
|
264
|
+
.content-children {
|
|
265
|
+
--tree-border-color: var(--bs-border-color);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.card {
|
|
269
|
+
--bs-card-bg: var(--gray-100);
|
|
270
|
+
--bs-card-border-color: var(--bs-border-color);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
&:hover>.card,
|
|
274
|
+
.card:focus-within {
|
|
275
|
+
background-color: $white;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// active效果
|
|
279
|
+
&.active .card {
|
|
280
|
+
background-color: $white;
|
|
281
|
+
}
|
|
282
|
+
}
|
package/treeItemV2.vue
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<li class="tree-item" :class="[itemClass]">
|
|
3
|
+
<div class="card flex-row d-flex input-group flex-nowrap">
|
|
4
|
+
<button type="button" class="btn text-primary border-end px-1"
|
|
5
|
+
:disabled="!item.children || item.children.length == 0" data-bs-toggle="collapse"
|
|
6
|
+
:data-bs-target="'#collapse-' + item.id">
|
|
7
|
+
<span class="material-icons">arrow_drop_down</span>
|
|
8
|
+
<slot name="icon-start"></slot>
|
|
9
|
+
</button>
|
|
10
|
+
<div class="btn-title d-flex text-start rounded-0 flex-grow-1" :for="item.id" @click="clickItem(item)">
|
|
11
|
+
<div class="btn btn-text border-start">{{ item.title }}</div>
|
|
12
|
+
<slot name="icon" :item="item">
|
|
13
|
+
<div class="btn d-flex align-items-center border-start rounded-0 text-primary h-100 ms-auto">
|
|
14
|
+
<span class="material-icons icon-18"></span>
|
|
15
|
+
</div>
|
|
16
|
+
</slot>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
<template v-if="item.children">
|
|
20
|
+
<ul :id="'collapse-' + item.id" class="content-children show">
|
|
21
|
+
<TreeItem class="children-box" v-for="(subItem, subIndex) in item.children" :key="subItem.id" :item="subItem"
|
|
22
|
+
:index="subIndex" :click-item="clickItem" :active-id="activeId" :tree-item-class="treeItemClass">
|
|
23
|
+
<template v-slot:icon-start>
|
|
24
|
+
<slot name="icon-start"></slot>
|
|
25
|
+
</template>
|
|
26
|
+
<template v-slot:icon="slotProps">
|
|
27
|
+
<slot name="icon" :item="slotProps.item">
|
|
28
|
+
<div class="btn d-flex align-items-center border-start rounded-0 text-primary h-100 ms-auto">
|
|
29
|
+
<span class="material-icons icon-18"></span>
|
|
30
|
+
</div>
|
|
31
|
+
</slot>
|
|
32
|
+
</template>
|
|
33
|
+
</TreeItem>
|
|
34
|
+
</ul>
|
|
35
|
+
</template>
|
|
36
|
+
</li>
|
|
37
|
+
</template>
|
|
38
|
+
|
|
39
|
+
<script>
|
|
40
|
+
import { ref, computed } from 'vue';
|
|
41
|
+
export default {
|
|
42
|
+
name: 'TreeItem',
|
|
43
|
+
props: {
|
|
44
|
+
item: {
|
|
45
|
+
type: Object,
|
|
46
|
+
required: true
|
|
47
|
+
},
|
|
48
|
+
index: {
|
|
49
|
+
type: Number,
|
|
50
|
+
required: true
|
|
51
|
+
},
|
|
52
|
+
clickItem: {
|
|
53
|
+
type: Function
|
|
54
|
+
},
|
|
55
|
+
activeId: {
|
|
56
|
+
type: String,
|
|
57
|
+
required: true
|
|
58
|
+
},
|
|
59
|
+
treeItemClass: {
|
|
60
|
+
type: Array,
|
|
61
|
+
default: function () {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
setup(props, { emit }) {
|
|
67
|
+
const itemClass = computed(() => {
|
|
68
|
+
var classList = [...props.treeItemClass];
|
|
69
|
+
if (props.activeId === props.item.id) {
|
|
70
|
+
classList.push('active');
|
|
71
|
+
}
|
|
72
|
+
return classList;
|
|
73
|
+
});
|
|
74
|
+
return {
|
|
75
|
+
itemClass: itemClass
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
</script>
|
package/treeV2.vue
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<form ref="form">
|
|
3
|
+
<tree-item v-for="(item, index) in items" :key="item.id" :item="item" :index="index" :click-item="clickItem"
|
|
4
|
+
:active-id="activeId" :tree-item-class="treeItemClass">
|
|
5
|
+
<template v-slot:icon-start>
|
|
6
|
+
<slot name="icon-start"></slot>
|
|
7
|
+
</template>
|
|
8
|
+
<template v-slot:icon="slotProps">
|
|
9
|
+
<slot name="icon" :item="slotProps.item"></slot>
|
|
10
|
+
</template>
|
|
11
|
+
</tree-item>
|
|
12
|
+
</form>
|
|
13
|
+
</template>
|
|
14
|
+
|
|
15
|
+
<script>
|
|
16
|
+
import { ref, computed } from 'vue';
|
|
17
|
+
import TreeItem from './treeItemV2.vue';
|
|
18
|
+
export default {
|
|
19
|
+
props: {
|
|
20
|
+
items: {
|
|
21
|
+
type: Array,
|
|
22
|
+
default: function () {
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
clickItem: {
|
|
27
|
+
type: Function
|
|
28
|
+
},
|
|
29
|
+
size: {
|
|
30
|
+
type: String,
|
|
31
|
+
default: ""
|
|
32
|
+
},
|
|
33
|
+
bgColor: {
|
|
34
|
+
type: String,
|
|
35
|
+
default: ""
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
components: {
|
|
39
|
+
TreeItem
|
|
40
|
+
},
|
|
41
|
+
setup(props, { emit }) {
|
|
42
|
+
const form = ref(null);
|
|
43
|
+
const activeId = ref("");
|
|
44
|
+
const clickItem = (item) => {
|
|
45
|
+
activeId.value = item.id;
|
|
46
|
+
props.clickItem(item);
|
|
47
|
+
};
|
|
48
|
+
const treeItemClass = computed(() => {
|
|
49
|
+
var classList = [];
|
|
50
|
+
if (props.size == 'sm') {
|
|
51
|
+
classList.push('tree-item-sm');
|
|
52
|
+
}
|
|
53
|
+
if (props.bgColor == 'white') {
|
|
54
|
+
classList.push('tree-item-in-white');
|
|
55
|
+
}
|
|
56
|
+
return classList;
|
|
57
|
+
});
|
|
58
|
+
const reset = () => {
|
|
59
|
+
activeId.value = "";
|
|
60
|
+
};
|
|
61
|
+
return {
|
|
62
|
+
form: form,
|
|
63
|
+
treeItemClass: treeItemClass,
|
|
64
|
+
activeId: activeId,
|
|
65
|
+
clickItem: clickItem,
|
|
66
|
+
reset: reset
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
</script>
|
|
71
|
+
<style></style>
|