fix(director):sort

This commit is contained in:
DESKTOP-1R2VSQH\Lenovo ThinkPad E490 2025-10-09 14:50:02 +07:00
parent 629efe5abf
commit 0bec7d1dbc
5 changed files with 270 additions and 368 deletions

View file

@ -7,6 +7,7 @@ const appeal = `${env.API_URI}/discipline/complaint_appeal`;
const disciplineReport = `${env.API_URI}/discipline/report`; const disciplineReport = `${env.API_URI}/discipline/report`;
export default { export default {
directorListMain: `${disciplineMain}/director/`,
directorList: ( directorList: (
page: number, page: number,
pageSize: number, pageSize: number,

View file

@ -19,32 +19,31 @@ const router = useRouter();
* @param id ระบ คคล * @param id ระบ คคล
*/ */
function onSubmit(formData: FormDataPost) { function onSubmit(formData: FormDataPost) {
dialogConfirm($q, () => addData(formData)); dialogConfirm($q, async () => {
} showLoader();
await http
function addData(formData: FormDataPost) { .post(config.API.director(), {
showLoader(); personalId: formData.personalId ?? "",
http prefix: formData.prefix,
.post(config.API.director(), { firstName: formData.firstname,
personalId: formData.personalId ?? "", lastName: formData.lastname,
prefix: formData.prefix, position: formData.position,
firstName: formData.firstname, email: formData.email,
lastName: formData.lastname, phone: formData.phone,
position: formData.position, qualification: formData.qualification,
email: formData.email, rootDnaId: formData.rootDnaId,
phone: formData.phone, })
qualification: formData.qualification, .then(async () => {
rootDnaId: formData.rootDnaId, await success($q, "บันทึกข้อมูลสำเร็จ");
}) await router.push(`/discipline/director`);
.then((res) => { })
success($q, "บันทึกข้อมูลสำเร็จ"); .catch((e) => {
}) messageError($q, e);
.catch((e) => { })
messageError($q, e); .finally(() => {
}) hideLoader();
.finally(async () => { });
router.push(`/discipline/director`); });
});
} }
</script> </script>
<template> <template>

View file

@ -7,6 +7,7 @@ import { useRoute } from "vue-router";
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin"; import { useCounterMixin } from "@/stores/mixin";
import { usePagination } from "@/composables/usePagination";
import type { import type {
FormData, FormData,
@ -18,15 +19,6 @@ import type {
import PopupPersonal from "@/components/Dialogs/PopupPersonalNew.vue"; import PopupPersonal from "@/components/Dialogs/PopupPersonalNew.vue";
const total = ref<number>(0);
const totalList = ref<number>(1);
const pagination = ref({
sortBy: "createdAt",
descending: true,
page: 1,
rowsPerPage: 10,
});
const route = useRoute(); const route = useRoute();
const modalPersonal = ref<boolean>(false); const modalPersonal = ref<boolean>(false);
const personId = ref<string>(""); const personId = ref<string>("");
@ -36,6 +28,7 @@ const search = ref<string>("");
const $q = useQuasar(); const $q = useQuasar();
const mixin = useCounterMixin(); const mixin = useCounterMixin();
const { messageError, showLoader, hideLoader } = mixin; const { messageError, showLoader, hideLoader } = mixin;
const { pagination, params, onRequest } = usePagination("", getSearch);
/** รับ props มาจาก page หลัก */ /** รับ props มาจาก page หลัก */
const props = defineProps({ const props = defineProps({
@ -56,16 +49,8 @@ const typeOps = ref<typeOp[]>([
]); ]);
const isReadonly = ref<boolean>(false); // const isReadonly = ref<boolean>(false); //
const emit = defineEmits(["formDataReturn"]); const emit = defineEmits(["formDataReturn"]);
/**
* อมลเลขประจำตวประชาชน
*/
//
const idCard = ref<string>("");
const idCardRef = ref<any>(null);
/** /** ข้อมูลทั้งก้อน form*/
* อมลทงกอน form
*/
const formData = reactive<FormData>({ const formData = reactive<FormData>({
personalId: "", personalId: "",
prefix: "", prefix: "",
@ -78,9 +63,7 @@ const formData = reactive<FormData>({
rootDnaId: "", rootDnaId: "",
}); });
/** /** ตรวจสอบข้อมูลก่อนส่งไปยัง api*/
* ตรวจสอบขอมลกอนสงไปย api
*/
const prefixRef = ref<object | null>(null); const prefixRef = ref<object | null>(null);
const firstnameRef = ref<object | null>(null); const firstnameRef = ref<object | null>(null);
const lastnameRef = ref<object | null>(null); const lastnameRef = ref<object | null>(null);
@ -183,11 +166,8 @@ function updateSelect() {
/** ค้าหาข้อมูล */ /** ค้าหาข้อมูล */
async function searchInput() { async function searchInput() {
searchRef.value.validate(); pagination.value.page = 1;
if (!searchRef.value.hasError) { await getSearch();
pagination.value.page = 1;
await getSearch();
}
} }
/** ดึงข้อมูล */ /** ดึงข้อมูล */
@ -195,44 +175,40 @@ async function getSearch() {
showLoader(); showLoader();
const body = { const body = {
fieldName: type.value, fieldName: type.value,
keyword: search.value, keyword: search.value ? search.value.trim() : "",
system: (route.meta?.Key as string) || undefined, system: (route.meta?.Key as string) || undefined,
}; };
await http await http
.post( .post(config.API.orgSearchPersonal(), body, { params: params.value })
config.API.orgSearchPersonal() +
`?page=${pagination.value.page}&pageSize=${pagination.value.rowsPerPage}&searchKeyword=${search.value}`,
body
)
.then((res) => { .then((res) => {
totalList.value = Math.ceil( const result = res.data.result;
res.data.result.total / pagination.value.rowsPerPage pagination.value.rowsNumber = result.total;
); if (result.data.length > 0) {
total.value = res.data.result.total; rows.value = result.data.map((e: ResponsePreson) => ({
const data = res.data.result.data; personId: e.id,
const list = data.map((e: ResponsePreson) => ({ idcard: e.citizenId,
personId: e.id, prefix: e.prefix,
idcard: e.citizenId, firstName: e.firstName,
prefix: e.prefix, lastName: e.lastName,
firstName: e.firstName, name: `${e.prefix ? e.prefix : ""}${
lastName: e.lastName, e.firstName ? e.firstName : ""
name: `${e.prefix ? e.prefix : ""}${e.firstName ? e.firstName : ""} ${ } ${e.lastName ? e.lastName : ""}`,
e.lastName ? e.lastName : "" posNo: e.posNo ?? "-",
}`, position: e.position ?? "-",
posNo: e.posNo ?? "-", positionLevel: e.positionLevel ?? "-",
position: e.position ?? "-", salary: e.salaries ?? "-",
positionLevel: e.positionLevel ?? "-", organization: e.organization ?? "-",
salary: e.salaries ?? "-", phone: e.phone ?? "-",
organization: e.organization ?? "-", email: e.email ?? "-",
phone: e.phone ?? "-", rootDnaId: e.rootDnaId ?? "-",
email: e.email ?? "-", }));
rootDnaId: e.rootDnaId ?? "-", } else {
})); rows.value = [];
}
rows.value = list;
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
rows.value = [];
}) })
.finally(() => { .finally(() => {
hideLoader(); hideLoader();
@ -267,31 +243,23 @@ function updatemodalPersonal(modal: boolean) {
modalPersonal.value = modal; modalPersonal.value = modal;
} }
function updatePagination(newPagination: any) {
pagination.value.page = 1;
pagination.value.rowsPerPage = newPagination.rowsPerPage;
}
/** /**
* เชคขอมลจาก props * เชคขอมลจาก props
* เมอมอม * เมอมอม
* เกบขอมลลง formData * เกบขอมลลง formData
*/ */
watch(props.data, async () => {
formData.prefix = props.data.prefix;
formData.firstname = props.data.firstname;
formData.lastname = props.data.lastname;
formData.position = props.data.position;
formData.phone = props.data.phone;
formData.email = props.data.email;
formData.qualification = props.data.qualification;
});
watch( watch(
() => pagination.value.rowsPerPage, () => props.data,
async () => { async () => {
await getSearch(); formData.prefix = props.data.prefix;
} formData.firstname = props.data.firstname;
formData.lastname = props.data.lastname;
formData.position = props.data.position;
formData.phone = props.data.phone;
formData.email = props.data.email;
formData.qualification = props.data.qualification;
},
{ deep: true }
); );
</script> </script>
@ -343,7 +311,7 @@ watch(
</div> </div>
<div class="col-12 q-pt-sm"> <div class="col-12 q-pt-sm">
<d-table <p-table
ref="table" ref="table"
:columns="columnsRespondent" :columns="columnsRespondent"
:rows="rows" :rows="rows"
@ -352,26 +320,11 @@ watch(
bordered bordered
:paging="true" :paging="true"
dense dense
class="custom-header-table"
:visible-columns="visibleColumnsRespondent" :visible-columns="visibleColumnsRespondent"
:rows-per-page-options="[10, 25, 50, 100]" :rows-per-page-options="[10, 25, 50, 100]"
@update:pagination="updatePagination" v-model:pagination="pagination"
@request="onRequest"
> >
<template v-slot:pagination="scope">
งหมด {{ total }} รายการ
<q-pagination
v-model="pagination.page"
active-color="primary"
color="dark"
:max="Number(totalList)"
size="sm"
boundary-links
direction-links
:max-pages="5"
@update:model-value="getSearch"
></q-pagination>
</template>
<template v-slot:header="props"> <template v-slot:header="props">
<q-tr :props="props"> <q-tr :props="props">
<q-th <q-th
@ -393,11 +346,7 @@ watch(
@click="returnDetail(props.row)" @click="returnDetail(props.row)"
> >
<div v-if="col.name == 'no'"> <div v-if="col.name == 'no'">
{{ {{ props.rowIndex + 1 }}
(pagination.page - 1) * pagination.rowsPerPage +
props.rowIndex +
1
}}
</div> </div>
<div v-else-if="col.name == 'info'"> <div v-else-if="col.name == 'info'">
<q-btn <q-btn
@ -413,12 +362,12 @@ watch(
</div> </div>
<div v-else> <div v-else>
{{ col.value }} {{ col.value ?? "-" }}
</div> </div>
</q-td> </q-td>
</q-tr> </q-tr>
</template> </template>
</d-table> </p-table>
</div> </div>
</div> </div>

View file

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, watch } from "vue"; import { ref, onMounted } from "vue";
import { useQuasar } from "quasar"; import { useQuasar } from "quasar";
import config from "@/app.config"; import config from "@/app.config";
@ -9,6 +9,7 @@ import { checkPermission } from "@/utils/permissions";
import { useCounterMixin } from "@/stores/mixin"; import { useCounterMixin } from "@/stores/mixin";
import { useDisciplineDirectorDataStore } from "@/modules/11_discipline/store/DirectorStore"; import { useDisciplineDirectorDataStore } from "@/modules/11_discipline/store/DirectorStore";
import { useDisciplineMainStore } from "@/modules/11_discipline/store/Main"; import { useDisciplineMainStore } from "@/modules/11_discipline/store/Main";
import { usePagination } from "@/composables/usePagination";
import type { DirectorRowsResponse } from "@/modules/11_discipline/interface/response/director"; import type { DirectorRowsResponse } from "@/modules/11_discipline/interface/response/director";
@ -21,6 +22,7 @@ const mainStore = useDisciplineMainStore();
const route = useRoute(); const route = useRoute();
const mixin = useCounterMixin(); const mixin = useCounterMixin();
const { messageError, showLoader, hideLoader, dialogRemove, success } = mixin; const { messageError, showLoader, hideLoader, dialogRemove, success } = mixin;
const { pagination, params, onRequest } = usePagination("", getList);
const titleInvestigate = ref<string>(""); const titleInvestigate = ref<string>("");
const personalId = ref<string>(""); const personalId = ref<string>("");
@ -36,33 +38,23 @@ const dataPopUp = ref<DirectorRowsResponse>();
const filterKeyword = ref<string>(""); const filterKeyword = ref<string>("");
const filterRef = ref<HTMLInputElement | null>(null); const filterRef = ref<HTMLInputElement | null>(null);
const total = ref<number>(0);
const totalList = ref<number>(1);
const pagination = ref({
sortBy: "createdAt",
descending: true,
page: 1,
rowsPerPage: 10,
});
async function getList() { async function getList() {
showLoader(); showLoader();
await http await http
.get( .get(
config.API.directorList( config.API.directorListMain +
pagination.value.page, `${mainStore.pathDirector(route.name as string)}`,
pagination.value.rowsPerPage, {
filterKeyword.value.trim(), params: {
mainStore.pathDirector(route.name as string) ...params.value,
) keyword: filterKeyword.value.trim(),
},
}
) )
.then((res) => { .then((res) => {
const data = res.data.result.data; const result = res.data.result;
totalList.value = Math.ceil( pagination.value.rowsNumber = result.total;
res.data.result.total / pagination.value.rowsPerPage dataStore.fetchData(result.data);
);
total.value = res.data.result.total;
dataStore.fetchData(data);
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
@ -77,38 +69,21 @@ async function getList() {
* @param id ไอดของขอม * @param id ไอดของขอม
*/ */
function clickDelete(id: string) { function clickDelete(id: string) {
dialogRemove($q, async () => deleteData(id), `ลบข้อมูล`); dialogRemove($q, async () => {
} showLoader();
await http
/** .delete(config.API.directorbyId(id))
* ลบขอม .then(async () => {
* @param id type await getList();
*/ success($q, "ลบข้อมูลสำเร็จ");
async function deleteData(id: string) { })
showLoader(); .catch((e) => {
await http messageError($q, e);
.delete(config.API.directorbyId(id)) })
.then((res) => { .finally(async () => {
success($q, "ลบข้อมูลสำเร็จ"); hideLoader();
}) });
.catch((e) => { });
messageError($q, e);
})
.finally(async () => {
await getList();
});
}
function resetFilter() {
filterKeyword.value = "";
if (filterRef.value) {
filterRef.value.focus();
getSearch();
}
}
function filterFn() {
getSearch();
} }
function openDetail(data: DirectorRowsResponse, typeChange: string) { function openDetail(data: DirectorRowsResponse, typeChange: string) {
@ -132,210 +107,188 @@ function onEdit(id: string, check: boolean) {
isEdit.value = check; isEdit.value = check;
} }
function updatePagination(newPagination: any) {
pagination.value.page = 1;
pagination.value.rowsPerPage = newPagination.rowsPerPage;
}
function getSearch() { function getSearch() {
pagination.value.page = 1; pagination.value.page = 1;
getList(); getList();
} }
watch(
() => pagination.value.rowsPerPage,
async () => {
getSearch();
}
);
/** /**
* งขอมลจำลองไปย store * งขอมลจำลองไปย store
*/ */
onMounted(() => { onMounted(() => {
getList(); getList();
// get store
}); });
</script> </script>
<template> <template>
<div class="toptitle text-dark col-12 row items-center"> <div class="toptitle text-dark col-12 row items-center">
รายการชอกรรมการ รายการชอกรรมการ
</div> </div>
<q-card flat bordered class="col-12 q-mt-sm q-pa-md"> <q-card flat bordered>
<div class="row col-12 q-col-gutter-sm q-mb-sm"> <div class="col-12 q-pa-md q-col-gutter-sm">
<div> <div class="col-12">
<q-btn <div class="row q-col-gutter-sm">
v-if="checkPermission($route)?.attrIsCreate" <div class="col-xs-12 col-sm-3 col-md-4 col-lg-2">
@click="$router.push(`/discipline/director/add`)" <div class="row items-center">
flat <q-btn
dense v-if="checkPermission($route)?.attrIsCreate"
round @click="$router.push(`/discipline/director/add`)"
color="primary" flat
icon="mdi-plus" dense
> round
<q-tooltip>เพมรายชอกรรมการ</q-tooltip> color="primary"
</q-btn> icon="mdi-plus"
>
<q-tooltip>เพมรายชอกรรมการ</q-tooltip>
</q-btn>
</div>
</div>
<q-space />
<div class="col-xs-12 col-sm-8 col-md-6 col-lg-4">
<div class="row q-col-gutter-sm items-center">
<div class="col-7">
<q-input
standout
dense
v-model="filterKeyword"
ref="filterRef"
outlined
placeholder="ค้นหา"
@keydown.enter.prevent="getSearch"
>
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
</div>
<div class="col-5">
<q-select
v-model="dataStore.visibleColumns"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="dataStore.columns"
option-value="name"
/>
</div>
</div>
</div>
</div>
</div> </div>
<q-space />
<q-input <div class="col-12">
class="col-xs-12 col-sm-3 col-md-2" <p-table
standout :columns="dataStore.columns"
dense :rows="dataStore.rows"
v-model="filterKeyword" row-key="tb-list"
ref="filterRef" flat
outlined bordered
placeholder="ค้นหา" :paging="true"
@keydown.enter.prevent="filterFn" dense
> :rows-per-page-options="[10, 25, 50, 100]"
<template v-slot:append> :visible-columns="dataStore.visibleColumns"
<q-icon name="search" /> v-model:pagination="pagination"
</template> @request="onRequest"
</q-input> >
<template v-slot:header="props">
<q-select <q-tr :props="props">
v-model="dataStore.visibleColumns" <q-th auto-width />
multiple <q-th v-for="col in props.cols" :key="col.name" :props="props">
outlined <span class="text-weight-medium">{{ col.label }}</span>
dense </q-th>
options-dense </q-tr>
:display-value="$q.lang.table.columns" </template>
emit-value <template v-slot:body="props">
map-options <q-tr :props="props">
:options="dataStore.columns" <q-td auto-width>
option-value="name" <q-btn
v-if="checkPermission($route)?.attrIsGet"
style="min-width: 140px" dense
class="col-xs-12 col-sm-3 col-md-2" flat
/> round
</div> color="info"
@click="onEdit(props.row.id, false)"
<div class="col-12"> icon="mdi-eye"
<d-table >
:columns="dataStore.columns" <q-tooltip>รายละเอยด</q-tooltip>
:rows="dataStore.rows" </q-btn>
row-key="tb-list" <q-btn
flat v-if="
bordered checkPermission($route)?.attrIsUpdate &&
:paging="true" checkPermission($route)?.attrIsGet
dense "
:rows-per-page-options="[10, 25, 50, 100]" dense
@update:pagination="updatePagination" flat
:visible-columns="dataStore.visibleColumns" round
> color="edit"
<template v-slot:pagination="scope"> @click="onEdit(props.row.id, true)"
งหมด {{ total }} รายการ icon="edit"
<q-pagination >
v-model="pagination.page" <q-tooltip>แกไขขอม</q-tooltip>
active-color="primary" </q-btn>
color="dark" <q-btn
:max="Number(totalList)" v-if="checkPermission($route)?.attrIsDelete"
size="sm" dense
boundary-links flat
direction-links round
:max-pages="5" color="red"
@update:model-value="getList" @click="clickDelete(props.row.id)"
></q-pagination> icon="mdi-delete"
</template> >
<template v-slot:header="props"> <q-tooltip>ลบขอม</q-tooltip>
<q-tr :props="props"> </q-btn>
<q-th auto-width /> </q-td>
<q-th v-for="col in props.cols" :key="col.name" :props="props"> <q-td v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span> <div v-if="col.name == 'no'">
</q-th> {{ props.rowIndex + 1 }}
</q-tr> </div>
</template> <div
<template v-slot:body="props"> v-else-if="
<q-tr :props="props"> col.name == 'totalInvestigate' &&
<q-td auto-width> props.row.totalInvestigate > 0
<q-btn "
v-if="checkPermission($route)?.attrIsGet" :class="
dense checkPermission($route)?.attrIsGet
flat ? 'text-blue cursor-pointer'
round : ''
color="info" "
@click="onEdit(props.row.id, false)" @click="
icon="mdi-eye" checkPermission($route)?.attrIsGet
> ? openDetail(props.row, 'investigate')
<q-tooltip>รายละเอยด</q-tooltip> : ''
</q-btn> "
<q-btn >
v-if=" {{ props.row.totalInvestigate }}
checkPermission($route)?.attrIsUpdate && </div>
checkPermission($route)?.attrIsGet <div
" v-else-if="
dense col.name == 'totalDisciplinary' &&
flat props.row.totalDisciplinary > 0
round "
color="edit" :class="
@click="onEdit(props.row.id, true)" checkPermission($route)?.attrIsGet
icon="edit" ? 'text-blue cursor-pointer'
> : ''
<q-tooltip>แกไขขอม</q-tooltip> "
</q-btn> @click="
<q-btn checkPermission($route)?.attrIsGet
v-if="checkPermission($route)?.attrIsDelete" ? openDetail(props.row, 'disciplinary')
dense : ''
flat "
round >
color="red" {{ props.row.totalDisciplinary }}
@click="clickDelete(props.row.id)" </div>
icon="mdi-delete" <div v-else>
> {{ col.value ?? "-" }}
<q-tooltip>ลบขอม</q-tooltip> </div>
</q-btn> </q-td>
</q-td> </q-tr>
<q-td v-for="col in props.cols" :key="col.name" :props="props"> </template>
<div v-if="col.name == 'no'"> </p-table>
{{ </div>
(pagination.page - 1) * pagination.rowsPerPage +
props.rowIndex +
1
}}
</div>
<div
v-else-if="
col.name == 'totalInvestigate' &&
props.row.totalInvestigate > 0
"
:class="
checkPermission($route)?.attrIsGet
? 'text-blue cursor-pointer'
: ''
"
@click="
checkPermission($route)?.attrIsGet
? openDetail(props.row, 'investigate')
: ''
"
>
{{ props.row.totalInvestigate }}
</div>
<div
v-else-if="
col.name == 'totalDisciplinary' &&
props.row.totalDisciplinary > 0
"
:class="
checkPermission($route)?.attrIsGet
? 'text-blue cursor-pointer'
: ''
"
@click="
checkPermission($route)?.attrIsGet
? openDetail(props.row, 'disciplinary')
: ''
"
>
{{ props.row.totalDisciplinary }}
</div>
<div v-else>
{{ col.value ?? "-" }}
</div>
</q-td>
</q-tr>
</template>
</d-table>
</div> </div>
</q-card> </q-card>

View file

@ -14,7 +14,7 @@ export const useDisciplineDirectorDataStore = defineStore(
const rows = ref<DirectorRowsResponse[]>([]); const rows = ref<DirectorRowsResponse[]>([]);
const visibleColumns = ref<string[]>([ const visibleColumns = ref<string[]>([
"no", "no",
"fullName", "firstName",
"position", "position",
"email", "email",
"phone", "phone",
@ -34,7 +34,7 @@ export const useDisciplineDirectorDataStore = defineStore(
style: "font-size: 14px", style: "font-size: 14px",
}, },
{ {
name: "fullName", name: "firstName",
align: "left", align: "left",
label: "ชื่อ-นามสกุล", label: "ชื่อ-นามสกุล",
sortable: true, sortable: true,