API รายการคำสั่งและ Template

This commit is contained in:
DESKTOP-1R2VSQH\Lenovo ThinkPad E490 2024-09-13 15:55:45 +07:00
parent 5625fa06f4
commit 1794218a8f
6 changed files with 391 additions and 260 deletions

View file

@ -1,6 +1,7 @@
import env from "../index"; import env from "../index";
const order = `${env.API_URI}/order`; const order = `${env.API_URI}/org`;
export default { export default {
commandType: `${order}/order-type`, commandType: `${order}/commandType`,
commandSysList: `${order}/commandSys/list`,
}; };

View file

@ -1,71 +1,73 @@
<script setup lang="ts"> <script setup lang="ts">
import { watch, ref } from "vue"; import { ref, onMounted } from "vue";
import { useQuasar } from "quasar"; import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin"; import { useCounterMixin } from "@/stores/mixin";
import { useDataStore } from "@/modules/05_command/stores/main"; import { useDataStore } from "@/modules/05_command/stores/main";
import type { DataTemplateDetail } from "@/modules/05_command/interface/response/Main";
const $q = useQuasar(); const $q = useQuasar();
const mixin = useCounterMixin(); const mixin = useCounterMixin();
const { const { dialogConfirm, success, showLoader, hideLoader, messageError } = mixin;
dialogConfirm,
success,
showLoader,
hideLoader,
dialogRemove,
messageError,
} = mixin;
const store = useDataStore(); const store = useDataStore();
const commandId = defineModel<string>("commandId", { required: true }); const commandId = defineModel<string>("commandId", { required: true });
const type = defineModel<string>("type", { required: true }); const type = defineModel<string>("type", { required: true });
const dataTemplateDetail = defineModel<DataTemplateDetail>(
"dataTemplateDetail",
{
required: true,
}
);
const { fetchDataTemplate } = defineProps({
fetchDataTemplate: {
type: Function,
required: true,
},
});
const textHeader = ref<string>(""); const textHeader = ref<string>("");
const textBody = ref<string>(""); const textBody = ref<string>("");
const textFooter = ref<string>(""); const textFooter = ref<string>("");
const fetchData = async () => { function fetchData(data: DataTemplateDetail) {
textHeader.value = ""; textHeader.value = data.detailHeader;
textBody.value = ""; textBody.value = data.detailBody;
textFooter.value = ""; textFooter.value = data.detailFooter;
};
const onSave = () => {
console.log("textHeader===>", textHeader.value);
console.log("textBody===>", textBody.value);
console.log("textFooter===>", textFooter.value);
};
function clearFormat(type: string) {
switch (type) {
case "textHeader":
textHeader.value = textHeader.value.replace(/<\/?[^>]+(>|$)/g, "");
break;
case "textBody":
textBody.value = textBody.value.replace(/<\/?[^>]+(>|$)/g, "");
break;
case "textFooter":
textFooter.value = textFooter.value.replace(/<\/?[^>]+(>|$)/g, "");
break;
default:
break;
}
} }
const handleInput = (event: any, type: string) => { const onSave = () => {
if (event.inputType === "insertFromPaste") { dialogConfirm($q, () => {
clearFormat(type); showLoader();
} http
.put(config.API.commandType + `/text/${commandId.value}`, {
detailHeader: textHeader.value,
detailBody: textBody.value,
detailFooter: textFooter.value,
})
.then(async () => {
await fetchDataTemplate(commandId.value);
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
});
}; };
watch( onMounted(() => {
() => commandId.value, fetchData(dataTemplateDetail.value);
(newValue, oldValue) => { });
if (newValue && newValue !== oldValue) {
fetchData(); defineExpose({
} fetchData,
} });
);
</script> </script>
<template> <template>
@ -83,24 +85,6 @@ watch(
v-model="textHeader" v-model="textHeader"
label="เนื้อหาคำสั่งส่วนต้น" label="เนื้อหาคำสั่งส่วนต้น"
/> />
<!-- <q-label>เนอหาคำสงสวนต</q-label>
<q-field
class="q_field_p_none"
ref="fieldRef"
v-model="textHeader"
borderless
hide-bottom-space
>
<template #control>
<q-editor
class="full-width"
v-model="textHeader"
min-height="5rem"
:toolbar="store.toolbarOptions"
@input="(e:any) => handleInput(e, 'textHeader')"
/>
</template>
</q-field> -->
</div> </div>
<div class="col-12"> <div class="col-12">
@ -114,25 +98,6 @@ watch(
v-model="textBody" v-model="textBody"
label="เนื้อหาคำสั่งส่วนกลาง" label="เนื้อหาคำสั่งส่วนกลาง"
/> />
<!-- <q-label>เนอหาคำสงสวนกลาง</q-label>
<q-field
class="q_field_p_none"
ref="fieldRef"
v-model="textBody"
borderless
hide-bottom-space
>
<template #control>
<q-editor
class="full-width"
v-model="textBody"
min-height="5rem"
:toolbar="store.toolbarOptions"
@input="(e:any) => handleInput(e, 'textBody')"
/>
</template>
</q-field> -->
</div> </div>
<div class="col-12"> <div class="col-12">
@ -146,24 +111,6 @@ watch(
v-model="textFooter" v-model="textFooter"
label="เนื้อหาคำสั่งส่วนท้าย" label="เนื้อหาคำสั่งส่วนท้าย"
/> />
<!-- <q-label>เนอหาคำสงสวนทาย</q-label>
<q-field
class="q_field_p_none"
ref="fieldRef"
v-model="textFooter"
borderless
hide-bottom-space
>
<template #control>
<q-editor
class="full-width"
v-model="textFooter"
min-height="5rem"
:toolbar="store.toolbarOptions"
@input="(e:any) => handleInput(e, 'textFooter')"
/>
</template>
</q-field> -->
</div> </div>
</div> </div>
</q-card-section> </q-card-section>

View file

@ -1,14 +1,16 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, watch } from "vue"; import { onMounted, ref, watch } from "vue";
import { VuePDF, usePDF } from "@tato30/vue-pdf"; import { VuePDF, usePDF } from "@tato30/vue-pdf";
import { useQuasar } from "quasar"; import { useQuasar } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import config from "@/app.config"; import config from "@/app.config";
import axios from "axios"; import axios from "axios";
import { useCounterMixin } from "@/stores/mixin";
import genReport from "@/plugins/genreport"; import genReport from "@/plugins/genreport";
import type { DataTemplateDetail } from "@/modules/05_command/interface/response/Main";
const $q = useQuasar(); const $q = useQuasar();
const mixin = useCounterMixin(); const mixin = useCounterMixin();
const { const {
@ -22,31 +24,38 @@ const {
const idOrder = defineModel<string>("idOrder", { required: true }); // tab const idOrder = defineModel<string>("idOrder", { required: true }); // tab
const type = defineModel<string>("type", { required: true }); // tab const type = defineModel<string>("type", { required: true }); // tab
const dataTemplateDetail = defineModel<DataTemplateDetail>(
"dataTemplateDetail",
{
required: true,
}
);
const documentFile = ref<File | null>(null); // file const documentFile = ref<File | null>(null); // file
const isLoadPDF = ref<boolean>(false);
/** download file */ /** download file */
async function downloadFile() { async function downloadFile() {
showLoader(); showLoader();
const data = await { const body = {
template: "command_test", template: "command_test",
reportName: "docx-report", reportName: "docx-report",
data: { data: {
title: "สำนักงานเขตพระนคร", issue: ".....", //
commandNo: "๑๒", title: "....", //
commandYear: "๒๕๖๗", commandNo: "....",
commandTitle: "ย้ายข้าราชการ", commandYear: ".....",
detailHeader: "", commandTitle: dataTemplateDetail.value.name, //name
detailBody: detailHeader: dataTemplateDetail.value.detailHeader,
"อาศัยอำนาจตามความในมาตรา ๔๔ และมาตรา ๕๒ (๔) แห่งพระราชบัญญัติระเบียบข้าราชการ-กรุงเทพมหานครและบุคลากรกรุงเทพมหานคร พ.ศ. ๒๕๕๔ ประกอบกับมาตรา ๖๒ และมาตรา ๖๓ แห่งพระราชบัญญัติระเบียบข้าราชการพลเรือน พ.ศ. ๒๕๕๑ มาตรา ๑๔ แห่งพระราชกฤษฎีกาการจ่าย-เงินเดือน เงินปี บำเหน็จ บำนาญ และเงินอื่นในลักษณะเดียวกัน พ.ศ. ๒๕๓๕ มติ ก.ก. ครั้งที่ ๕/๒๕๕๔", detailBody: dataTemplateDetail.value.detailBody,
detailFooter: detailFooter: dataTemplateDetail.value.detailFooter,
"เมื่อวันที่ ๒๑ กรกฎาคม ๒๕๕๔ และมติ ก.ก. ครั้งที่ ๖/๒๕๕๔ เมื่อวันที่ ๑๘ สิงหาคม ๒๕๕๔ ให้ย้ายข้าราชการ จำนวน ๑ ราย ดังบัญชีรายละเอียดแนบท้ายนี้",
commandDate: "๑ สิงหาคม ๒๕๖๗", commandDate: "๑ สิงหาคม ๒๕๖๗",
name: "นายสมชาย ใจดี", name: "นายสมชาย ใจดี",
position: "ผู้อำนวยการเขตพระนคร", position: "ผู้อำนวยการเขตพระนคร",
}, },
}; };
await genReport(data, `คำสั่ง`);
await genReport(body, `คำสั่ง`);
} }
/** uplaod file */ /** uplaod file */
@ -71,25 +80,20 @@ function backPage() {
} }
} }
function replaceAllTag(html: string) { async function fetchDocumentTemplate(dataTemple: DataTemplateDetail) {
return html.replace("div", "p");
}
async function fetchDocumentTemplate() {
showLoader(); showLoader();
const data = await { const body = {
template: "command_test", template: "command_test",
reportName: "docx-report", reportName: "docx-report",
data: { data: {
title: "สำนักงานเขตพระนคร", issue: ".....", //
commandNo: "๑๒", title: "....", //
commandYear: "๒๕๖๗", commandNo: "....",
commandTitle: "ย้ายข้าราชการ", commandYear: ".....",
detailHeader: "", commandTitle: dataTemple.name, //name
detailBody: detailHeader: dataTemple.detailHeader,
"อาศัยอำนาจตามความในมาตรา ๔๔ และมาตรา ๕๒ (๔) แห่งพระราชบัญญัติระเบียบข้าราชการ-กรุงเทพมหานครและบุคลากรกรุงเทพมหานคร พ.ศ. ๒๕๕๔ ประกอบกับมาตรา ๖๒ และมาตรา ๖๓ แห่งพระราชบัญญัติระเบียบข้าราชการพลเรือน พ.ศ. ๒๕๕๑ มาตรา ๑๔ แห่งพระราชกฤษฎีกาการจ่าย-เงินเดือน เงินปี บำเหน็จ บำนาญ และเงินอื่นในลักษณะเดียวกัน พ.ศ. ๒๕๓๕ มติ ก.ก. ครั้งที่ ๕/๒๕๕๔", detailBody: dataTemple.detailBody,
detailFooter: detailFooter: dataTemple.detailFooter,
"เมื่อวันที่ ๒๑ กรกฎาคม ๒๕๕๔ และมติ ก.ก. ครั้งที่ ๖/๒๕๕๔ เมื่อวันที่ ๑๘ สิงหาคม ๒๕๕๔ ให้ย้ายข้าราชการ จำนวน ๑ ราย ดังบัญชีรายละเอียดแนบท้ายนี้",
commandDate: "๑ สิงหาคม ๒๕๖๗", commandDate: "๑ สิงหาคม ๒๕๖๗",
name: "นายสมชาย ใจดี", name: "นายสมชาย ใจดี",
position: "ผู้อำนวยการเขตพระนคร", position: "ผู้อำนวยการเขตพระนคร",
@ -97,7 +101,7 @@ async function fetchDocumentTemplate() {
}; };
await axios await axios
.post(config.API.reportTemplate + `/docx/html`, data, { .post(config.API.reportTemplate + `/docx/html`, body, {
headers: { headers: {
accept: "application/pdf", accept: "application/pdf",
"content-Type": "application/json", "content-Type": "application/json",
@ -105,32 +109,33 @@ async function fetchDocumentTemplate() {
responseType: "blob", responseType: "blob",
}) })
.then(async (res) => { .then(async (res) => {
isLoadPDF.value = false;
const blob = new Blob([res.data]); const blob = new Blob([res.data]);
const objectUrl = URL.createObjectURL(blob); const objectUrl = URL.createObjectURL(blob);
const pdfData = await usePDF(`${objectUrl}`); const pdfData = await usePDF(`${objectUrl}`);
showLoader();
setTimeout(() => { setTimeout(() => {
pdfSrc.value = pdfData.pdf.value; pdfSrc.value = pdfData.pdf.value;
numOfPages.value = pdfData.pages.value; numOfPages.value = pdfData.pages.value;
hideLoader(); isLoadPDF.value = true;
}, 1500); }, 1500);
}) })
.catch(async (e) => { .catch(async (e) => {
messageError($q, e); messageError($q, e);
})
.finally(() => {
hideLoader(); hideLoader();
}); });
} }
watch( onMounted(() => {
() => idOrder.value, fetchDocumentTemplate(dataTemplateDetail.value);
(newValue, oldValue) => { });
if (newValue && newValue !== oldValue) {
fetchDocumentTemplate(); defineExpose({
} fetchDocumentTemplate,
}, });
{ immediate: true }
);
</script> </script>
<template> <template>
@ -222,7 +227,31 @@ watch(
</template> </template>
<template v-slot:after> <template v-slot:after>
<div class="q-pa-md"> <div class="q-pa-md">
<VuePDF ref="vuePDFRef" :pdf="pdfSrc" :page="page" fit-parent /> <VuePDF
v-if="isLoadPDF"
ref="vuePDFRef"
:pdf="pdfSrc"
:page="page"
fit-parent
/>
<div
v-else
class="full-width row flex-center text-accent q-gutter-sm"
>
<span
><div
style="
height: 40vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
"
>
<q-spinner color="primary" size="3em" />
</div>
</span>
</div>
</div> </div>
</template> </template>
<template v-slot:default> <template v-slot:default>

View file

@ -16,8 +16,9 @@ interface ListOrder {
id: string; id: string;
commandCode: string; commandCode: string;
name: string; name: string;
status: boolean; isActive: boolean;
category?: string; category?: string;
commandSysId: string;
} }
interface ListTemplateSalary { interface ListTemplateSalary {

View file

@ -1 +1,22 @@
export type {}; interface DataCommandSys {
id: string;
createdAt: string;
lastUpdatedAt: string;
createdFullName: string;
lastUpdateFullName: string;
sysName: string;
sysDescription: string;
}
interface DataTemplateDetail {
id: string;
name: string;
code: string;
detailHeader: string;
detailBody: string;
detailFooter: string;
isActive: boolean;
commandSysId: string;
}
export type { DataCommandSys, DataTemplateDetail };

View file

@ -13,6 +13,10 @@ import type {
Tabs, Tabs,
DateOption, DateOption,
} from "@/modules/05_command/interface/index/Main"; } from "@/modules/05_command/interface/index/Main";
import type {
DataCommandSys,
DataTemplateDetail,
} from "@/modules/05_command/interface/response/Main";
import Header from "@/components/DialogHeader.vue"; import Header from "@/components/DialogHeader.vue";
import PageOrder from "@/modules/05_command/components/ViewPdf.vue"; import PageOrder from "@/modules/05_command/components/ViewPdf.vue";
@ -30,7 +34,12 @@ const {
messageError, messageError,
} = mixin; } = mixin;
const isActive = ref<string>(""); // const childTemplateDetailRef = ref<InstanceType<typeof TemplateDetail> | null>(
null
); //ref components
const childPageOrderRef = ref<InstanceType<typeof PageOrder> | null>(null); //ref components
const isActive = ref<boolean>(true); //
// options // options
const activeOptions = ref<ActiveOptions[]>([ const activeOptions = ref<ActiveOptions[]>([
{ {
@ -70,20 +79,73 @@ const listOrder = ref<ListOrder[]>([]); // list คำสั่ง
const status = ref<boolean>(false); // const status = ref<boolean>(false); //
const isEdit = ref<boolean>(false); // true/false const isEdit = ref<boolean>(false); // true/false
const dialogFormCommand = ref<boolean>(false); // model const dialogFormCommand = ref<boolean>(false); // model
const dataTemplateDetail = ref<DataTemplateDetail>();
const page = ref<number>(1); //
const pageSize = ref<number>(13); //
const maxPage = ref<number>(0); //
/**
* งกนดงรายการประเภทคำส
*/
async function fetchCommandType() {
showLoader();
await http
.get(config.API.commandType + `/admin`, {
params: {
page: page.value,
pageSize: pageSize.value,
isActive: isActive.value,
},
})
.then(async (res) => {
const data = res.data.result;
listOrder.value = data.commandTypes;
maxPage.value = Math.ceil(data.total / pageSize.value);
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/**
* งกนดงขอมลรายการหมวดหม
*/
function fetchCommandSys() {
showLoader();
http
.get(config.API.commandSysList)
.then((res) => {
const data = res.data.result;
const option = data.map((e: DataCommandSys) => ({
id: e.id,
name: e.sysName,
}));
dataCategory.value = option;
categoryOP.value = option;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/** /**
* งกนคนหาคำส ตามสถานะ * งกนคนหาคำส ตามสถานะ
* @param val สถานะ true/false * @param val สถานะ true/false
*/ */
function searchByStatus(val: string) { function searchByStatus() {
console.log(val); activeOrderId.value = "";
page.value = 1;
pageSize.value = 13;
fetchCommandType();
} }
/** เปิด dialog */
function onDialogAdd() {
isEdit.value = false;
dialogFormCommand.value = true;
}
/** /**
* เป dialog Edit * เป dialog Edit
* @param data อมลคำส * @param data อมลคำส
@ -91,8 +153,8 @@ function onDialogAdd() {
function onDialogEdit(data: ListOrder) { function onDialogEdit(data: ListOrder) {
idOrder.value = data.id; idOrder.value = data.id;
name.value = data.name; name.value = data.name;
status.value = data.status; status.value = data.isActive;
category.value = data.commandSysId;
isEdit.value = true; isEdit.value = true;
dialogFormCommand.value = true; dialogFormCommand.value = true;
} }
@ -103,52 +165,82 @@ function onDialogEdit(data: ListOrder) {
*/ */
function onDelete(id: string) { function onDelete(id: string) {
dialogRemove($q, () => { dialogRemove($q, () => {
// http showLoader();
// .delete(config.API.) http
// .then((res) => {}) .delete(config.API.commandType + `/${id}`)
// .catch((e) => { .then(async () => {
// messageError($q, e); await fetchCommandType();
// }) })
// .finally(() => {}); .catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}); });
} }
/** ปิด dialog */ /**
* dialog
*/
function closeDialog() { function closeDialog() {
idOrder.value = ""; idOrder.value = "";
isEdit.value = false; isEdit.value = false;
dialogFormCommand.value = false; dialogFormCommand.value = false;
name.value = ""; name.value = "";
status.value = false; status.value = false;
} category.value = "";
/** บันทึกข้อมูล dialog */
function onSubmit() {
dialogConfirm($q, () => {});
}
/** เก็บ id list คำสั่งที่เลือก เพื่อใช้ class */
function selectInbox(data: ListOrder) {
activeOrderId.value = data.id;
} }
/** /**
* งกนดงรายการประเภทคำส * นทกขอมลการแกไขคำส
*/ */
async function fetchOrderType() { function onSubmit() {
dialogConfirm($q, async () => {
showLoader();
await http
.put(config.API.commandType + `/${idOrder.value}`, {
name: name.value,
commandSysId: category.value,
isActive: status.value,
})
.then(async () => {
await fetchCommandType();
success($q, "บันทึกข้อมูลสำเร็จ");
closeDialog();
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
});
}
/**
* เก id list คำสงทเลอก เพอใช class
*/
function selectInbox(data: ListOrder) {
activeOrderId.value = data.id;
fetchDataCommandTypeId(data.id);
}
/**
* งกนดงขอมลรายละเอยดคำส
* @param id คำส
*/
async function fetchDataCommandTypeId(id: string) {
showLoader(); showLoader();
await http await http
.get(config.API.commandType) .get(config.API.commandType + `/${id}`)
.then(async (res) => { .then(async (res) => {
listOrder.value = res.data.result.map((item: any) => { const data = res.data.result;
return { dataTemplateDetail.value = data;
name: item.name, await Promise.all([
category: item.category, childTemplateDetailRef?.value?.fetchData(data),
commandCode: item.commandCode, childPageOrderRef?.value?.fetchDocumentTemplate(data),
id: item.id, ]);
status: true,
};
});
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
@ -167,14 +259,14 @@ function filterSelector(val: string, update: Function) {
update(() => { update(() => {
category.value = val ? "" : category.value; category.value = val ? "" : category.value;
categoryOP.value = dataCategory.value.filter( categoryOP.value = dataCategory.value.filter(
(v: any) => v.name.indexOf(val) > -1 (v: DateOption) => v.name.indexOf(val) > -1
); );
}); });
} }
/** เริ่มเมื่อโหลดหน้านี้*/ /** เริ่มเมื่อโหลดหน้านี้*/
onMounted(() => { onMounted(async () => {
fetchOrderType(); await Promise.all([fetchCommandType(), fetchCommandSys()]);
}); });
</script> </script>
@ -182,11 +274,12 @@ onMounted(() => {
<div class="toptitle text-dark col-12 row items-center"> <div class="toptitle text-dark col-12 row items-center">
รายการคำสงและ Template รายการคำสงและ Template
</div> </div>
<div class="row q-col-gutter-sm">
<div class="row q-col-gutter-sm" style="height: 85vh; display: flex">
<div class="col-4"> <div class="col-4">
<q-card bordered style="height: 100%"> <q-card bordered style="min-height: 100%">
<div class="row items-center q-pa-sm"> <div class="row items-center q-pa-sm">
<div class="col-2"> <!-- <div class="col-2">
<q-btn <q-btn
flat flat
dense dense
@ -197,7 +290,7 @@ onMounted(() => {
> >
<q-tooltip>เพมขอม</q-tooltip> <q-tooltip>เพมขอม</q-tooltip>
</q-btn> </q-btn>
</div> </div> -->
<q-space /> <q-space />
<div class="col-12 col-md-6"> <div class="col-12 col-md-6">
<q-select <q-select
@ -210,82 +303,114 @@ onMounted(() => {
option-label="label" option-label="label"
option-value="value" option-value="value"
emit-value emit-value
map-options
@update:model-value="searchByStatus" @update:model-value="searchByStatus"
></q-select> ></q-select>
</div> </div>
</div> </div>
<q-separator /> <q-separator />
<q-card-section class="q-pa-sm"> <q-card-section class="q-pa-sm">
<q-scroll-area style="height: 70vh" class="scrollStyle"> <q-list
<q-list v-for="(item, index) in listOrder"
v-for="(item, index) in listOrder" :key="item.id"
:key="item.id" class="q-pr-sm"
class="q-pr-sm" >
<q-item
clickable
v-ripple
:active="activeOrderId === item.id"
active-class="my-menu_link"
@click="selectInbox(item)"
> >
<q-item <q-item-section>
clickable <q-item-label>
v-ripple {{ item.name }}
:active="activeOrderId === item.id" </q-item-label>
active-class="my-menu_link" </q-item-section>
@click="selectInbox(item)" <q-item-section side center @click.stop>
> <q-icon
<q-item-section> name="mdi-dots-vertical"
<q-item-label> class="q-pa-none q-ml-xs"
{{ item.name }} color="grey-13"
</q-item-label> flat
</q-item-section> dense
<q-item-section side center @click.stop> >
<q-icon <q-menu transition-show="jump-down" transition-hide="jump-up">
name="mdi-dots-vertical" <q-list dense style="min-width: 160px">
class="q-pa-none q-ml-xs" <q-item
color="grey-13" clickable
flat v-close-popup
dense @click="onDialogEdit(item)"
> >
<q-menu <q-item-section
transition-show="jump-down" style="min-width: 0px"
transition-hide="jump-up" avatar
> class="q-py-sm"
<q-list dense style="min-width: 160px">
<q-item
clickable
v-close-popup
@click="onDialogEdit(item)"
> >
<q-item-section <q-icon color="edit" size="xs" name="mdi-pencil" />
style="min-width: 0px" </q-item-section>
avatar <q-item-section>แกไข</q-item-section>
class="q-py-sm" </q-item>
> <q-separator />
<q-icon color="edit" size="xs" name="mdi-pencil" /> <q-item
</q-item-section> clickable
<q-item-section>แกไข</q-item-section> v-close-popup
</q-item> @click="onDelete(item.id)"
<q-separator /> >
<q-item <q-item-section
clickable style="min-width: 0px"
v-close-popup avatar
@click="onDelete(item.id)" class="q-py-sm"
> >
<q-item-section <q-icon color="red" size="xs" name="mdi-delete" />
style="min-width: 0px" </q-item-section>
avatar <q-item-section>ลบ</q-item-section>
class="q-py-sm" </q-item>
>
<q-icon color="red" size="xs" name="mdi-delete" />
</q-item-section>
<q-item-section>ลบ</q-item-section>
</q-item>
<q-separator /> <q-separator />
</q-list> </q-menu </q-list> </q-menu
></q-icon> ></q-icon>
</q-item-section> </q-item-section>
</q-item> </q-item>
<q-separator v-if="listOrder.length !== index + 1" /> <q-separator v-if="listOrder.length !== index + 1" />
</q-list> </q-list>
</q-scroll-area> <div
class="full-width row flex-center text-accent q-gutter-sm"
v-if="listOrder.length === 0"
>
<span
><div
style="
height: 76vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
"
class="text-grey-5"
>
<q-icon name="search" size="4rem" />
<span>{{ "ไม่พบข้อมูล" }}</span>
</div>
</span>
</div>
</q-card-section> </q-card-section>
<q-separator />
<q-card-actions align="around" v-if="listOrder.length > 0">
<q-pagination
class="q-pa-sm"
v-model="page"
active-color="primary"
color="dark"
:max="maxPage"
size="sm"
boundary-links
direction-links
:max-pages="5"
@update:model-value="fetchCommandType"
></q-pagination>
</q-card-actions>
</q-card> </q-card>
</div> </div>
<div class="col-8"> <div class="col-8">
@ -313,20 +438,27 @@ onMounted(() => {
<q-tab-panels v-model="store.currentTab" animated> <q-tab-panels v-model="store.currentTab" animated>
<q-tab-panel name="order"> <q-tab-panel name="order">
<PageOrder <PageOrder
ref="childPageOrderRef"
v-model:type="store.currentTab" v-model:type="store.currentTab"
v-model:data-template-detail="dataTemplateDetail as DataTemplateDetail"
:id-order="activeOrderId" :id-order="activeOrderId"
/> />
</q-tab-panel> </q-tab-panel>
<q-tab-panel name="account"> <q-tab-panel name="account">
<PageOrder <PageOrder
ref="childPageOrderRef"
v-model:type="store.currentTab" v-model:type="store.currentTab"
v-model:data-template-detail="dataTemplateDetail as DataTemplateDetail"
:id-order="activeOrderId" :id-order="activeOrderId"
/> />
</q-tab-panel> </q-tab-panel>
<q-tab-panel name="template"> <q-tab-panel name="template">
<TemplateDetail <TemplateDetail
ref="childTemplateDetailRef"
v-model:type="store.currentTab" v-model:type="store.currentTab"
v-model:data-template-detail="dataTemplateDetail as DataTemplateDetail"
:command-id="activeOrderId" :command-id="activeOrderId"
:fetch-data-template="fetchDataCommandTypeId"
/> />
</q-tab-panel> </q-tab-panel>
</q-tab-panels> </q-tab-panels>