@hostlink/nuxt-light 0.0.3
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/README.md +106 -0
- package/dist/module.cjs +5 -0
- package/dist/module.d.ts +7 -0
- package/dist/module.json +5 -0
- package/dist/module.mjs +51 -0
- package/dist/runtime/assets/element.css +15925 -0
- package/dist/runtime/assets/element.css.map +1 -0
- package/dist/runtime/assets/main.css +13 -0
- package/dist/runtime/components/l-add-btn.vue +22 -0
- package/dist/runtime/components/l-app-main.vue +214 -0
- package/dist/runtime/components/l-app.vue +17 -0
- package/dist/runtime/components/l-back-btn.vue +7 -0
- package/dist/runtime/components/l-btn.vue +19 -0
- package/dist/runtime/components/l-card.vue +19 -0
- package/dist/runtime/components/l-checkbox.vue +6 -0
- package/dist/runtime/components/l-col.vue +14 -0
- package/dist/runtime/components/l-customizer.vue +102 -0
- package/dist/runtime/components/l-date-picker.vue +78 -0
- package/dist/runtime/components/l-delete-btn.vue +23 -0
- package/dist/runtime/components/l-edit-btn.vue +3 -0
- package/dist/runtime/components/l-file-manager-labels.vue +55 -0
- package/dist/runtime/components/l-file-manager-move.vue +185 -0
- package/dist/runtime/components/l-file-manager-preview.vue +59 -0
- package/dist/runtime/components/l-file-manager.vue +618 -0
- package/dist/runtime/components/l-file.vue +33 -0
- package/dist/runtime/components/l-form.vue +73 -0
- package/dist/runtime/components/l-input.vue +48 -0
- package/dist/runtime/components/l-item.vue +14 -0
- package/dist/runtime/components/l-link.vue +24 -0
- package/dist/runtime/components/l-list.vue +5 -0
- package/dist/runtime/components/l-login.vue +128 -0
- package/dist/runtime/components/l-menu.vue +37 -0
- package/dist/runtime/components/l-page.vue +94 -0
- package/dist/runtime/components/l-row.vue +5 -0
- package/dist/runtime/components/l-save-btn.vue +3 -0
- package/dist/runtime/components/l-select.vue +77 -0
- package/dist/runtime/components/l-table.vue +333 -0
- package/dist/runtime/components/l-tabs.vue +5 -0
- package/dist/runtime/components/l-time-picker.vue +28 -0
- package/dist/runtime/components/l-view-btn.vue +3 -0
- package/dist/runtime/composables/addObject.d.ts +2 -0
- package/dist/runtime/composables/addObject.mjs +6 -0
- package/dist/runtime/composables/f.d.ts +1 -0
- package/dist/runtime/composables/f.mjs +27 -0
- package/dist/runtime/composables/getApiUrl.d.ts +1 -0
- package/dist/runtime/composables/getApiUrl.mjs +4 -0
- package/dist/runtime/composables/getCurrentUser.d.ts +2 -0
- package/dist/runtime/composables/getCurrentUser.mjs +8 -0
- package/dist/runtime/composables/getObject.d.ts +1 -0
- package/dist/runtime/composables/getObject.mjs +20 -0
- package/dist/runtime/composables/id.d.ts +2 -0
- package/dist/runtime/composables/id.mjs +12 -0
- package/dist/runtime/composables/list.d.ts +1 -0
- package/dist/runtime/composables/list.mjs +33 -0
- package/dist/runtime/composables/listData.d.ts +1 -0
- package/dist/runtime/composables/listData.mjs +30 -0
- package/dist/runtime/composables/login.d.ts +2 -0
- package/dist/runtime/composables/login.mjs +17 -0
- package/dist/runtime/composables/m.d.ts +1 -0
- package/dist/runtime/composables/m.mjs +73 -0
- package/dist/runtime/composables/mutation.d.ts +1 -0
- package/dist/runtime/composables/mutation.mjs +23 -0
- package/dist/runtime/composables/q.d.ts +1 -0
- package/dist/runtime/composables/q.mjs +18 -0
- package/dist/runtime/composables/removeObject.d.ts +1 -0
- package/dist/runtime/composables/removeObject.mjs +15 -0
- package/dist/runtime/composables/t.d.ts +1 -0
- package/dist/runtime/composables/t.mjs +8 -0
- package/dist/runtime/composables/updateObject.d.ts +2 -0
- package/dist/runtime/composables/updateObject.mjs +10 -0
- package/dist/runtime/composables/useLight.d.ts +7 -0
- package/dist/runtime/composables/useLight.mjs +17 -0
- package/dist/runtime/composables/viewAs.d.ts +1 -0
- package/dist/runtime/composables/viewAs.mjs +15 -0
- package/dist/runtime/locales/en.json +14 -0
- package/dist/runtime/locales/zh-hk.json +140 -0
- package/dist/runtime/pages/EventLog/_eventlog_id/view.vue +21 -0
- package/dist/runtime/pages/EventLog/index.vue +56 -0
- package/dist/runtime/pages/FileManager/index.vue +5 -0
- package/dist/runtime/pages/MailLog/index.vue +48 -0
- package/dist/runtime/pages/Permission/add.vue +47 -0
- package/dist/runtime/pages/Permission/all.vue +85 -0
- package/dist/runtime/pages/Permission/index.vue +26 -0
- package/dist/runtime/pages/Role/add.vue +28 -0
- package/dist/runtime/pages/Role/index.vue +51 -0
- package/dist/runtime/pages/System/database/backup.vue +5 -0
- package/dist/runtime/pages/System/database/table.vue +19 -0
- package/dist/runtime/pages/System/index.vue +8 -0
- package/dist/runtime/pages/System/mailtest.vue +22 -0
- package/dist/runtime/pages/System/package.vue +8 -0
- package/dist/runtime/pages/System/phpinfo.vue +8 -0
- package/dist/runtime/pages/System/setting.vue +68 -0
- package/dist/runtime/pages/System/view_as.vue +56 -0
- package/dist/runtime/pages/User/_user_id/change-password.vue +49 -0
- package/dist/runtime/pages/User/_user_id/edit.vue +49 -0
- package/dist/runtime/pages/User/_user_id/view.vue +21 -0
- package/dist/runtime/pages/User/add.vue +64 -0
- package/dist/runtime/pages/User/index.vue +47 -0
- package/dist/runtime/pages/User/profile.vue +25 -0
- package/dist/runtime/pages/User/update-password.vue +45 -0
- package/dist/runtime/pages/UserLog/index.vue +53 -0
- package/dist/runtime/pages/index.vue +9 -0
- package/dist/runtime/pages/logout.vue +10 -0
- package/dist/runtime/plugin.d.ts +4 -0
- package/dist/runtime/plugin.mjs +58 -0
- package/dist/runtime/routes.d.ts +7 -0
- package/dist/runtime/routes.mjs +261 -0
- package/dist/runtime/system_menus.d.ts +10 -0
- package/dist/runtime/system_menus.mjs +37 -0
- package/dist/types.d.ts +15 -0
- package/package.json +57 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
const obj = reactive({})
|
|
3
|
+
|
|
4
|
+
const onSave = async () => {
|
|
5
|
+
if (await m("mailTest", obj)) {
|
|
6
|
+
que.notify({
|
|
7
|
+
message: "Mail sent",
|
|
8
|
+
color: "positive",
|
|
9
|
+
icon: "email"
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
</script>
|
|
14
|
+
<template>
|
|
15
|
+
<l-page>
|
|
16
|
+
<l-form @save="onSave">
|
|
17
|
+
<l-input label="Email" v-model="obj.email" required></l-input>
|
|
18
|
+
<l-input label="Subject" v-model="obj.subject" required></l-input>
|
|
19
|
+
<l-input type="textarea" label="Content" v-model="obj.content" required></l-input>
|
|
20
|
+
</l-form>
|
|
21
|
+
</l-page>
|
|
22
|
+
</template>
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
const router = useRouter()
|
|
3
|
+
const que = useQuasar()
|
|
4
|
+
|
|
5
|
+
const app = await q("app", [f("config", ["name", "value"])])
|
|
6
|
+
|
|
7
|
+
//const system = await q("system", ["passwordPolicy"])
|
|
8
|
+
|
|
9
|
+
const obj = reactive(app.config.reduce((acc, cur) => {
|
|
10
|
+
acc[cur.name] = cur.value
|
|
11
|
+
return acc
|
|
12
|
+
}, {}));
|
|
13
|
+
|
|
14
|
+
const fields = ["company", "company_logo", "password_upper_case", "password_lower_case", "password_number", "password_special_character",
|
|
15
|
+
"file_manager_show"];
|
|
16
|
+
|
|
17
|
+
//filter out fields that are not in the app.config table
|
|
18
|
+
Object.keys(obj).forEach((key) => {
|
|
19
|
+
if (!fields.includes(key)) {
|
|
20
|
+
delete obj[key]
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const onSave = async () => {
|
|
25
|
+
const data = Object.keys(obj).map((key) => {
|
|
26
|
+
return {
|
|
27
|
+
name: key,
|
|
28
|
+
value: obj[key]
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
for (let i = 0; i < data.length; i++) {
|
|
33
|
+
await m("updateAppConfig", data[i])
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
//show success
|
|
38
|
+
que.notify({
|
|
39
|
+
message: "Saved",
|
|
40
|
+
type: "positive",
|
|
41
|
+
position: "top",
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
</script>
|
|
49
|
+
<template>
|
|
50
|
+
<l-page>
|
|
51
|
+
|
|
52
|
+
<l-form @save="onSave">
|
|
53
|
+
<l-input label="Company" v-model="obj.company"></l-input>
|
|
54
|
+
<l-input label="Company logo" v-model="obj.company_logo"></l-input>
|
|
55
|
+
|
|
56
|
+
<q-field label="Password policy" stack-label>
|
|
57
|
+
<q-checkbox label="Upper case" v-model="obj.password_upper_case" true-value="1"
|
|
58
|
+
false-value="0"></q-checkbox>
|
|
59
|
+
<q-checkbox label="Lower case" v-model="obj.password_lower_case" true-value="1"
|
|
60
|
+
false-value="0"></q-checkbox>
|
|
61
|
+
<q-checkbox label="Number" v-model="obj.password_number" true-value="1" false-value="0"></q-checkbox>
|
|
62
|
+
<q-checkbox label="Special character" v-model="obj.password_special_character" true-value="1"
|
|
63
|
+
false-value="0"></q-checkbox>
|
|
64
|
+
</q-field>
|
|
65
|
+
|
|
66
|
+
</l-form>
|
|
67
|
+
</l-page>
|
|
68
|
+
</template>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
let users = await list("User", {
|
|
3
|
+
fields: [
|
|
4
|
+
"user_id", "username", "name", "roles"
|
|
5
|
+
]
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
let columns = [
|
|
9
|
+
{
|
|
10
|
+
label: "Username",
|
|
11
|
+
name: "username",
|
|
12
|
+
field: "username",
|
|
13
|
+
align: "left",
|
|
14
|
+
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: "name",
|
|
18
|
+
label: "姓名",
|
|
19
|
+
field: "name",
|
|
20
|
+
align: "left",
|
|
21
|
+
}, {
|
|
22
|
+
name: "roles",
|
|
23
|
+
label: "Roles",
|
|
24
|
+
align: "left",
|
|
25
|
+
field: r => r.roles.join(",")
|
|
26
|
+
}, {
|
|
27
|
+
name: "view",
|
|
28
|
+
label: "View",
|
|
29
|
+
align: "left"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
const router = useRouter();
|
|
34
|
+
const onCickView = async (id) => {
|
|
35
|
+
|
|
36
|
+
if (await viewAs(id)) {
|
|
37
|
+
router.back();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
}
|
|
41
|
+
</script>
|
|
42
|
+
<template>
|
|
43
|
+
<l-page>
|
|
44
|
+
<q-table flat :columns="columns" :rows="users">
|
|
45
|
+
<template #body-cell-view="props">
|
|
46
|
+
<q-td :props="props">
|
|
47
|
+
<q-btn rounded outline color="primary" @click="onCickView(props.row.user_id)">view</q-btn>
|
|
48
|
+
</q-td>
|
|
49
|
+
|
|
50
|
+
</template>
|
|
51
|
+
|
|
52
|
+
</q-table>
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
</l-page>
|
|
56
|
+
</template>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
const system = await q("system", ["passwordPolicy"]);
|
|
3
|
+
const rules = system.passwordPolicy.map((rule) => {
|
|
4
|
+
let s = rule.split(":");
|
|
5
|
+
|
|
6
|
+
switch (s[0]) {
|
|
7
|
+
case "required":
|
|
8
|
+
return (v) => !!v || "Required";
|
|
9
|
+
break;
|
|
10
|
+
case "containUpper":
|
|
11
|
+
return (v) => /[A-Z]/.test(v) || "Must contain at least one uppercase letter";
|
|
12
|
+
break;
|
|
13
|
+
case "containLower":
|
|
14
|
+
return (v) => /[a-z]/.test(v) || "Must contain at least one lowercase letter";
|
|
15
|
+
break;
|
|
16
|
+
case "containNumber":
|
|
17
|
+
return (v) => /[0-9]/.test(v) || "Must contain at least one number";
|
|
18
|
+
break;
|
|
19
|
+
case "containSpecial":
|
|
20
|
+
return (v) => /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(v) || "Must contain at least one special character";
|
|
21
|
+
break;
|
|
22
|
+
case "minLength":
|
|
23
|
+
return (v) => v.length >= parseInt(s[1]) || `Must be at least ${s[1]} characters`;
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
const router = useRouter();
|
|
28
|
+
const route = useRoute();
|
|
29
|
+
const obj = reactive({
|
|
30
|
+
id: parseInt(route.params.user_id)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
const onUpdatePassword = async () => {
|
|
35
|
+
if (await m("changeUserPassword", obj)) {
|
|
36
|
+
router.push("/User");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
</script>
|
|
41
|
+
<template>
|
|
42
|
+
<l-page>
|
|
43
|
+
<l-form @save="onUpdatePassword">
|
|
44
|
+
<l-input type="password" label="New password" :rules="rules" v-model="obj.password">
|
|
45
|
+
</l-input>
|
|
46
|
+
</l-form>
|
|
47
|
+
|
|
48
|
+
</l-page>
|
|
49
|
+
</template>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
const obj = reactive(await getObject(["first_name", "last_name", "email", "phone",
|
|
3
|
+
"addr1", "addr2", "addr3", "join_date", "expiry_date", "status", "language", "default_page"
|
|
4
|
+
]))
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<template>
|
|
8
|
+
<l-page>
|
|
9
|
+
<l-form v-model="obj">
|
|
10
|
+
<l-row>
|
|
11
|
+
<l-col md="6">
|
|
12
|
+
<l-input label="First name" v-model="obj.first_name" required />
|
|
13
|
+
<l-input label="Last name" v-model="obj.last_name" />
|
|
14
|
+
<l-input label="Email" v-model="obj.email" required />
|
|
15
|
+
</l-col>
|
|
16
|
+
<l-col md="6">
|
|
17
|
+
<l-input label="Phone" v-model="obj.phone" />
|
|
18
|
+
<l-input label="Address1" v-model="obj.addr1" />
|
|
19
|
+
<l-input label="Address2" v-model="obj.addr2" />
|
|
20
|
+
<l-input label="Address3" v-model="obj.addr3" />
|
|
21
|
+
</l-col>
|
|
22
|
+
<l-col>
|
|
23
|
+
<l-date-picker label="Join date" v-model="obj.join_date" required />
|
|
24
|
+
<l-date-picker label="Expiry date" v-model="obj.expiry_date" />
|
|
25
|
+
|
|
26
|
+
<l-select label="Status" :options="[{ value: 0, label: 'Active' }, { value: 1, label: 'Inactive' }]"
|
|
27
|
+
v-model="obj.status" required></l-select>
|
|
28
|
+
|
|
29
|
+
<l-select label="Language" :options="[{
|
|
30
|
+
label: 'English',
|
|
31
|
+
value: 'en'
|
|
32
|
+
}, {
|
|
33
|
+
label: '中文',
|
|
34
|
+
value: 'zh-hk'
|
|
35
|
+
}]" v-model="obj.language" emit-value map-options required></l-select>
|
|
36
|
+
|
|
37
|
+
<l-input label="Default page" v-model="obj.default_page"></l-input>
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
</l-col>
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
</l-row>
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
</l-form>
|
|
48
|
+
</l-page>
|
|
49
|
+
</template>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
const obj = await getObject(["username", "first_name", "last_name", "email", "phone"]);
|
|
3
|
+
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<template>
|
|
7
|
+
<l-page>
|
|
8
|
+
<template #header>
|
|
9
|
+
<l-btn to="change-password" icon="sym_o_key" permission="user.changePassword">Change password</l-btn>
|
|
10
|
+
</template>
|
|
11
|
+
<l-card>
|
|
12
|
+
<l-list>
|
|
13
|
+
<l-item label="Username">{{ obj.username }}</l-item>
|
|
14
|
+
<l-item label="First name">{{ obj.first_name }}</l-item>
|
|
15
|
+
<l-item label="Last name">{{ obj.last_name }}</l-item>
|
|
16
|
+
<l-item label="Email">{{ obj.email }}</l-item>
|
|
17
|
+
<l-item label="Phone">{{ obj.phone }}</l-item>
|
|
18
|
+
</l-list>
|
|
19
|
+
</l-card>
|
|
20
|
+
</l-page>
|
|
21
|
+
</template>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
const obj = reactive({
|
|
3
|
+
roles: ['Users'],
|
|
4
|
+
status: 'Active',
|
|
5
|
+
language: "en"
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
let roles = await q("listRole", ["name"]);
|
|
9
|
+
roles = roles.map((role) => {
|
|
10
|
+
return {
|
|
11
|
+
label: role.name,
|
|
12
|
+
value: role.name,
|
|
13
|
+
};
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
</script>
|
|
17
|
+
<template>
|
|
18
|
+
<l-page>
|
|
19
|
+
<l-form v-model="obj">
|
|
20
|
+
<l-row>
|
|
21
|
+
<l-col md="6">
|
|
22
|
+
<l-input label="Username" v-model="obj.username" required />
|
|
23
|
+
<l-input label="Password" v-model="obj.password" required type="password" />
|
|
24
|
+
<l-input label="First name" v-model="obj.first_name" required />
|
|
25
|
+
<l-input label="Last name" v-model="obj.last_name" />
|
|
26
|
+
<l-input label="Email" v-model="obj.email" required />
|
|
27
|
+
|
|
28
|
+
</l-col>
|
|
29
|
+
<l-col md="6">
|
|
30
|
+
<l-input label="Phone" v-model="obj.phone" />
|
|
31
|
+
<l-input label="Address1" v-model="obj.addr1" />
|
|
32
|
+
<l-input label="Address2" v-model="obj.addr2" />
|
|
33
|
+
<l-input label="Address3" v-model="obj.addr3" />
|
|
34
|
+
</l-col>
|
|
35
|
+
<l-col>
|
|
36
|
+
<l-date-picker label="Join date" v-model="obj.join_date" required />
|
|
37
|
+
<l-date-picker label="Expiry date" v-model="obj.expiry_date" />
|
|
38
|
+
|
|
39
|
+
<l-select label="Status" :options="['Active', 'Inactve']" v-model="obj.status"></l-select>
|
|
40
|
+
<l-select label="Language" :options="[{
|
|
41
|
+
label: 'English',
|
|
42
|
+
value: 'en'
|
|
43
|
+
}, {
|
|
44
|
+
label: '中文',
|
|
45
|
+
value: 'zh-hk'
|
|
46
|
+
}]" v-model="obj.language" emit-value map-options></l-select>
|
|
47
|
+
|
|
48
|
+
<l-input label="Default page" v-model="obj.default_page"></l-input>
|
|
49
|
+
|
|
50
|
+
<q-field label="Roles" stack-label>
|
|
51
|
+
<q-option-group type="checkbox" :options="roles" v-model="obj.roles" inline>
|
|
52
|
+
</q-option-group>
|
|
53
|
+
</q-field>
|
|
54
|
+
|
|
55
|
+
</l-col>
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
</l-row>
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
</l-form>
|
|
63
|
+
</l-page>
|
|
64
|
+
</template>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
const onRequest = async (params) => {
|
|
5
|
+
listData("User", params, ["canDelete", "canUpdate", "canRead", "user_id"]);
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const columns = [
|
|
9
|
+
{
|
|
10
|
+
label: "Username",
|
|
11
|
+
name: "username",
|
|
12
|
+
sortable: true,
|
|
13
|
+
searchable: true,
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
label: "First name",
|
|
17
|
+
name: "first_name",
|
|
18
|
+
sortable: true,
|
|
19
|
+
searchable: true,
|
|
20
|
+
}, {
|
|
21
|
+
|
|
22
|
+
label: "Last name",
|
|
23
|
+
name: "last_name",
|
|
24
|
+
sortable: true,
|
|
25
|
+
searchable: true,
|
|
26
|
+
}, {
|
|
27
|
+
label: "Email",
|
|
28
|
+
name: "email",
|
|
29
|
+
sortable: true,
|
|
30
|
+
searchable: true,
|
|
31
|
+
}, {
|
|
32
|
+
label: "Phone",
|
|
33
|
+
name: "phone",
|
|
34
|
+
sortable: true,
|
|
35
|
+
searchable: true,
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<template>
|
|
42
|
+
<l-page>
|
|
43
|
+
<l-table @request="onRequest" :columns="columns" :show-actions="['view', 'edit', 'delete']">
|
|
44
|
+
</l-table>
|
|
45
|
+
|
|
46
|
+
</l-page>
|
|
47
|
+
</template>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
const my = await q("my", ["username", "first_name", "last_name", "email", "phone", "roles", "addr1", "addr2", "addr3", "join_date"])
|
|
3
|
+
|
|
4
|
+
</script>
|
|
5
|
+
<template>
|
|
6
|
+
<l-page title="User profile">
|
|
7
|
+
<template #header>
|
|
8
|
+
<q-btn rounded icon="sym_o_key" to="update-password" outline color="primary">Update password</q-btn>
|
|
9
|
+
</template>
|
|
10
|
+
<l-card>
|
|
11
|
+
<l-list>
|
|
12
|
+
<l-item label="Username">{{ my.username }}</l-item>
|
|
13
|
+
<l-item label="First name">{{ my.first_name }}</l-item>
|
|
14
|
+
<l-item label="Last name">{{ my.last_name }}</l-item>
|
|
15
|
+
<l-item label="Email">{{ my.email }}</l-item>
|
|
16
|
+
<l-item label="Phone">{{ my.phone }}</l-item>
|
|
17
|
+
<l-item label="Address">{{ my.addr1 }} {{ my.addr2 }} {{ my.addr3 }}</l-item>
|
|
18
|
+
<l-item label="Join date">{{ my.join_date }}</l-item>
|
|
19
|
+
<l-item label="Roles">{{ my.roles.join(",") }}</l-item>
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
</l-list>
|
|
23
|
+
</l-card>
|
|
24
|
+
</l-page>
|
|
25
|
+
</template>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
|
|
3
|
+
const obj = reactive({
|
|
4
|
+
old_password: "",
|
|
5
|
+
new_password: "",
|
|
6
|
+
confirm_password: ""
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
const qua = useQuasar();
|
|
10
|
+
const router = useRouter();
|
|
11
|
+
|
|
12
|
+
const onSave = async () => {
|
|
13
|
+
if (await m("updatePassword", {
|
|
14
|
+
old_password: obj.old_password,
|
|
15
|
+
new_password: obj.new_password,
|
|
16
|
+
})) {
|
|
17
|
+
//back
|
|
18
|
+
router.back();
|
|
19
|
+
} else {
|
|
20
|
+
//show error
|
|
21
|
+
qua.notify({
|
|
22
|
+
message: "Invalid old password",
|
|
23
|
+
color: "negative",
|
|
24
|
+
icon: "sym_o_error",
|
|
25
|
+
position: "top",
|
|
26
|
+
timeout: 2000
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
</script>
|
|
32
|
+
<template>
|
|
33
|
+
<l-page>
|
|
34
|
+
<l-form @save="onSave">
|
|
35
|
+
<l-input label="Old password" v-model="obj.old_password" type="password"
|
|
36
|
+
:rules="[v => !!v || 'Old password is required']" />
|
|
37
|
+
<l-input label="New password" v-model="obj.new_password" type="password"
|
|
38
|
+
:rules="[v => !!v || 'New password is required']" />
|
|
39
|
+
<l-input label="Confirm password" v-model="obj.confirm_password" type="password" :rules="[
|
|
40
|
+
v => !!v || 'Confirm password is required',
|
|
41
|
+
v => v == obj.new_password || 'Confirm password does not match'
|
|
42
|
+
]" />
|
|
43
|
+
</l-form>
|
|
44
|
+
</l-page>
|
|
45
|
+
</template>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
const onRequest = async (params) => {
|
|
3
|
+
listData("UserLog", params);
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
const columns = [
|
|
7
|
+
{
|
|
8
|
+
label: "ID",
|
|
9
|
+
name: "userlog_id",
|
|
10
|
+
sortable: true,
|
|
11
|
+
searchable: true,
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
label: "User",
|
|
15
|
+
name: "username"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
label: "Login time",
|
|
19
|
+
name: "login_dt",
|
|
20
|
+
sortable: true,
|
|
21
|
+
searchable: true,
|
|
22
|
+
}, {
|
|
23
|
+
label: "Login out",
|
|
24
|
+
name: "logout_dt",
|
|
25
|
+
sortable: true,
|
|
26
|
+
searchable: true,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
label: "Result",
|
|
30
|
+
name: "result",
|
|
31
|
+
sortable: true,
|
|
32
|
+
searchable: true,
|
|
33
|
+
}, {
|
|
34
|
+
label: "User agent",
|
|
35
|
+
name: "user_agent",
|
|
36
|
+
sortable: true,
|
|
37
|
+
searchable: true,
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<template>
|
|
49
|
+
<l-page>
|
|
50
|
+
<l-table @request="onRequest" :columns="columns" sort-by="login_dt:desc">
|
|
51
|
+
</l-table>
|
|
52
|
+
</l-page>
|
|
53
|
+
</template>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Quasar, Dialog, Notify, Loading } from "quasar";
|
|
2
|
+
import ElementPlus from "element-plus";
|
|
3
|
+
import { createI18n } from "vue-i18n";
|
|
4
|
+
import { defineNuxtPlugin } from "#app";
|
|
5
|
+
import "./assets/main.css";
|
|
6
|
+
import "./assets/element.css";
|
|
7
|
+
import zhTW from "element-plus/es/locale/lang/zh-tw";
|
|
8
|
+
import en from "element-plus/es/locale/lang/en";
|
|
9
|
+
import message_en from "./locales/en.json";
|
|
10
|
+
import message_zh from "./locales/zh-hk.json";
|
|
11
|
+
import routes from "./routes.mjs";
|
|
12
|
+
localStorage.getItem("locale") || localStorage.setItem("locale", "en");
|
|
13
|
+
import { useLight } from "./composables/useLight.mjs";
|
|
14
|
+
export default defineNuxtPlugin((nuxtApp) => {
|
|
15
|
+
let locale = localStorage.getItem("locale") || "en";
|
|
16
|
+
nuxtApp.vueApp.config.errorHandler = (error) => {
|
|
17
|
+
console.log(error);
|
|
18
|
+
const light = useLight();
|
|
19
|
+
light.addError(error);
|
|
20
|
+
};
|
|
21
|
+
const i18n = createI18n({
|
|
22
|
+
legacy: false,
|
|
23
|
+
locale,
|
|
24
|
+
messages: {
|
|
25
|
+
en: Object.assign(en, message_en),
|
|
26
|
+
"zh-hk": Object.assign(zhTW, message_zh),
|
|
27
|
+
"zh-tw": Object.assign(zhTW, message_zh)
|
|
28
|
+
},
|
|
29
|
+
fallbackWarn: false,
|
|
30
|
+
missingWarn: false
|
|
31
|
+
});
|
|
32
|
+
nuxtApp.vueApp.use(i18n);
|
|
33
|
+
nuxtApp.vueApp.use(ElementPlus);
|
|
34
|
+
nuxtApp.vueApp.use(Quasar, {
|
|
35
|
+
config: {
|
|
36
|
+
brand: {
|
|
37
|
+
primary: "#7367f0",
|
|
38
|
+
secondary: "#82868b",
|
|
39
|
+
accent: "#9C27B0",
|
|
40
|
+
dark: "#4b4b4b",
|
|
41
|
+
darkPage: "#121212",
|
|
42
|
+
positive: "#28c76f",
|
|
43
|
+
negative: "#ea5455",
|
|
44
|
+
info: "#00cfe8",
|
|
45
|
+
warning: "#ff9f43"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
plugins: {
|
|
49
|
+
Dialog,
|
|
50
|
+
Notify,
|
|
51
|
+
Loading
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
const router = useRouter();
|
|
55
|
+
routes.forEach((route) => {
|
|
56
|
+
router.addRoute(route);
|
|
57
|
+
});
|
|
58
|
+
});
|