642 lines
19 KiB
Vue
642 lines
19 KiB
Vue
<script setup lang="ts">
|
|
import { ref, onMounted, watch, computed } from "vue";
|
|
import { useQuasar } from "quasar";
|
|
|
|
import http from "@/plugins/http";
|
|
import config from "@/app.config";
|
|
import { useCounterMixin } from "@/stores/mixin";
|
|
import { useDataStore } from "@/modules/05_command/stores/main";
|
|
|
|
import type {
|
|
ListOrder,
|
|
Tabs,
|
|
DateOption,
|
|
} 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 PageOrder from "@/modules/05_command/components/ViewPdf.vue";
|
|
import TemplateDetail from "@/modules/05_command/components/FormTemplate.vue";
|
|
|
|
const $q = useQuasar();
|
|
const mixin = useCounterMixin();
|
|
const store = useDataStore();
|
|
const { dialogConfirm, success, showLoader, hideLoader, messageError } = mixin;
|
|
|
|
const childTemplateDetailRef = ref<InstanceType<typeof TemplateDetail> | null>(
|
|
null
|
|
); //ref components ข้อความต้นแบบ
|
|
const childPageOrderRef = ref<InstanceType<typeof PageOrder> | null>(null); //ref components คำสั่ง
|
|
|
|
// Tabs
|
|
const tabs = ref<Tabs[]>([
|
|
{
|
|
value: "cover",
|
|
label: "คำสั่ง",
|
|
},
|
|
{
|
|
value: "attachment",
|
|
label: "บัญชีแนบท้าย",
|
|
},
|
|
{
|
|
value: "template",
|
|
label: "ข้อความต้นแบบ",
|
|
},
|
|
]);
|
|
|
|
/** เมื่อ แนบท้ายเป็น false ตัด tab attachment ออก */
|
|
const filteredTabs = computed(() =>
|
|
isAttachmentShow.value
|
|
? tabs.value
|
|
: tabs.value.filter((tab) => tab.value !== "attachment")
|
|
);
|
|
|
|
const isCode = ref<string>(""); // ตัวแปรเก็บ code
|
|
const isActive = ref<boolean>(true); // สถานะของรายการคำสั่ง
|
|
const isAttachment = ref<boolean>(true); // บัญชีแนบท้าย
|
|
const isSalary = ref<boolean>(true); // แก้ไขเงินเดือน
|
|
const isAttachmentShow = ref<boolean>(true); // บัญชีแนบท้าย show/off
|
|
const isUploadAttachment = ref<boolean>(false);
|
|
|
|
const dataCategory = ref<DateOption[]>([]); //ข้อมูล หมวดหมู่
|
|
const categoryOP = ref<DateOption[]>([]); // options หมวดหมู่
|
|
|
|
const commandId = ref<string>(""); // Id คำสั่ง
|
|
const activeCommandId = ref<string>(""); // Id คำสั่งที่เลือก
|
|
const name = ref<string>(""); // ชื่อคำสั่ง
|
|
const subtitle = ref<string>(""); // คำอธิบาย
|
|
const category = ref<string>(""); // หมวดหมู่
|
|
const listOrder = ref<ListOrder[]>([]); // list คำสั่ง
|
|
const status = ref<boolean>(false); // สถานะ
|
|
const isEdit = ref<boolean>(false); //เก็บ true/false เช็คแก้ไข
|
|
const dialogFormCommand = ref<boolean>(false); // model คำสั่ง
|
|
const dataTemplateDetail = ref<DataTemplateDetail>();
|
|
|
|
const keyword = ref<string>("");
|
|
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,
|
|
keyword: keyword.value,
|
|
},
|
|
})
|
|
.then(async (res) => {
|
|
const data = res.data.result;
|
|
listOrder.value = data.commandTypes;
|
|
maxPage.value = Math.ceil(data.total / pageSize.value);
|
|
|
|
if (activeCommandId.value) {
|
|
listOrder.value.find((e: ListOrder) => {
|
|
if (e.id === activeCommandId.value) {
|
|
selectInbox(e);
|
|
}
|
|
});
|
|
}
|
|
})
|
|
.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
|
|
*/
|
|
function searchByStatus() {
|
|
activeCommandId.value = "";
|
|
page.value = 1;
|
|
pageSize.value = 13;
|
|
fetchCommandType();
|
|
}
|
|
|
|
/**
|
|
* เปิด dialog Edit
|
|
* @param data ข้อมูลคำสั่ง
|
|
*/
|
|
function onDialogEdit(data: ListOrder) {
|
|
commandId.value = data.id;
|
|
name.value = data.name;
|
|
status.value = data.isActive;
|
|
category.value = data.commandSysId;
|
|
subtitle.value = data.subtitle ? data.subtitle : "";
|
|
isEdit.value = true;
|
|
isAttachment.value = data.isAttachment;
|
|
isUploadAttachment.value = data.isUploadAttachment;
|
|
dialogFormCommand.value = true;
|
|
}
|
|
|
|
/**
|
|
* ปิด dialog
|
|
*/
|
|
function closeDialog() {
|
|
commandId.value = "";
|
|
isEdit.value = false;
|
|
dialogFormCommand.value = false;
|
|
subtitle.value = "";
|
|
name.value = "";
|
|
status.value = false;
|
|
category.value = "";
|
|
}
|
|
|
|
/** บันทึกข้อมูลการแก้ไขคำสั่ง*/
|
|
function onSubmit() {
|
|
dialogConfirm($q, async () => {
|
|
showLoader();
|
|
await http
|
|
.put(config.API.commandType + `/${commandId.value}`, {
|
|
name: name.value,
|
|
subtitle: subtitle.value,
|
|
commandSysId: category.value,
|
|
isActive: status.value,
|
|
isAttachment: isAttachment.value,
|
|
isSalary: isSalary.value,
|
|
isUploadAttachment: isUploadAttachment.value,
|
|
})
|
|
.then(async () => {
|
|
await fetchCommandType();
|
|
success($q, "บันทึกข้อมูลสำเร็จ");
|
|
closeDialog();
|
|
})
|
|
.catch((err) => {
|
|
messageError($q, err);
|
|
})
|
|
.finally(() => {
|
|
hideLoader();
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* เก็บ id list คำสั่งที่เลือก เพื่อใช้ class
|
|
*/
|
|
function selectInbox(data: ListOrder) {
|
|
isCode.value = data.code;
|
|
if (data.code === "C-PM-47") {
|
|
isAttachmentShow.value = false;
|
|
activeCommandId.value = "";
|
|
return;
|
|
}
|
|
store.currentTab =
|
|
!data.isAttachment && store.currentTab == "attachment"
|
|
? "cover"
|
|
: store.currentTab;
|
|
isAttachmentShow.value = data.isAttachment;
|
|
activeCommandId.value = data.id;
|
|
fetchDataCommandTypeId(data.id);
|
|
}
|
|
|
|
/**
|
|
* ฟังก์ชันดึงข้อมูลรายละเอียดคำสั่ง
|
|
* @param id คำสั่ง
|
|
*/
|
|
async function fetchDataCommandTypeId(id: string) {
|
|
showLoader();
|
|
await http
|
|
.get(config.API.commandType + `/${id}`)
|
|
.then(async (res) => {
|
|
const data = await res.data.result;
|
|
dataTemplateDetail.value = data;
|
|
await Promise.all([childTemplateDetailRef?.value?.fetchData(data)]);
|
|
})
|
|
.catch((err) => {
|
|
messageError($q, err);
|
|
})
|
|
.finally(() => {
|
|
hideLoader();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* ฟังก์ชั่นค้นหาข้อมูลใน Select หมวดหมู่
|
|
* @param val คำค้นหา
|
|
* @param update ฟังก์ชั่นค้นหา
|
|
*/
|
|
function filterSelector(val: string, update: Function) {
|
|
update(() => {
|
|
categoryOP.value = dataCategory.value.filter(
|
|
(v: DateOption) => v.name.indexOf(val) > -1
|
|
);
|
|
});
|
|
}
|
|
|
|
/** เช็คการเปลี่ยนแปลงของค่า isActive*/
|
|
watch(
|
|
() => isActive.value,
|
|
() => {
|
|
searchByStatus();
|
|
}
|
|
);
|
|
|
|
/** เริ่มเมื่อโหลดหน้านี้*/
|
|
onMounted(async () => {
|
|
await Promise.all([fetchCommandType(), fetchCommandSys()]);
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<div class="toptitle text-dark col-12 row items-center">
|
|
รายการคำสั่งและต้นแบบ
|
|
</div>
|
|
|
|
<div class="row q-col-gutter-sm" style="height: 85vh; display: flex">
|
|
<div class="col-4">
|
|
<q-card bordered style="min-height: 100%">
|
|
<q-toolbar>
|
|
<q-input
|
|
borderless
|
|
dense
|
|
outlined
|
|
v-model="keyword"
|
|
placeholder="ค้นหา"
|
|
@keydown.enter.prevent="searchByStatus()"
|
|
>
|
|
<template v-slot:append>
|
|
<q-icon name="search" />
|
|
</template>
|
|
</q-input>
|
|
|
|
<q-space />
|
|
<div class="row items-center no-wrap">
|
|
<q-label :class="`${isActive ? `text-primary` : `text-orange`}`">{{
|
|
`${isActive ? `ใช้งาน` : `ไม่ใช้งาน`}`
|
|
}}</q-label>
|
|
<label :class="`q-ml-lg toggle-control`">
|
|
<input type="checkbox" v-model="isActive" />
|
|
<span class="control"></span>
|
|
</label>
|
|
</div>
|
|
</q-toolbar>
|
|
|
|
<q-separator />
|
|
<q-card-section class="q-pa-sm">
|
|
<q-list v-for="(item, index) in listOrder" bordered :key="item.id">
|
|
<q-item
|
|
clickable
|
|
v-ripple
|
|
:active="activeCommandId === item.id"
|
|
active-class="my-menu_link"
|
|
@click="selectInbox(item)"
|
|
>
|
|
<q-item-section>
|
|
<q-item-label>
|
|
{{ item.name }}
|
|
<q-item-label caption>{{
|
|
item.subtitle ? item.subtitle : ""
|
|
}}</q-item-label>
|
|
</q-item-label>
|
|
</q-item-section>
|
|
<q-item-section side center @click.stop>
|
|
<q-icon
|
|
name="edit"
|
|
class="q-pa-none q-ml-xs"
|
|
color="edit"
|
|
flat
|
|
dense
|
|
@click="onDialogEdit(item)"
|
|
/>
|
|
<q-tooltip>แก้ไขข้อมูล</q-tooltip>
|
|
</q-item-section>
|
|
</q-item>
|
|
</q-list>
|
|
<div
|
|
v-if="listOrder.length === 0"
|
|
class="full-width row flex-center text-accent q-gutter-sm"
|
|
>
|
|
<div class="text-grey-5">ไม่พบข้อมูล</div>
|
|
</div>
|
|
</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>
|
|
</div>
|
|
<div class="col-8">
|
|
<q-card bordered style="height: 100%">
|
|
<div v-if="activeCommandId !== ''">
|
|
<q-tabs
|
|
dense
|
|
v-model="store.currentTab"
|
|
align="left"
|
|
indicator-color="primary"
|
|
active-color="primary bg-teal-1"
|
|
inline-label
|
|
class="text-body2 text-grey-7"
|
|
>
|
|
<q-tab
|
|
v-for="tab in filteredTabs"
|
|
:key="tab.value"
|
|
v-on:click="store.currentTab = tab.value"
|
|
:label="tab.label"
|
|
:name="tab.value"
|
|
class="q-py-xs"
|
|
/>
|
|
</q-tabs>
|
|
<q-separator />
|
|
<q-tab-panels v-model="store.currentTab" animated>
|
|
<q-tab-panel name="cover">
|
|
<PageOrder
|
|
ref="childPageOrderRef"
|
|
v-model:type="store.currentTab"
|
|
v-model:data-template-detail="dataTemplateDetail as DataTemplateDetail"
|
|
:command-id="activeCommandId"
|
|
:fetch-data-template="fetchDataCommandTypeId"
|
|
/>
|
|
</q-tab-panel>
|
|
<q-tab-panel name="attachment">
|
|
<PageOrder
|
|
ref="childPageOrderRef"
|
|
v-model:type="store.currentTab"
|
|
v-model:data-template-detail="dataTemplateDetail as DataTemplateDetail"
|
|
:command-id="activeCommandId"
|
|
:fetch-data-template="fetchDataCommandTypeId"
|
|
/>
|
|
</q-tab-panel>
|
|
<q-tab-panel name="template">
|
|
<TemplateDetail
|
|
ref="childTemplateDetailRef"
|
|
v-model:type="store.currentTab"
|
|
v-model:data-template-detail="dataTemplateDetail as DataTemplateDetail"
|
|
:command-id="activeCommandId"
|
|
:fetch-data-template="fetchDataCommandTypeId"
|
|
/>
|
|
</q-tab-panel>
|
|
</q-tab-panels>
|
|
</div>
|
|
<div
|
|
v-else-if="isCode == 'C-PM-47'"
|
|
style="height: auto; max-width: 100%; max-height: 90vh"
|
|
>
|
|
<div
|
|
class="absolute-center text-center text-grey-9"
|
|
style="width: 100%"
|
|
></div>
|
|
</div>
|
|
<div v-else style="height: auto; max-width: 100%; max-height: 90vh">
|
|
<div
|
|
class="absolute-center text-center text-grey-9"
|
|
style="width: 100%"
|
|
>
|
|
<div class="column items-center">
|
|
<q-icon
|
|
name="mdi-hand-pointing-left"
|
|
size="lg"
|
|
color="primary"
|
|
></q-icon>
|
|
<span>กรุณาเลือกรายการคำสั่ง</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</q-card>
|
|
</div>
|
|
</div>
|
|
|
|
<q-dialog v-model="dialogFormCommand" persistent>
|
|
<q-card class="col-12" style="width: 40vw">
|
|
<q-form greedy @submit.prevent @validation-success="onSubmit">
|
|
<Header
|
|
:tittle="isEdit ? 'แก้ไขคำสั่ง' : 'เพิ่มคำสั่ง'"
|
|
:close="closeDialog"
|
|
/>
|
|
<q-separator />
|
|
|
|
<q-card-section>
|
|
<div class="row q-col-gutter-sm">
|
|
<div class="col-12">
|
|
<q-input
|
|
outlined
|
|
dense
|
|
v-model="name"
|
|
label="ชื่อคำสั่ง"
|
|
class="inputgreen"
|
|
:rules="[(val:string) => !!val || `${'กรุณากรอกชื่อคำสั่ง'}`,]"
|
|
hide-bottom-space
|
|
></q-input>
|
|
</div>
|
|
<div class="col-12">
|
|
<q-input
|
|
outlined
|
|
dense
|
|
v-model="subtitle"
|
|
label="คำอธิบาย"
|
|
class="inputgreen"
|
|
hide-bottom-space
|
|
></q-input>
|
|
</div>
|
|
<div class="col-12">
|
|
<q-select
|
|
class="inputgreen"
|
|
v-model="category"
|
|
:label="`${'หมวดหมู่'}`"
|
|
dense
|
|
emit-value
|
|
map-options
|
|
option-label="name"
|
|
:options="categoryOP"
|
|
option-value="id"
|
|
lazy-rules
|
|
use-input
|
|
hide-selected
|
|
fill-input
|
|
hide-bottom-space
|
|
outlined
|
|
:rules="[(val:string) => !!val || `${'กรุณาเลือกหมวดหมู่'}`]"
|
|
@filter="(inputValue:string,
|
|
doneFn:Function) => filterSelector(inputValue, doneFn) "
|
|
>
|
|
<template v-slot:no-option>
|
|
<q-item>
|
|
<q-item-section class="text-grey">
|
|
ไม่มีข้อมูล
|
|
</q-item-section>
|
|
</q-item>
|
|
</template>
|
|
</q-select>
|
|
</div>
|
|
<div class="col-12">
|
|
<div class="row items-center justify-between border_custom">
|
|
<p class="q-ma-none">สถานะการใช้งาน</p>
|
|
<label :class="`toggle-control`">
|
|
<input type="checkbox" v-model="status" />
|
|
<span class="control"></span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="col-12">
|
|
<q-checkbox
|
|
v-model="isAttachment"
|
|
label="บัญชีแนบท้าย"
|
|
size="sm"
|
|
/>
|
|
<q-checkbox v-model="isSalary" label="แก้ไขเงินเดือน" size="sm" />
|
|
|
|
<q-checkbox
|
|
v-model="isUploadAttachment"
|
|
label="อัปโหลดบัญชีแนบท้าย"
|
|
size="sm"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</q-card-section>
|
|
<q-separator />
|
|
|
|
<q-card-actions align="right">
|
|
<q-btn label="บันทึก" color="secondary" type="submit"
|
|
><q-tooltip>บันทึกข้อมูล</q-tooltip></q-btn
|
|
>
|
|
</q-card-actions>
|
|
</q-form>
|
|
</q-card>
|
|
</q-dialog>
|
|
</template>
|
|
|
|
<style scoped lang="scss">
|
|
:deep(.scrollStyle .q-scrollarea__bar) {
|
|
background-color: #909090;
|
|
border-radius: 10px;
|
|
width: 5px;
|
|
opacity: 0.1;
|
|
right: 0px;
|
|
}
|
|
:deep(.scrollStyle .q-scrollarea__thumb) {
|
|
background-color: #909090;
|
|
border-radius: 10px;
|
|
width: 5px;
|
|
opacity: 0.5;
|
|
right: 0px;
|
|
}
|
|
.my-menu_link {
|
|
background: #ebf9f7 !important;
|
|
border-radius: 5px;
|
|
color: #1bb19ab8 !important;
|
|
}
|
|
|
|
.my-menu-link .q-hoverable {
|
|
border-radius: 5px;
|
|
}
|
|
|
|
.my-link {
|
|
font-size: 0.75rem;
|
|
padding: 2px;
|
|
min-height: 10px !important;
|
|
}
|
|
|
|
.my-link:hover {
|
|
border-radius: 5px;
|
|
}
|
|
|
|
.border_custom {
|
|
border-radius: 5px !important;
|
|
border: 1px solid #c8d3db;
|
|
height: 40px;
|
|
padding: 0 12px;
|
|
}
|
|
$toggle-background-color-on: #06884d;
|
|
$toggle-background-color-off: darkgray;
|
|
$toggle-control-color: white;
|
|
$toggle-width: 40px;
|
|
$toggle-height: 25px;
|
|
$toggle-gutter: 3px;
|
|
$toggle-radius: 50%;
|
|
$toggle-control-speed: 0.15s;
|
|
$toggle-control-ease: ease-in;
|
|
$toggle-radius: calc($toggle-height / 2);
|
|
$toggle-control-size: $toggle-height - ($toggle-gutter * 2);
|
|
|
|
.toggle-control {
|
|
display: block;
|
|
position: relative;
|
|
padding-left: $toggle-width;
|
|
margin-bottom: 12px;
|
|
cursor: pointer;
|
|
font-size: 22px;
|
|
user-select: none;
|
|
|
|
input {
|
|
position: absolute;
|
|
opacity: 0;
|
|
cursor: pointer;
|
|
height: 0;
|
|
width: 0;
|
|
}
|
|
|
|
input:checked ~ .control {
|
|
background-color: $toggle-background-color-on;
|
|
|
|
&:after {
|
|
left: $toggle-width - $toggle-control-size - $toggle-gutter;
|
|
}
|
|
}
|
|
|
|
.control {
|
|
position: absolute;
|
|
top: -7px;
|
|
left: -15px;
|
|
height: $toggle-height;
|
|
width: $toggle-width;
|
|
border-radius: $toggle-radius;
|
|
background-color: $toggle-background-color-off;
|
|
transition: background-color $toggle-control-speed $toggle-control-ease;
|
|
|
|
&:after {
|
|
content: "";
|
|
position: absolute;
|
|
left: $toggle-gutter;
|
|
top: $toggle-gutter;
|
|
width: $toggle-control-size;
|
|
height: $toggle-control-size;
|
|
border-radius: $toggle-radius;
|
|
background: $toggle-control-color;
|
|
transition: left $toggle-control-speed $toggle-control-ease;
|
|
}
|
|
}
|
|
}
|
|
</style>
|