@7365admin1/layer-common 1.9.0 → 1.10.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/CHANGELOG.md +12 -0
- package/components/AcceptDialog.vue +44 -0
- package/components/AccessCardAddForm.vue +101 -13
- package/components/AccessManagement.vue +130 -47
- package/components/AddSupplyForm.vue +165 -0
- package/components/AreaChecklistHistoryLogs.vue +235 -0
- package/components/AreaChecklistHistoryMain.vue +176 -0
- package/components/AreaFormDialog.vue +266 -0
- package/components/AreaMain.vue +841 -0
- package/components/AttendanceCheckInOutDialog.vue +416 -0
- package/components/AttendanceDetailsDialog.vue +184 -0
- package/components/AttendanceMain.vue +155 -0
- package/components/AttendanceMapSearchDialog.vue +393 -0
- package/components/AttendanceSettingsDialog.vue +398 -0
- package/components/BuildingManagement/buildings.vue +5 -5
- package/components/BuildingManagement/units.vue +5 -5
- package/components/ChecklistItemRow.vue +54 -0
- package/components/CheckoutItemMain.vue +705 -0
- package/components/CleaningScheduleMain.vue +271 -0
- package/components/DocumentManagement.vue +8 -9
- package/components/EntryPass/QrTemplatePreview.vue +104 -0
- package/components/EntryPassMain.vue +252 -200
- package/components/HygieneUpdateMoreAction.vue +238 -0
- package/components/IncidentReport/Authorities.vue +226 -0
- package/components/IncidentReport/IncidentInformation.vue +258 -0
- package/components/IncidentReport/affectedEntities.vue +167 -0
- package/components/InvitationMain.vue +19 -17
- package/components/ManageChecklistMain.vue +384 -0
- package/components/MemberMain.vue +48 -20
- package/components/MyAttendanceMain.vue +224 -0
- package/components/OnlineFormsConfiguration.vue +9 -2
- package/components/PasswordConfirmation.vue +95 -0
- package/components/PhotoUpload.vue +410 -0
- package/components/RolePermissionMain.vue +17 -15
- package/components/ScheduleAreaMain.vue +313 -0
- package/components/ScheduleTaskAreaFormDialog.vue +144 -0
- package/components/ScheduleTaskAreaUpdateMoreAction.vue +109 -0
- package/components/ScheduleTaskForm.vue +471 -0
- package/components/ScheduleTaskMain.vue +345 -0
- package/components/ScheduleTastTicketMain.vue +182 -0
- package/components/ServiceProviderMain.vue +27 -7
- package/components/StockCard.vue +191 -0
- package/components/SupplyManagementMain.vue +557 -0
- package/components/TableHygiene.vue +617 -0
- package/components/UnitMain.vue +451 -0
- package/components/VisitorManagement.vue +28 -15
- package/composables/useAccessManagement.ts +90 -0
- package/composables/useAreaPermission.ts +51 -0
- package/composables/useAreas.ts +99 -0
- package/composables/useAttendance.ts +89 -0
- package/composables/useAttendancePermission.ts +68 -0
- package/composables/useBuilding.ts +2 -2
- package/composables/useBuildingUnit.ts +2 -2
- package/composables/useCard.ts +2 -0
- package/composables/useCheckout.ts +61 -0
- package/composables/useCheckoutPermission.ts +80 -0
- package/composables/useCleaningPermission.ts +229 -0
- package/composables/useCleaningSchedulePermission.ts +58 -0
- package/composables/useCleaningSchedules.ts +233 -0
- package/composables/useCountry.ts +8 -0
- package/composables/useDOBEntries.ts +13 -0
- package/composables/useDashboardData.ts +2 -2
- package/composables/useDocument.ts +3 -2
- package/composables/useFeedback.ts +1 -1
- package/composables/useFile.ts +4 -6
- package/composables/useLocation.ts +78 -0
- package/composables/useOnlineForm.ts +16 -9
- package/composables/usePeople.ts +87 -72
- package/composables/useQR.ts +29 -0
- package/composables/useRole.ts +3 -2
- package/composables/useScheduleTask.ts +89 -0
- package/composables/useScheduleTaskArea.ts +85 -0
- package/composables/useScheduleTaskPermission.ts +68 -0
- package/composables/useSiteEntryPassSettings.ts +4 -15
- package/composables/useStock.ts +45 -0
- package/composables/useSupply.ts +63 -0
- package/composables/useSupplyPermission.ts +92 -0
- package/composables/useUnitPermission.ts +51 -0
- package/composables/useUnits.ts +82 -0
- package/composables/useWebUsb.ts +389 -0
- package/composables/useWorkOrder.ts +1 -1
- package/nuxt.config.ts +3 -0
- package/package.json +4 -1
- package/types/area.d.ts +22 -0
- package/types/attendance.d.ts +38 -0
- package/types/checkout-item.d.ts +27 -0
- package/types/cleaner-schedule.d.ts +54 -0
- package/types/location.d.ts +42 -0
- package/types/schedule-task.d.ts +18 -0
- package/types/stock.d.ts +16 -0
- package/types/supply.d.ts +11 -0
- package/types/verification.d.ts +1 -1
- package/utils/acm-crypto.ts +30 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-row no-gutters align="center" justify="center">
|
|
3
|
+
<v-col cols="12" lg="12">
|
|
4
|
+
<TableMain
|
|
5
|
+
v-if="canViewSchedules"
|
|
6
|
+
:title="'Cleaner Checklist'"
|
|
7
|
+
:items="items"
|
|
8
|
+
:headers="headers"
|
|
9
|
+
:loading="loading"
|
|
10
|
+
:show-header="true"
|
|
11
|
+
v-model:page="page"
|
|
12
|
+
:pages="pages"
|
|
13
|
+
:pageRange="pageRange"
|
|
14
|
+
:no-data-text="'No Cleaner Checklist found'"
|
|
15
|
+
@refresh="getCleanerChecklistRefresh"
|
|
16
|
+
@row-click="onRowClick"
|
|
17
|
+
>
|
|
18
|
+
<template #extension>
|
|
19
|
+
<v-row no-gutters class="w-100 d-flex flex-column">
|
|
20
|
+
<v-card
|
|
21
|
+
class="w-100 px-3 d-flex align-center ga-5 py-2"
|
|
22
|
+
flat
|
|
23
|
+
:height="60"
|
|
24
|
+
>
|
|
25
|
+
<InputDateTimePicker
|
|
26
|
+
v-model:utc="startDate"
|
|
27
|
+
density="compact"
|
|
28
|
+
hide-details
|
|
29
|
+
/>
|
|
30
|
+
<InputDateTimePicker
|
|
31
|
+
v-model:utc="endDate"
|
|
32
|
+
density="compact"
|
|
33
|
+
hide-details
|
|
34
|
+
/>
|
|
35
|
+
<v-select
|
|
36
|
+
v-model="status"
|
|
37
|
+
:items="statusOptions"
|
|
38
|
+
density="compact"
|
|
39
|
+
hide-details
|
|
40
|
+
class="mx-3"
|
|
41
|
+
style="max-width: 160px"
|
|
42
|
+
item-title="title"
|
|
43
|
+
item-value="value"
|
|
44
|
+
label="Status"
|
|
45
|
+
/>
|
|
46
|
+
</v-card>
|
|
47
|
+
</v-row>
|
|
48
|
+
</template>
|
|
49
|
+
|
|
50
|
+
<template #item.createdAt="{ value }">
|
|
51
|
+
{{
|
|
52
|
+
formatDate
|
|
53
|
+
? formatDate(value)
|
|
54
|
+
: value
|
|
55
|
+
? new Date(value).toLocaleString()
|
|
56
|
+
: ""
|
|
57
|
+
}}
|
|
58
|
+
</template>
|
|
59
|
+
<template #item.closeIn="{ item }">
|
|
60
|
+
<!-- <v-chip class="text-capitalize">{{ value || "No Status" }}</v-chip> -->
|
|
61
|
+
<v-chip class="text-capitalize" variant="flat" color="primary">{{
|
|
62
|
+
remainingTime[item._id] || "No Status"
|
|
63
|
+
}}</v-chip>
|
|
64
|
+
</template>
|
|
65
|
+
<template #item.status="{ value }">
|
|
66
|
+
<v-chip
|
|
67
|
+
class="text-capitalize"
|
|
68
|
+
:color="getStatusColor(value)"
|
|
69
|
+
variant="flat"
|
|
70
|
+
pill
|
|
71
|
+
>
|
|
72
|
+
{{ value || "No Status" }}
|
|
73
|
+
</v-chip>
|
|
74
|
+
</template>
|
|
75
|
+
<template #item.download="{ item }">
|
|
76
|
+
<v-btn
|
|
77
|
+
v-if="canDownloadSchedule"
|
|
78
|
+
variant="outlined"
|
|
79
|
+
size="medium"
|
|
80
|
+
class="text-capitalize px-4 py-2"
|
|
81
|
+
:loading="downloadingId === item._id"
|
|
82
|
+
@click.stop="downloadItem(item)"
|
|
83
|
+
>
|
|
84
|
+
<v-icon left>mdi-download</v-icon>
|
|
85
|
+
Download
|
|
86
|
+
</v-btn>
|
|
87
|
+
</template>
|
|
88
|
+
</TableMain>
|
|
89
|
+
<div v-else class="pa-4">
|
|
90
|
+
<v-card variant="outlined" class="pa-4">
|
|
91
|
+
<div class="text-subtitle-1">
|
|
92
|
+
You do not have permission to view cleaning schedules.
|
|
93
|
+
</div>
|
|
94
|
+
</v-card>
|
|
95
|
+
</div>
|
|
96
|
+
</v-col>
|
|
97
|
+
</v-row>
|
|
98
|
+
</template>
|
|
99
|
+
|
|
100
|
+
<script lang="ts" setup>
|
|
101
|
+
import { useCleaningSchedulePermission } from "../composables/useCleaningSchedulePermission";
|
|
102
|
+
import useCleaningSchedules from "../composables/useCleaningSchedules";
|
|
103
|
+
|
|
104
|
+
const props = defineProps({
|
|
105
|
+
orgId: { type: String, required: true },
|
|
106
|
+
site: { type: String, required: true },
|
|
107
|
+
type: { type: String, required: true },
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const startDate = ref("");
|
|
111
|
+
const endDate = ref("");
|
|
112
|
+
const status = ref<TScheduleAreaStatus>("All");
|
|
113
|
+
const statusOptions = [
|
|
114
|
+
{ title: "All", value: "all" },
|
|
115
|
+
{ title: "Ready", value: "ready" },
|
|
116
|
+
{ title: "Ongoing", value: "ongoing" },
|
|
117
|
+
{ title: "Completed", value: "completed" },
|
|
118
|
+
] as const;
|
|
119
|
+
|
|
120
|
+
const items = ref<Array<Record<string, any>>>([]);
|
|
121
|
+
const page = ref(1);
|
|
122
|
+
const pages = ref(0);
|
|
123
|
+
const pageRange = ref("-- - -- of --");
|
|
124
|
+
|
|
125
|
+
const headers = [
|
|
126
|
+
{ title: "Created Date", value: "createdAt" },
|
|
127
|
+
{ title: "Close in", value: "closeIn" },
|
|
128
|
+
{ title: "Status", value: "status" },
|
|
129
|
+
{ title: "Completion Date", value: "completionDate" },
|
|
130
|
+
{ title: "", value: "download" },
|
|
131
|
+
];
|
|
132
|
+
const remainingTime = ref({} as any);
|
|
133
|
+
const downloadingId = ref<string | null>(null);
|
|
134
|
+
|
|
135
|
+
const { getCleaningSchedules, downloadChecklistPdf } = useCleaningSchedules();
|
|
136
|
+
const { formatDate } = useUtils();
|
|
137
|
+
|
|
138
|
+
const getStatusColor = (status: unknown): string => {
|
|
139
|
+
if (!status) return "grey";
|
|
140
|
+
|
|
141
|
+
const normalized = String(status).toLowerCase();
|
|
142
|
+
|
|
143
|
+
switch (normalized) {
|
|
144
|
+
case "ready":
|
|
145
|
+
return "grey";
|
|
146
|
+
case "ongoing":
|
|
147
|
+
return "primary";
|
|
148
|
+
case "completed":
|
|
149
|
+
case "accepted":
|
|
150
|
+
return "success";
|
|
151
|
+
default:
|
|
152
|
+
return "secondary";
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const {
|
|
157
|
+
canDownloadSchedule,
|
|
158
|
+
canViewSchedules,
|
|
159
|
+
canViewScheduleDetails,
|
|
160
|
+
canManageScheduleTasks,
|
|
161
|
+
} = useCleaningSchedulePermission();
|
|
162
|
+
|
|
163
|
+
const {
|
|
164
|
+
data: getCleanerChecklistReq,
|
|
165
|
+
refresh: getCleanerChecklistRefresh,
|
|
166
|
+
pending: loading,
|
|
167
|
+
} = await useLazyAsyncData(
|
|
168
|
+
"get-all-areas",
|
|
169
|
+
() =>
|
|
170
|
+
getCleaningSchedules({
|
|
171
|
+
page: page.value,
|
|
172
|
+
site: props.site,
|
|
173
|
+
startDate: startDate.value,
|
|
174
|
+
endDate: endDate.value,
|
|
175
|
+
status: status.value === "All" ? undefined : status.value,
|
|
176
|
+
}),
|
|
177
|
+
{
|
|
178
|
+
watch: [() => page.value, () => props.site, startDate, endDate, status],
|
|
179
|
+
}
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
function calculateRemainingTime(
|
|
183
|
+
item: Date | string | number | null | undefined
|
|
184
|
+
) {
|
|
185
|
+
if (!item) return -1;
|
|
186
|
+
const _date = new Date(item);
|
|
187
|
+
if (isNaN(_date.getTime())) return -1;
|
|
188
|
+
const creationTime = _date.getTime();
|
|
189
|
+
const currentTime = Date.now();
|
|
190
|
+
const differenceInMillis = currentTime - creationTime;
|
|
191
|
+
const differenceInSeconds = Math.floor(differenceInMillis / 1000);
|
|
192
|
+
const desiredDurationInSeconds = 24 * 60 * 60;
|
|
193
|
+
const remainingTimeInSeconds = desiredDurationInSeconds - differenceInSeconds;
|
|
194
|
+
return remainingTimeInSeconds;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const formatTime = (seconds: number) => {
|
|
198
|
+
if (seconds <= 0 || isNaN(seconds)) return "00h 00m";
|
|
199
|
+
const hours = Math.floor(seconds / 3600);
|
|
200
|
+
const minutes = Math.floor((seconds % 3600) / 60);
|
|
201
|
+
return `${String(hours).padStart(2, "0")}h ${String(minutes).padStart(
|
|
202
|
+
2,
|
|
203
|
+
"0"
|
|
204
|
+
)}m`;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const updateRemainingTime = () => {
|
|
208
|
+
console.log(items.value);
|
|
209
|
+
items.value.forEach((item) => {
|
|
210
|
+
const itemId = item._id as string;
|
|
211
|
+
const _time = calculateRemainingTime(item.date as string);
|
|
212
|
+
remainingTime.value[itemId] = _time < 0 ? "00h 00m" : formatTime(_time);
|
|
213
|
+
});
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
watchEffect(() => {
|
|
217
|
+
if (getCleanerChecklistReq.value) {
|
|
218
|
+
items.value = getCleanerChecklistReq.value.items;
|
|
219
|
+
pages.value = getCleanerChecklistReq.value.pages;
|
|
220
|
+
pageRange.value = getCleanerChecklistReq.value.pageRange;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
updateRemainingTime();
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
async function downloadItem(item: any) {
|
|
227
|
+
const id = item?._id;
|
|
228
|
+
if (!id) return;
|
|
229
|
+
|
|
230
|
+
try {
|
|
231
|
+
downloadingId.value = id;
|
|
232
|
+
await downloadChecklistPdf(id);
|
|
233
|
+
} catch (err) {
|
|
234
|
+
console.error("Failed to download checklist PDF", err);
|
|
235
|
+
} finally {
|
|
236
|
+
downloadingId.value = null;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function onRowClick(data: any) {
|
|
241
|
+
const item = data?.item ?? data;
|
|
242
|
+
const id = item?._id || item?.id || item?.areaId;
|
|
243
|
+
if (id) {
|
|
244
|
+
if (!canViewScheduleDetails.value) {
|
|
245
|
+
showMessage(
|
|
246
|
+
"You do not have permission to view schedule details.",
|
|
247
|
+
"error"
|
|
248
|
+
);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (props.type === "toilet") {
|
|
253
|
+
const path = `/${props.orgId}/${props.site}/toilet-checklist/${id}`;
|
|
254
|
+
navigateTo(path);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const path = `/${props.orgId}/${props.site}/cleaning-schedule/${id}`;
|
|
258
|
+
navigateTo(path);
|
|
259
|
+
} else {
|
|
260
|
+
console.warn("Row clicked but no id found to navigate:", item);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function showMessage(msg: string, color: string = "error") {
|
|
265
|
+
try {
|
|
266
|
+
console.warn(msg);
|
|
267
|
+
} catch (e) {
|
|
268
|
+
alert(msg);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
</script>
|
|
@@ -165,12 +165,6 @@
|
|
|
165
165
|
Are you sure you want to delete this document? This action cannot be
|
|
166
166
|
undone.
|
|
167
167
|
</p>
|
|
168
|
-
|
|
169
|
-
<v-row v-if="message" no-gutters justify="center" class="mt-4">
|
|
170
|
-
<span class="text-caption text-error text-center">
|
|
171
|
-
{{ message }}
|
|
172
|
-
</span>
|
|
173
|
-
</v-row>
|
|
174
168
|
</v-card-text>
|
|
175
169
|
|
|
176
170
|
<v-toolbar density="compact">
|
|
@@ -270,6 +264,9 @@ const messageColor = ref("");
|
|
|
270
264
|
|
|
271
265
|
const items = ref<Array<Record<string, any>>>([]);
|
|
272
266
|
|
|
267
|
+
const route = useRoute();
|
|
268
|
+
const siteId = route.params.site as string;
|
|
269
|
+
|
|
273
270
|
const {
|
|
274
271
|
data: getDocumentReq,
|
|
275
272
|
refresh: getDocuments,
|
|
@@ -280,6 +277,7 @@ const {
|
|
|
280
277
|
_getAllDocuments({
|
|
281
278
|
page: page.value,
|
|
282
279
|
search: headerSearch.value,
|
|
280
|
+
site: siteId,
|
|
283
281
|
}),
|
|
284
282
|
{
|
|
285
283
|
watch: [page, headerSearch],
|
|
@@ -303,7 +301,7 @@ const selectedDocument = ref<TDocument>({
|
|
|
303
301
|
_id: "",
|
|
304
302
|
name: "",
|
|
305
303
|
attachment: "",
|
|
306
|
-
type: ""
|
|
304
|
+
type: "",
|
|
307
305
|
});
|
|
308
306
|
const deleteLoading = ref(false);
|
|
309
307
|
const confirmDialog = ref(false);
|
|
@@ -354,7 +352,8 @@ function openEditDialog() {
|
|
|
354
352
|
async function handleDeleteDocument() {
|
|
355
353
|
deleteLoading.value = true;
|
|
356
354
|
try {
|
|
357
|
-
await deleteById(selectedDocument.value._id ?? "");
|
|
355
|
+
const response = await deleteById(selectedDocument.value._id ?? "");
|
|
356
|
+
showMessage(response.message, "success");
|
|
358
357
|
await getDocuments();
|
|
359
358
|
selectedDocumentId.value = null;
|
|
360
359
|
confirmDialog.value = false;
|
|
@@ -372,5 +371,5 @@ function successUpdate() {
|
|
|
372
371
|
previewDialog.value = false;
|
|
373
372
|
getDocuments();
|
|
374
373
|
showMessage("Document updated successfully!", "success");
|
|
375
|
-
}
|
|
374
|
+
}
|
|
376
375
|
</script>
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-dialog
|
|
3
|
+
:model-value="modelValue"
|
|
4
|
+
transition="dialog-right-transition"
|
|
5
|
+
width="550"
|
|
6
|
+
persistent
|
|
7
|
+
@update:model-value="emit('update:modelValue', $event)"
|
|
8
|
+
>
|
|
9
|
+
<v-card>
|
|
10
|
+
<v-toolbar
|
|
11
|
+
style="height: 12px"
|
|
12
|
+
:color="isDark ? 'grey-darken-4' : 'white'"
|
|
13
|
+
>
|
|
14
|
+
<v-spacer></v-spacer>
|
|
15
|
+
<v-btn
|
|
16
|
+
color="grey-darken-1"
|
|
17
|
+
icon="mdi-close"
|
|
18
|
+
@click="emit('update:modelValue', false)"
|
|
19
|
+
></v-btn>
|
|
20
|
+
</v-toolbar>
|
|
21
|
+
|
|
22
|
+
<v-card-text style="padding: 0 !important">
|
|
23
|
+
<v-container>
|
|
24
|
+
<v-row no-gutters class="text-center">
|
|
25
|
+
<v-col cols="12">
|
|
26
|
+
<p class="font-weight-bold text-h5 mb-3">{{ header }}</p>
|
|
27
|
+
<p>{{ subText }}</p>
|
|
28
|
+
</v-col>
|
|
29
|
+
|
|
30
|
+
<v-col cols="12" class="mt-5">
|
|
31
|
+
<!-- UPPER QR -->
|
|
32
|
+
<v-row no-gutters>
|
|
33
|
+
<v-col cols="6">
|
|
34
|
+
<img v-if="qrSmall" :src="qrSmall" width="80" height="80" />
|
|
35
|
+
</v-col>
|
|
36
|
+
<v-col cols="6">
|
|
37
|
+
<img v-if="qrSmall" :src="qrSmall" width="80" height="80" />
|
|
38
|
+
</v-col>
|
|
39
|
+
</v-row>
|
|
40
|
+
|
|
41
|
+
<!-- CENTER QR -->
|
|
42
|
+
<img v-if="qrLarge" :src="qrLarge" width="130" height="130" class="my-2" />
|
|
43
|
+
|
|
44
|
+
<!-- LOWER QR -->
|
|
45
|
+
<v-row no-gutters>
|
|
46
|
+
<v-col cols="6">
|
|
47
|
+
<img v-if="qrSmall" :src="qrSmall" width="80" height="80" />
|
|
48
|
+
</v-col>
|
|
49
|
+
<v-col cols="6">
|
|
50
|
+
<img v-if="qrSmall" :src="qrSmall" width="80" height="80" />
|
|
51
|
+
</v-col>
|
|
52
|
+
</v-row>
|
|
53
|
+
</v-col>
|
|
54
|
+
|
|
55
|
+
<v-col cols="12" class="mt-5">
|
|
56
|
+
<p class="font-weight-bold text-h5 mb-2">Company Name</p>
|
|
57
|
+
<p class="font-weight-bold text-h5 mb-3">BL 01/03/24</p>
|
|
58
|
+
<p class="mb-1">{{ `Date: ${dateStr} ${timeStr}` }}</p>
|
|
59
|
+
<p class="mb-1">Access: Door</p>
|
|
60
|
+
<p>Scan and press level 1. One time use.</p>
|
|
61
|
+
</v-col>
|
|
62
|
+
</v-row>
|
|
63
|
+
</v-container>
|
|
64
|
+
</v-card-text>
|
|
65
|
+
</v-card>
|
|
66
|
+
</v-dialog>
|
|
67
|
+
</template>
|
|
68
|
+
|
|
69
|
+
<script lang="ts" setup>
|
|
70
|
+
import { useTheme } from "vuetify";
|
|
71
|
+
import QRCode from "qrcode";
|
|
72
|
+
|
|
73
|
+
defineProps({
|
|
74
|
+
modelValue: {
|
|
75
|
+
type: Boolean,
|
|
76
|
+
default: false,
|
|
77
|
+
},
|
|
78
|
+
header: {
|
|
79
|
+
type: String,
|
|
80
|
+
default: "",
|
|
81
|
+
},
|
|
82
|
+
subText: {
|
|
83
|
+
type: String,
|
|
84
|
+
default: "",
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const emit = defineEmits(["update:modelValue"]);
|
|
89
|
+
|
|
90
|
+
const { global: themeGlobal } = useTheme();
|
|
91
|
+
const isDark = computed(() => themeGlobal.current.value.dark);
|
|
92
|
+
|
|
93
|
+
const qrSmall = ref<string>("");
|
|
94
|
+
const qrLarge = ref<string>("");
|
|
95
|
+
|
|
96
|
+
onMounted(async () => {
|
|
97
|
+
qrSmall.value = await QRCode.toDataURL("123123", { width: 80, margin: 1 });
|
|
98
|
+
qrLarge.value = await QRCode.toDataURL("123123", { width: 130, margin: 1 });
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
const now = new Date();
|
|
102
|
+
const dateStr = now.toLocaleDateString();
|
|
103
|
+
const timeStr = now.toLocaleTimeString();
|
|
104
|
+
</script>
|