@mptw/skylens-ui 1.4.109 → 1.5.1
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/AGENTS.md +59 -0
- package/CLAUDE.md +36 -0
- package/README.md +7 -7
- package/app/app.config.ts +14 -0
- package/app/app.vue +5 -0
- package/app/assets/css/layout.css +134 -0
- package/app/assets/css/main.css +189 -0
- package/{components → app/components}/SLAlertModal.vue +24 -16
- package/{components → app/components}/SLBreadcrumbs.vue +12 -8
- package/app/components/SLButton.vue +370 -0
- package/{components → app/components}/SLCalendarButton.vue +40 -34
- package/{components → app/components}/SLCalendarPopup.vue +79 -53
- package/{components → app/components}/SLCard.vue +57 -41
- package/{components → app/components}/SLChart.vue +6 -3
- package/{components → app/components}/SLCheckbox.vue +92 -49
- package/{components → app/components}/SLCircleButton.vue +25 -16
- package/{components → app/components}/SLCollapsableBlock.vue +44 -33
- package/{components → app/components}/SLCollapsableMulitPillSelect.vue +20 -15
- package/{components → app/components}/SLConfirmModal.vue +9 -6
- package/{components → app/components}/SLContextMenu.vue +88 -48
- package/{components → app/components}/SLDateInput.vue +109 -92
- package/{components → app/components}/SLDatePicker.vue +9 -7
- package/{components → app/components}/SLDistributor.vue +1 -1
- package/{components → app/components}/SLDownloadButton.vue +39 -29
- package/{components → app/components}/SLDraggable.vue +2 -2
- package/{components → app/components}/SLDropdown.vue +33 -25
- package/{components → app/components}/SLDropdownItem.vue +9 -5
- package/{components → app/components}/SLElementWithTitle.vue +12 -7
- package/{components → app/components}/SLEyeCheckbox.vue +44 -31
- package/{components → app/components}/SLFileInput.vue +23 -16
- package/{components → app/components}/SLGenderAgeSelect.vue +52 -36
- package/{components → app/components}/SLHourRangeInput.vue +45 -32
- package/{components → app/components}/SLIOSSwitch.vue +81 -60
- package/{components → app/components}/SLIcon.vue +4 -3
- package/{components → app/components}/SLIconButton.vue +31 -29
- package/{components → app/components}/SLInfoTip.vue +51 -40
- package/{components → app/components}/SLInsightSitePage.vue +12 -7
- package/{components → app/components}/SLLegend.vue +19 -12
- package/app/components/SLLinearProgressBar.vue +22 -0
- package/{components → app/components}/SLLink.vue +12 -8
- package/{components → app/components}/SLLoading.vue +34 -31
- package/{components → app/components}/SLMapChart.vue +5 -4
- package/{components → app/components}/SLModal.vue +90 -66
- package/{components → app/components}/SLMonthCalendarButton.vue +91 -45
- package/{components → app/components}/SLMonthPicker.vue +42 -37
- package/{components → app/components}/SLMultiEmailInput.vue +163 -113
- package/{components → app/components}/SLMultiSelect.vue +37 -26
- package/{components → app/components}/SLNoData.vue +16 -11
- package/app/components/SLNotification.vue +155 -0
- package/{components → app/components}/SLPageModal.vue +14 -9
- package/{components → app/components}/SLPagination.vue +45 -33
- package/{components → app/components}/SLPillCheckbox.vue +50 -42
- package/{components → app/components}/SLPillLabel.vue +43 -28
- package/{components → app/components}/SLPopupMenuButton.vue +26 -17
- package/{components → app/components}/SLProfileButton.vue +28 -20
- package/{components → app/components}/SLProjectShareItem.vue +30 -17
- package/{components → app/components}/SLRadioButton.vue +41 -33
- package/{components → app/components}/SLRadioButtonGroup.vue +28 -23
- package/app/components/SLRadioGroup.vue +221 -0
- package/{components → app/components}/SLRangeInput.vue +53 -38
- package/{components → app/components}/SLRegionsMapChart.vue +5 -4
- package/{components → app/components}/SLRightSider.vue +50 -40
- package/{components → app/components}/SLSearchInput.vue +24 -19
- package/{components → app/components}/SLSelect.vue +114 -87
- package/{components → app/components}/SLSelectAllToggle.vue +52 -37
- package/app/components/SLSidebarNav.vue +487 -0
- package/{components → app/components}/SLSidebarNavGroupItem.vue +13 -10
- package/{components → app/components}/SLSidebarNavGroupItemSection.vue +240 -179
- package/{components → app/components}/SLSidebarNavLinkItem.vue +131 -109
- package/{components → app/components}/SLSidebarNavSectionItem.vue +21 -18
- package/{components → app/components}/SLSitePage.vue +35 -24
- package/{components → app/components}/SLSkyInsightSitePage.vue +13 -8
- package/{components → app/components}/SLSortByDropdown.vue +35 -22
- package/{components → app/components}/SLSpinIcon.vue +6 -3
- package/{components → app/components}/SLStayRangeInput.vue +47 -36
- package/{components → app/components}/SLTab.vue +7 -2
- package/app/components/SLTable.vue +472 -0
- package/{components → app/components}/SLTableTooltip.vue +44 -30
- package/app/components/SLTabs.vue +528 -0
- package/{components → app/components}/SLTextInput.vue +162 -134
- package/{components → app/components}/SLTextarea.vue +40 -29
- package/{components → app/components}/SLToast.vue +19 -11
- package/{components → app/components}/SLToggleButton.vue +18 -11
- package/{components → app/components}/SLTwoLayerMultiSelect.vue +180 -85
- package/{components → app/components}/SLTwoLayerSelect.vue +47 -37
- package/{components → app/components}/SLTwoLayerSingleSelect.vue +52 -33
- package/{components → app/components}/SLWarnModal.vue +9 -7
- package/app/interface/commons.ts +7 -0
- package/{utils → app/utils}/index.ts +213 -146
- package/eslint.config.js +3 -0
- package/nuxt.config.ts +17 -14
- package/package.json +10 -9
- package/skills-lock.json +59 -0
- package/tsconfig.json +1 -6
- package/.eslintrc.cjs +0 -4
- package/app.config.ts +0 -5
- package/assets/css/layout.styl +0 -98
- package/assets/css/tailwind.css +0 -3
- package/components/SLButton.vue +0 -337
- package/components/SLLinearProgressBar.vue +0 -35
- package/components/SLNotification.vue +0 -151
- package/components/SLRadioGroup.vue +0 -209
- package/components/SLSidebarNav.vue +0 -427
- package/components/SLTable.vue +0 -455
- package/components/SLTabs.vue +0 -475
- package/interface/commons.ts +0 -7
- package/pages/index.vue +0 -15
- package/tailwind.config.js +0 -271
- /package/{assets → app/assets}/css/fonts/MEShPlus-font-icon.eot +0 -0
- /package/{assets → app/assets}/css/fonts/MEShPlus-font-icon.svg +0 -0
- /package/{assets → app/assets}/css/fonts/MEShPlus-font-icon.ttf +0 -0
- /package/{assets → app/assets}/css/fonts/MEShPlus-font-icon.woff +0 -0
- /package/{assets → app/assets}/css/icons.css +0 -0
- /package/{assets → app/assets}/images/commons/app-logo-white.png +0 -0
- /package/{assets → app/assets}/images/commons/app-logo.png +0 -0
- /package/{assets → app/assets}/images/commons/empty-box.png +0 -0
- /package/{interface → app/interface}/IDateRange.ts +0 -0
- /package/{interface → app/interface}/IHourRange.ts +0 -0
- /package/{interface → app/interface}/IInputOption.ts +0 -0
- /package/{interface → app/interface}/ILegendItem.ts +0 -0
- /package/{interface → app/interface}/IOrganization.ts +0 -0
- /package/{interface → app/interface}/IPopupMenuButton.ts +0 -0
- /package/{interface → app/interface}/IStayRange.ts +0 -0
- /package/{interface → app/interface}/ITableField.ts +0 -0
- /package/{interface → app/interface}/IWeb.ts +0 -0
- /package/{interface → app/interface}/NavConfigType.ts +0 -0
- /package/{models → app/models}/DateRange.ts +0 -0
- /package/{plugins → app/plugins}/v-calendar.ts +0 -0
- /package/{utils → app/utils}/constants.ts +0 -0
- /package/{utils → app/utils}/generateSheet.ts +0 -0
|
@@ -18,10 +18,10 @@
|
|
|
18
18
|
</template>
|
|
19
19
|
|
|
20
20
|
<script lang="ts">
|
|
21
|
-
import { fromEvent, Subscription } from
|
|
22
|
-
import type IDateRange from
|
|
21
|
+
import { fromEvent, Subscription } from "rxjs";
|
|
22
|
+
import type IDateRange from "~ui/app/interface/IDateRange";
|
|
23
23
|
|
|
24
|
-
const WatermarkImage =
|
|
24
|
+
const WatermarkImage = "/assets/images/commons/watermark-2.svg";
|
|
25
25
|
const keys = { 37: 1, 38: 1, 30: 1, 40: 1 };
|
|
26
26
|
|
|
27
27
|
function preventDefault(e: Event) {
|
|
@@ -36,7 +36,7 @@ function preventDefaultForScrollKeys(e: Event) {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
export default defineComponent({
|
|
39
|
-
name:
|
|
39
|
+
name: "SLContextMenu",
|
|
40
40
|
props: {
|
|
41
41
|
target: {
|
|
42
42
|
type: HTMLElement,
|
|
@@ -44,7 +44,7 @@ export default defineComponent({
|
|
|
44
44
|
},
|
|
45
45
|
filename: {
|
|
46
46
|
type: String,
|
|
47
|
-
default:
|
|
47
|
+
default: "",
|
|
48
48
|
},
|
|
49
49
|
dateRanges: {
|
|
50
50
|
type: Array as PropType<(IDateRange | null)[]>,
|
|
@@ -64,30 +64,45 @@ export default defineComponent({
|
|
|
64
64
|
},
|
|
65
65
|
customStyle: {
|
|
66
66
|
type: Object as PropType<Partial<CSSStyleDeclaration>>,
|
|
67
|
-
default: () => {
|
|
67
|
+
default: () => {},
|
|
68
68
|
},
|
|
69
69
|
},
|
|
70
|
-
emits: [
|
|
70
|
+
emits: ["action"],
|
|
71
71
|
setup(props, { emit }) {
|
|
72
72
|
let supportsPassive = false;
|
|
73
73
|
|
|
74
74
|
try {
|
|
75
|
-
window.addEventListener(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
window.addEventListener(
|
|
76
|
+
"test",
|
|
77
|
+
null,
|
|
78
|
+
Object.defineProperty({}, "passive", {
|
|
79
|
+
get: function () {
|
|
80
|
+
supportsPassive = true;
|
|
81
|
+
},
|
|
82
|
+
}),
|
|
83
|
+
);
|
|
84
|
+
} catch (e) {}
|
|
79
85
|
|
|
80
86
|
const wheelOpt = supportsPassive ? { passive: false } : false;
|
|
81
|
-
const wheelEvent =
|
|
82
|
-
|
|
83
|
-
|
|
87
|
+
const wheelEvent =
|
|
88
|
+
"onwheel" in document.createElement("div") ? "wheel" : "mousewheel";
|
|
89
|
+
|
|
90
|
+
const {
|
|
91
|
+
target,
|
|
92
|
+
filename,
|
|
93
|
+
dateRanges,
|
|
94
|
+
padding,
|
|
95
|
+
watermark,
|
|
96
|
+
customFilter,
|
|
97
|
+
customStyle,
|
|
98
|
+
} = toRefs(props);
|
|
84
99
|
|
|
85
100
|
const el = shallowRef<HTMLDivElement | null>(null);
|
|
86
101
|
const isShow = ref(false);
|
|
87
102
|
const contextMenuX = ref(0);
|
|
88
103
|
const contextMenuY = ref(0);
|
|
89
104
|
const isShowCopyMsg = ref(false);
|
|
90
|
-
const copyMsg = ref(
|
|
105
|
+
const copyMsg = ref("");
|
|
91
106
|
const isCopySuccess = ref(false);
|
|
92
107
|
|
|
93
108
|
let contextMenuSubscriber: Subscription | null = null;
|
|
@@ -95,8 +110,8 @@ export default defineComponent({
|
|
|
95
110
|
let clearMsgTimeoutId: any = null;
|
|
96
111
|
|
|
97
112
|
const contextMenuActions = computed(() => [
|
|
98
|
-
{ key:
|
|
99
|
-
{ key:
|
|
113
|
+
{ key: "saveAs", label: "另存圖檔(.png)" },
|
|
114
|
+
{ key: "copy", label: "複製圖檔" },
|
|
100
115
|
]);
|
|
101
116
|
const contextMenuStyle = computed(() => ({
|
|
102
117
|
top: `${contextMenuY.value}px`,
|
|
@@ -105,35 +120,51 @@ export default defineComponent({
|
|
|
105
120
|
|
|
106
121
|
async function onClickAction(key: string) {
|
|
107
122
|
hide();
|
|
108
|
-
if (key ===
|
|
109
|
-
const dataURL = await domToPngDataUrl(
|
|
123
|
+
if (key === "saveAs") {
|
|
124
|
+
const dataURL = await domToPngDataUrl(
|
|
125
|
+
target.value,
|
|
126
|
+
customFilter.value,
|
|
127
|
+
customStyle.value,
|
|
128
|
+
padding.value,
|
|
129
|
+
dateRanges.value,
|
|
130
|
+
watermark.value,
|
|
131
|
+
WatermarkImage,
|
|
132
|
+
);
|
|
110
133
|
if (!dataURL) {
|
|
111
134
|
console.log("Can not generate data URL!");
|
|
112
135
|
return;
|
|
113
136
|
}
|
|
114
137
|
downloadURL(dataURL, `${filename.value}.png`);
|
|
115
|
-
} else if (key ===
|
|
138
|
+
} else if (key === "copy") {
|
|
116
139
|
if (!navigator.clipboard?.write || !window.ClipboardItem) {
|
|
117
140
|
console.log("Can not copy image to clipboard!");
|
|
118
141
|
return;
|
|
119
142
|
}
|
|
120
143
|
|
|
121
|
-
const dataURL = await domToPngDataUrl(
|
|
144
|
+
const dataURL = await domToPngDataUrl(
|
|
145
|
+
target.value,
|
|
146
|
+
customFilter.value,
|
|
147
|
+
customStyle.value,
|
|
148
|
+
padding.value,
|
|
149
|
+
dateRanges.value,
|
|
150
|
+
watermark.value,
|
|
151
|
+
WatermarkImage,
|
|
152
|
+
);
|
|
122
153
|
if (!dataURL) {
|
|
123
154
|
console.log("Can not generate data URL!");
|
|
124
155
|
return;
|
|
125
156
|
}
|
|
126
157
|
|
|
127
158
|
const blob = dataURLtoBlob(dataURL);
|
|
128
|
-
const data = [new window.ClipboardItem({
|
|
159
|
+
const data = [new window.ClipboardItem({ "image/png": blob })];
|
|
129
160
|
|
|
130
161
|
try {
|
|
131
162
|
await navigator.clipboard.write(data);
|
|
132
|
-
copyMsg.value =
|
|
163
|
+
copyMsg.value = "成功複製圖檔到剪貼簿";
|
|
133
164
|
isShowCopyMsg.value = true;
|
|
134
165
|
isCopySuccess.value = true;
|
|
135
166
|
} catch (e) {
|
|
136
|
-
copyMsg.value =
|
|
167
|
+
copyMsg.value = "無法複製圖檔到剪貼簿";
|
|
137
168
|
isShowCopyMsg.value = true;
|
|
138
169
|
isCopySuccess.value = false;
|
|
139
170
|
}
|
|
@@ -168,22 +199,22 @@ export default defineComponent({
|
|
|
168
199
|
clearTimeout(clearMsgTimeoutId);
|
|
169
200
|
}
|
|
170
201
|
clearMsgTimeoutId = setTimeout(() => {
|
|
171
|
-
copyMsg.value =
|
|
202
|
+
copyMsg.value = "";
|
|
172
203
|
}, 300);
|
|
173
204
|
}
|
|
174
205
|
|
|
175
206
|
function subscribeScrollEvents() {
|
|
176
|
-
window.addEventListener(
|
|
207
|
+
window.addEventListener("DOMMouseScroll", preventDefault, false); // older FF
|
|
177
208
|
window.addEventListener(wheelEvent, preventDefault, wheelOpt); // modern desktop
|
|
178
|
-
window.addEventListener(
|
|
179
|
-
window.addEventListener(
|
|
209
|
+
window.addEventListener("touchmove", preventDefault, wheelOpt); // mobile
|
|
210
|
+
window.addEventListener("keydown", preventDefaultForScrollKeys, false);
|
|
180
211
|
}
|
|
181
212
|
|
|
182
213
|
function unsubscribeScrollEvents() {
|
|
183
|
-
window.removeEventListener(
|
|
214
|
+
window.removeEventListener("DOMMouseScroll", preventDefault, false);
|
|
184
215
|
window.removeEventListener(wheelEvent, preventDefault, wheelOpt);
|
|
185
|
-
window.removeEventListener(
|
|
186
|
-
window.removeEventListener(
|
|
216
|
+
window.removeEventListener("touchmove", preventDefault, wheelOpt);
|
|
217
|
+
window.removeEventListener("keydown", preventDefaultForScrollKeys, false);
|
|
187
218
|
}
|
|
188
219
|
|
|
189
220
|
watch(isShow, () => {
|
|
@@ -202,7 +233,10 @@ export default defineComponent({
|
|
|
202
233
|
|
|
203
234
|
onMounted(() => {
|
|
204
235
|
if (el.value && el.value.parentElement) {
|
|
205
|
-
contextMenuSubscriber = fromEvent(
|
|
236
|
+
contextMenuSubscriber = fromEvent(
|
|
237
|
+
el.value.parentElement,
|
|
238
|
+
"contextmenu",
|
|
239
|
+
).subscribe((e) => {
|
|
206
240
|
onRightClick(e as PointerEvent);
|
|
207
241
|
});
|
|
208
242
|
}
|
|
@@ -232,25 +266,31 @@ export default defineComponent({
|
|
|
232
266
|
});
|
|
233
267
|
</script>
|
|
234
268
|
|
|
235
|
-
<style
|
|
236
|
-
.
|
|
237
|
-
@apply hidden
|
|
269
|
+
<style scoped>
|
|
270
|
+
@reference '~ui/app/assets/css/main.css';
|
|
238
271
|
|
|
239
|
-
.sl-context-menu-
|
|
240
|
-
@apply
|
|
272
|
+
.sl-context-menu-wrapper {
|
|
273
|
+
@apply hidden;
|
|
274
|
+
}
|
|
241
275
|
|
|
242
|
-
|
|
243
|
-
|
|
276
|
+
.sl-context-menu-container {
|
|
277
|
+
@apply fixed top-0 left-0 w-full h-full;
|
|
278
|
+
}
|
|
244
279
|
|
|
245
|
-
|
|
246
|
-
|
|
280
|
+
.sl-context-menu-container-modal {
|
|
281
|
+
@apply absolute top-0 left-0 w-full h-full;
|
|
282
|
+
}
|
|
247
283
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
284
|
+
.sl-context-menu-container .sl-context-menu {
|
|
285
|
+
@apply absolute top-0 left-0 m-0 border border-primary-600 rounded overflow-hidden shadow-popup-sm;
|
|
286
|
+
}
|
|
251
287
|
|
|
252
|
-
.
|
|
253
|
-
|
|
254
|
-
|
|
288
|
+
.sl-context-menu-container .sl-context-menu-item {
|
|
289
|
+
@apply block min-w-[160px] p-3 bg-white text-base text-gray-2;
|
|
290
|
+
@apply hover:bg-primary-100 hover:text-primary;
|
|
291
|
+
}
|
|
255
292
|
|
|
256
|
-
|
|
293
|
+
.toast.copy-msg-toast :deep(.toast-wrapper) {
|
|
294
|
+
@apply bg-black/80 shadow-popup-sm;
|
|
295
|
+
}
|
|
296
|
+
</style>
|
|
@@ -71,7 +71,7 @@ import { DatePicker } from "v-calendar";
|
|
|
71
71
|
import "v-calendar/style.css";
|
|
72
72
|
import type { PopoverVisibility } from "v-calendar/dist/types/src/utils/popovers";
|
|
73
73
|
import { isDate, differenceInCalendarDays } from "date-fns";
|
|
74
|
-
import type IDateRange from "~ui/interface/IDateRange";
|
|
74
|
+
import type IDateRange from "~ui/app/interface/IDateRange";
|
|
75
75
|
|
|
76
76
|
type DatePickerType = InstanceType<typeof DatePicker> & {
|
|
77
77
|
hidePopover: () => void;
|
|
@@ -180,12 +180,12 @@ export default defineComponent({
|
|
|
180
180
|
const startDate = ref<Date | null>(
|
|
181
181
|
isDate(modelValue.value)
|
|
182
182
|
? (modelValue.value as Date)
|
|
183
|
-
: (modelValue.value as IDateRange)?.start || null
|
|
183
|
+
: (modelValue.value as IDateRange)?.start || null,
|
|
184
184
|
);
|
|
185
185
|
const endDate = ref<Date | null>(
|
|
186
186
|
isDate(modelValue.value)
|
|
187
187
|
? null
|
|
188
|
-
: (modelValue.value as IDateRange)?.end || null
|
|
188
|
+
: (modelValue.value as IDateRange)?.end || null,
|
|
189
189
|
);
|
|
190
190
|
|
|
191
191
|
const dateInputClass = computed(() => {
|
|
@@ -364,98 +364,115 @@ export default defineComponent({
|
|
|
364
364
|
});
|
|
365
365
|
</script>
|
|
366
366
|
|
|
367
|
-
<style
|
|
368
|
-
.
|
|
369
|
-
&.date-input-xs
|
|
370
|
-
.input-group
|
|
371
|
-
&-prepend
|
|
372
|
-
@apply s('pl-2.75') pr-4 rounded-l-lg
|
|
367
|
+
<style>
|
|
368
|
+
@reference '~ui/app/assets/css/main.css';
|
|
373
369
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
.input-group
|
|
378
|
-
.inputs
|
|
379
|
-
div
|
|
380
|
-
input
|
|
381
|
-
@apply s('w-[5.875rem]') text-center
|
|
382
|
-
|
|
383
|
-
&.date-input-range.date-input-dateTime
|
|
384
|
-
.input-group
|
|
385
|
-
.inputs
|
|
386
|
-
div
|
|
387
|
-
input
|
|
388
|
-
@apply s('w-[10.5rem]')
|
|
389
|
-
|
|
390
|
-
&.inline
|
|
391
|
-
@apply flex
|
|
392
|
-
|
|
393
|
-
& > label
|
|
394
|
-
@apply flex-grow-0 flex-shrink-0 mb-0 mr-2 py-2 border-t border-b border-transparent
|
|
370
|
+
.date-input.date-input-xs .input-group-prepend {
|
|
371
|
+
@apply pl-2.75 pr-4 rounded-l-lg;
|
|
372
|
+
}
|
|
395
373
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
&.disabled, &.readonly
|
|
400
|
-
.input-group
|
|
401
|
-
.input-group-prepend, .inputs
|
|
402
|
-
@apply border-primary-500 bg-primary-100
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
& > label
|
|
406
|
-
@apply mb-2 text-base leading-normal text-pgray-2
|
|
407
|
-
|
|
408
|
-
.is-invalid
|
|
409
|
-
.input-group, .input-group.is-focus
|
|
410
|
-
.input-group-prepend
|
|
411
|
-
@apply border-danger-light
|
|
412
|
-
|
|
413
|
-
.inputs
|
|
414
|
-
@apply border-danger-light
|
|
415
|
-
|
|
416
|
-
.icon
|
|
417
|
-
@apply inline-block
|
|
418
|
-
|
|
419
|
-
.invalid-feedback
|
|
420
|
-
@apply block
|
|
374
|
+
.date-input.date-input-xs .input-group .inputs {
|
|
375
|
+
@apply pl-0 rounded-r-lg;
|
|
376
|
+
}
|
|
421
377
|
|
|
378
|
+
.date-input.date-input-xs .input-group .inputs div input {
|
|
379
|
+
@apply w-[5.875rem] text-center;
|
|
380
|
+
}
|
|
422
381
|
|
|
382
|
+
.date-input.date-input-range.date-input-dateTime
|
|
423
383
|
.input-group
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
384
|
+
.inputs
|
|
385
|
+
div
|
|
386
|
+
input {
|
|
387
|
+
@apply w-[10.5rem];
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
.date-input.inline {
|
|
391
|
+
@apply flex;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
.date-input.inline > label {
|
|
395
|
+
@apply grow-0 shrink-0 mb-0 mr-2 py-2 border-t border-b border-transparent;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
.date-input.inline .form-control {
|
|
399
|
+
@apply grow;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
.date-input.disabled .input-group .input-group-prepend,
|
|
403
|
+
.date-input.disabled .input-group .inputs,
|
|
404
|
+
.date-input.readonly .input-group .input-group-prepend,
|
|
405
|
+
.date-input.readonly .input-group .inputs {
|
|
406
|
+
@apply border-primary-500 bg-primary-100;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
.date-input > label {
|
|
410
|
+
@apply mb-2 text-base leading-[1.3125] text-pgray-2;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
.date-input .is-invalid .input-group .input-group-prepend,
|
|
414
|
+
.date-input .is-invalid .input-group.is-focus .input-group-prepend {
|
|
415
|
+
@apply border-danger-light;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
.date-input .is-invalid .input-group .inputs,
|
|
419
|
+
.date-input .is-invalid .input-group.is-focus .inputs {
|
|
420
|
+
@apply border-danger-light;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
.date-input .is-invalid .input-group .inputs .icon,
|
|
424
|
+
.date-input .is-invalid .input-group.is-focus .inputs .icon {
|
|
425
|
+
@apply inline-block;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
.date-input .is-invalid .invalid-feedback {
|
|
429
|
+
@apply block;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
.date-input .input-group {
|
|
433
|
+
@apply flex flex-nowrap w-full text-base leading-[1.3125];
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
.date-input .input-group.is-focus .input {
|
|
437
|
+
@apply border-primary;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
.date-input .input-group.is-fill .input .float-label,
|
|
441
|
+
.date-input .input-group.is-focus .input .float-label {
|
|
442
|
+
@apply ml-1.5 -mt-2.25 py-0 px-0.5 bg-white text-primary text-xs transition-(--transition-input-focus);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
.date-input .input-group .input-group-prepend {
|
|
446
|
+
@apply grow-0 shrink-0 flex items-center relative pl-4 pr-6 rounded-l border border-r-0 border-primary-500 bg-white text-base leading-none;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
.date-input .input-group .input-group-prepend::after {
|
|
450
|
+
content: "";
|
|
451
|
+
@apply block absolute top-2 right-1.75 bottom-2 w-px bg-primary;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
.date-input .input-group .inputs {
|
|
455
|
+
@apply relative grow flex items-center p-2 bg-white rounded-r border border-l-0 border-primary-500 text-base text-pgray-2;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
.date-input .input-group .inputs input {
|
|
459
|
+
@apply grow bg-transparent text-base text-pgray-2 text-left placeholder-pgray-4 focus:outline-none;
|
|
460
|
+
width: calc((100% - 25px) / 2);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
.date-input .input-group .inputs .date-range-split {
|
|
464
|
+
@apply grow-0 shrink-0 mx-0.5;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
.date-input .input-group .inputs .icon {
|
|
468
|
+
@apply absolute right-0 mr-2 text-danger-light hidden;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
.date-input .input-info {
|
|
472
|
+
@apply mt-1 text-xs text-pgray-3;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
.date-input .invalid-feedback {
|
|
476
|
+
@apply hidden text-danger text-xs;
|
|
477
|
+
}
|
|
460
478
|
</style>
|
|
461
|
-
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
max as dateMax,
|
|
30
30
|
isDate,
|
|
31
31
|
} from "date-fns";
|
|
32
|
-
import type IDateRange from "~ui/interface/IDateRange";
|
|
32
|
+
import type IDateRange from "~ui/app/interface/IDateRange";
|
|
33
33
|
|
|
34
34
|
type DatePickerType = InstanceType<typeof DatePicker>;
|
|
35
35
|
|
|
@@ -83,7 +83,7 @@ export default defineComponent({
|
|
|
83
83
|
|
|
84
84
|
const draggingMinDate = subDays(
|
|
85
85
|
draggingStartDate.value as Date,
|
|
86
|
-
maxDays.value - 1
|
|
86
|
+
maxDays.value - 1,
|
|
87
87
|
);
|
|
88
88
|
|
|
89
89
|
return minDate.value
|
|
@@ -95,7 +95,7 @@ export default defineComponent({
|
|
|
95
95
|
|
|
96
96
|
const draggingMaxDate = addDays(
|
|
97
97
|
draggingStartDate.value as Date,
|
|
98
|
-
maxDays.value - 1
|
|
98
|
+
maxDays.value - 1,
|
|
99
99
|
);
|
|
100
100
|
|
|
101
101
|
return maxDate.value
|
|
@@ -136,8 +136,10 @@ export default defineComponent({
|
|
|
136
136
|
});
|
|
137
137
|
</script>
|
|
138
138
|
|
|
139
|
-
<style
|
|
140
|
-
.
|
|
141
|
-
|
|
142
|
-
|
|
139
|
+
<style>
|
|
140
|
+
@reference '~ui/app/assets/css/main.css';
|
|
141
|
+
|
|
142
|
+
.custom-date-picker .vc-pane-container {
|
|
143
|
+
@apply border-0;
|
|
144
|
+
}
|
|
143
145
|
</style>
|
|
@@ -31,20 +31,15 @@ import { fromEvent, Subscription } from "rxjs";
|
|
|
31
31
|
import { createPopper } from "@popperjs/core";
|
|
32
32
|
import type { Instance as PopperInstance, Placement } from "@popperjs/core";
|
|
33
33
|
import ExcelJS from "exceljs";
|
|
34
|
-
import {
|
|
35
|
-
|
|
36
|
-
downloadBlob,
|
|
37
|
-
gaev,
|
|
38
|
-
ga4ev,
|
|
39
|
-
} from "~ui/utils";
|
|
40
|
-
import type IDateRange from "~ui/interface/IDateRange";
|
|
34
|
+
import { downloadURL, downloadBlob, gaev, ga4ev } from "~ui/app/utils";
|
|
35
|
+
import type IDateRange from "~ui/app/interface/IDateRange";
|
|
41
36
|
|
|
42
37
|
// http://www.excelcodex.com/2012/06/worksheets-naming-conventions/
|
|
43
38
|
function safeSheetName(name: string) {
|
|
44
39
|
return name.replace(/[\\/*?:[\]]/g, "").substring(0, 31);
|
|
45
40
|
}
|
|
46
41
|
|
|
47
|
-
const WatermarkImage =
|
|
42
|
+
const WatermarkImage = "/assets/images/commons/watermark-2.svg";
|
|
48
43
|
|
|
49
44
|
export default defineComponent({
|
|
50
45
|
name: "SLDownloadButton",
|
|
@@ -93,7 +88,7 @@ export default defineComponent({
|
|
|
93
88
|
},
|
|
94
89
|
customStyle: {
|
|
95
90
|
type: Object as PropType<Partial<CSSStyleDeclaration>>,
|
|
96
|
-
default: () => {
|
|
91
|
+
default: () => {},
|
|
97
92
|
},
|
|
98
93
|
evCategory: {
|
|
99
94
|
type: String,
|
|
@@ -204,7 +199,7 @@ export default defineComponent({
|
|
|
204
199
|
const workbook = new ExcelJS.Workbook();
|
|
205
200
|
sheets.value.map((sheetData) => {
|
|
206
201
|
const sheet = workbook.addWorksheet(
|
|
207
|
-
sheetData?.sheetName ? safeSheetName(sheetData.sheetName) : ""
|
|
202
|
+
sheetData?.sheetName ? safeSheetName(sheetData.sheetName) : "",
|
|
208
203
|
);
|
|
209
204
|
(sheetData?.sheetData || []).forEach((rowData) => {
|
|
210
205
|
sheet.addRow(rowData);
|
|
@@ -215,12 +210,20 @@ export default defineComponent({
|
|
|
215
210
|
downloadBlob(
|
|
216
211
|
buffer,
|
|
217
212
|
`${fileName.value}.xlsx`,
|
|
218
|
-
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
213
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
219
214
|
);
|
|
220
215
|
return;
|
|
221
216
|
}
|
|
222
217
|
|
|
223
|
-
const dataURL = await domToPngDataUrl(
|
|
218
|
+
const dataURL = await domToPngDataUrl(
|
|
219
|
+
imageTarget.value,
|
|
220
|
+
customFilter.value,
|
|
221
|
+
customStyle.value,
|
|
222
|
+
padding.value,
|
|
223
|
+
dateRanges.value,
|
|
224
|
+
watermark.value,
|
|
225
|
+
WatermarkImage,
|
|
226
|
+
);
|
|
224
227
|
if (!dataURL) {
|
|
225
228
|
console.log("Can not generate data URL!");
|
|
226
229
|
return;
|
|
@@ -269,27 +272,34 @@ export default defineComponent({
|
|
|
269
272
|
});
|
|
270
273
|
</script>
|
|
271
274
|
|
|
272
|
-
<style
|
|
273
|
-
.
|
|
274
|
-
@apply inline-block
|
|
275
|
+
<style>
|
|
276
|
+
@reference '~ui/app/assets/css/main.css';
|
|
275
277
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
278
|
+
.download-button {
|
|
279
|
+
@apply inline-block;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.download-button.disabled .download-button-toggle {
|
|
283
|
+
@apply border-pgray-5 text-pgray-5 cursor-default;
|
|
284
|
+
}
|
|
279
285
|
|
|
280
|
-
|
|
281
|
-
|
|
286
|
+
.download-button-toggle {
|
|
287
|
+
@apply inline-flex justify-center items-center w-[28px] h-[28px] bg-white border border-primary-600 rounded text-lg text-primary-600;
|
|
288
|
+
}
|
|
282
289
|
|
|
283
|
-
|
|
284
|
-
|
|
290
|
+
.download-button-toggle.active {
|
|
291
|
+
@apply bg-primary-600 text-white;
|
|
292
|
+
}
|
|
285
293
|
|
|
286
|
-
.download-button-popup
|
|
287
|
-
@apply z-60 absolute flex flex-col bg-white border border-primary-500 rounded overflow-hidden shadow invisible pointer-events-none
|
|
294
|
+
.download-button-popup {
|
|
295
|
+
@apply z-60 absolute flex flex-col bg-white border border-primary-500 rounded overflow-hidden shadow-default invisible pointer-events-none;
|
|
296
|
+
}
|
|
288
297
|
|
|
289
|
-
|
|
290
|
-
|
|
298
|
+
.download-button-popup[data-show] {
|
|
299
|
+
@apply visible pointer-events-auto;
|
|
300
|
+
}
|
|
291
301
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
302
|
+
.download-button-popup .download-option {
|
|
303
|
+
@apply block p-2 bg-white text-sm text-pgray-3 hover:bg-primary-100 hover:text-primary;
|
|
304
|
+
}
|
|
295
305
|
</style>
|
|
@@ -58,7 +58,7 @@ export default defineComponent({
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
const elIndex = Array.from(draggableEl.value.children).indexOf(
|
|
61
|
-
dragEl
|
|
61
|
+
dragEl,
|
|
62
62
|
);
|
|
63
63
|
|
|
64
64
|
if (elIndex === -1) {
|
|
@@ -148,4 +148,4 @@ export default defineComponent({
|
|
|
148
148
|
});
|
|
149
149
|
</script>
|
|
150
150
|
|
|
151
|
-
<style
|
|
151
|
+
<style></style>
|