Refactoring code module 01_metadata => 01_personal

This commit is contained in:
DESKTOP-1R2VSQH\Lenovo ThinkPad E490 2024-09-03 15:24:00 +07:00
parent d41a2516c3
commit 6c72c90524
42 changed files with 629 additions and 7824 deletions

View file

@ -1,365 +0,0 @@
<script setup lang="ts">
import { ref, reactive, onMounted } from "vue";
import { useQuasar } from "quasar";
import { useRouter, useRoute } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
/** importType*/
import type { FormDataRole } from "@/modules/01_metadata/interface/request/Main";
import type { DataOption } from "@/modules/01_metadata/interface/index/Main";
/** importStore*/
import { useCounterMixin } from "@/stores/mixin";
/** use*/
const $q = useQuasar();
const route = useRoute();
const router = useRouter();
const { showLoader, hideLoader, messageError, date2Thai } = useCounterMixin();
const heightSize = ref<string>("224");
const id = ref<string>(route.params.id ? route.params.id.toLocaleString() : "");
const form = reactive<FormDataRole>({
position: "", //
year: null, //
round: "", //
org: "", ///
including: "", //
includingName: "", //
target: "", //
unit: "", //
weight: null, //
meaning: "", //
formula: "", //
documentInfoEvidence: "", //
node: null,
nodeId: null,
orgRevisionId: null,
date: [null, null],
});
const fieldLabels = {
score5: "5",
score4: "4",
score3: "3",
score2: "2",
score1: "1",
};
const formScore = reactive<any>({
score5: "",
score4: "",
score3: "",
score2: "",
score1: "",
});
/** Option รอบการประเมิน*/
const roundOp = ref<DataOption[]>([
{ id: "APR", name: "รอบเมษายน" },
{ id: "OCT", name: "รอบตุลาคม" },
]);
function fetchspecialByid(id: string) {
showLoader();
http
.get(config.API.kpiSpecial + `/${id}`)
.then((res) => {
console.log(res);
const data = res.data.result;
form.year = data.year;
form.round = data.period;
form.including = data.including;
form.includingName = data.includingName;
form.target = data.target;
form.unit = data.unit;
form.weight = data.weight;
formScore.score1 = data.achievement1;
formScore.score2 = data.achievement2;
formScore.score3 = data.achievement3;
formScore.score4 = data.achievement4;
formScore.score5 = data.achievement5;
form.formula = data.formula;
form.meaning = data.meaning;
form.documentInfoEvidence = data.documentInfoEvidence;
if (data.startDate && data.endDate) {
form.date = [data.startDate, data.endDate];
}
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
function onResize(size: any) {
heightSize.value = `${size.height - 99}`;
}
onMounted(() => {
fetchspecialByid(id.value);
});
</script>
<template>
<div class="toptitle text-dark col-12 row items-center">
<q-btn
flat
round
dense
class="q-mr-sm"
icon="mdi-arrow-left"
color="primary"
@click="router.go(-1)"
/>
รายละเอยดงานทไดบมอบหมาย
</div>
<q-card flat>
<q-card-section>
<div class="row q-col-gutter-sm">
<div class="col-2">
<datepicker
menu-class-name="modalfix"
v-model="form.year"
:locale="'th'"
autoApply
year-picker
:enableTimePicker="false"
@update:model-value="form.round = ''"
readonly
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
dense
class="inputgreen"
outlined
:model-value="form.year === 0 ? null : Number(form.year) + 543"
:label="`${'ปีงบประมาณ'}`"
readonly
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-2">
<q-select
readonly
dense
outlined
v-model="form.round"
:options="roundOp"
option-label="name"
option-value="id"
emit-value
map-options
input-class="text-red"
label="รอบการประเมิน"
class="inputgreen"
/>
</div>
<div class="col-2" v-if="id">
<q-input
label="ลำดับ/รหัสตัวชี้วัด"
v-model="form.including"
outlined
readonly
dense
class="inputgreen"
/>
</div>
<div class="col-6">
<q-input
readonly
label="ชื่อตัวชี้วัด"
v-model="form.includingName"
outlined
dense
class="inputgreen"
lazy-rules
:rules="[(val:string) => !!val || `${'กรุณากรอกชื่อตัวชี้วัด'}`,]"
hide-bottom-space
/>
</div>
<div class="col-4">
<q-input
readonly
label="ค่าเป้าหมาย"
v-model="form.target"
outlined
dense
class="inputgreen"
lazy-rules
:rules="[(val:string) => !!val || `${'กรุณากรอกค่าเป้าหมาย'}`,]"
hide-bottom-space
/>
</div>
<div class="col-4">
<q-input
readonly
label="หน่วยนับ"
v-model="form.unit"
outlined
dense
class="inputgreen"
lazy-rules
:rules="[(val:string) => !!val || `${'กรุณากรอกหน่วยนับ'}`,]"
hide-bottom-space
/>
</div>
<div class="col-4">
<q-input
readonly
label="น้ำหนัก"
v-model="form.weight"
outlined
dense
class="inputgreen"
lazy-rules
:rules="[(val:string) => !!val || `${'กรุณากรอกน้ำหนัก'}`,]"
hide-bottom-space
/>
</div>
<div class="col-12">
<q-card flat bordered>
<q-resize-observer @resize="onResize" />
<q-card-section class="bg-grey-3 q-pa-sm">
<div class="row text-dark text-body2 text-weight-medium">
<div class="text-center col-4">ระดบคะแนน</div>
<div class="col-8">ผลสำเรจของงาน</div>
</div>
</q-card-section>
<q-card-section class="q-pa-none">
<div
v-for="(field, index) in Object.keys(fieldLabels)"
:key="index + 1"
>
<div class="row q-pa-sm">
<div
class="col-4 text-center text-body1 text-weight-bold self-center"
>
{{ fieldLabels[field as keyof typeof fieldLabels] }}
</div>
<div class="col-8 text-left">
<q-input
readonly
v-model="formScore[field]"
dense
outlined
class="inputgreen"
label="กรอกผลสำเร็จของงาน"
:rules="[(val:string) => !!val || `${'กรุณากรอกผลสำเร็จของงาน'}`,]"
hide-bottom-space
/>
</div>
</div>
<div
class="col-12"
v-if="index !== Object.keys(fieldLabels).length - 1"
>
<q-separator />
</div>
</div>
</q-card-section>
</q-card>
</div>
<div class="col-12">
<q-input
readonly
v-model="form.meaning"
label="นิยามหรือความหมาย"
dense
outlined
lazy-rules
class="inputgreen"
:rules="[(val:string) => !!val || `${'กรุณากรอกนิยามหรือความหมาย'}`,]"
hide-bottom-space
type="textarea"
/>
</div>
<div class="col-12">
<q-input
readonly
v-model="form.formula"
label="สูตรคำนวณ"
dense
outlined
lazy-rules
class="inputgreen"
:rules="[(val:string) => !!val || `${'กรุณากรอกสูตรคำนวณ'}`,]"
hide-bottom-space
type="textarea"
/>
</div>
<div class="col-12">
<q-input
readonly
class="inputgreen"
v-model="form.documentInfoEvidence"
label="ข้อมูลเอกสารหลักฐาน"
outlined
dense
type="textarea"
></q-input>
</div>
<div class="col-3">
<datepicker
v-model="form.date"
:locale="'th'"
autoApply
:enableTimePicker="false"
week-start="0"
range
readonly
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
readonly
dense
outlined
class="inputgreen"
:model-value="
form.date
? `${date2Thai(form.date[0])} - ${date2Thai(form.date[1])}`
: null
"
:label="`${'ช่วงเวลาเริ่มต้น-สิ้นสุด'}`"
hide-bottom-space
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
</div>
</q-card-section>
</q-card>
</template>
<style scoped></style>

View file

@ -1,79 +0,0 @@
<script setup lang="ts">
import { ref } from "vue";
import type { QTableProps } from "quasar";
import DialogHeader from "@/components/DialogHeader.vue";
import { useCounterMixin } from "@/stores/mixin";
const mixin = useCounterMixin();
const { date2Thai } = mixin;
const modal = defineModel<boolean>("modal", { required: true });
const rows = defineModel<any[]>("rows", { required: true });
const visibleColumns = ref<string[]>(["createdFullName", "lastUpdatedAt"]);
const columns = ref<QTableProps["columns"]>([
{
name: "createdFullName",
align: "left",
label: "ชื่อ",
sortable: true,
field: "createdFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "lastUpdatedAt",
align: "left",
label: "เวลาที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
]);
function close() {
modal.value = false;
}
</script>
<template>
<q-dialog persistent v-model="modal">
<q-card style="min-width: 30vw">
<DialogHeader tittle="ประวัติการแก้ไข" :close="close" />
<q-separator />
<q-card-section>
<d-table
for="table"
ref="table"
:columns="columns"
:rows="rows"
row-key="id"
flat
bordered
dense
class="custom-header-table"
:rows-per-page-options="[10, 25, 50, 100]"
:visible-columns="visibleColumns"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props" class="cursor-pointer">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'lastUpdatedAt'" class="table_ellipsis">
{{ col.value ? date2Thai(col.value, false, true) : "-" }}
</div>
<div v-else class="table_ellipsis">
{{ col.value ? col.value : "-" }}
</div>
</q-td>
</q-tr>
</template>
</d-table>
</q-card-section>
</q-card>
</q-dialog>
</template>

View file

@ -1,31 +0,0 @@
<script setup lang="ts">
import { ref } from "vue";
import { useRouter, useRoute } from "vue-router";
import IndicatorByPlan from "@/modules/01_metadata/components/Indicators/indicatorByPlan/IndicatorByPlan.vue";
const router = useRouter();
const route = useRoute();
const title = ref<string>(route.params.id ? "แก้ไข" : "เพิ่ม");
</script>
<template>
<div class="toptitle text-dark col-12 row items-center">
<q-btn
flat
round
dense
class="q-mr-sm"
icon="mdi-arrow-left"
color="primary"
@click="router.push(`/KPI-indicator-plan`)"
/>
{{ `${title}ตัวชี้วัดตามแผนฯ` }}
</div>
<q-card flat bordered>
<IndicatorByPlan />
</q-card>
</template>
<style scoped></style>

View file

@ -1,678 +0,0 @@
<script setup lang="ts">
import { ref, reactive, onMounted } from "vue";
import { QForm, useQuasar } from "quasar";
import { useRoute, useRouter } from "vue-router";
import config from "@/app.config";
import http from "@/plugins/http";
/** importType*/
import type { DataOption } from "@/modules/01_metadata/interface/index/Main";
/** importStore*/
import { usePositionEmp } from "@/modules/01_metadata/stores/organizational";
import { useCounterMixin } from "@/stores/mixin";
/**use*/
const $q = useQuasar();
const route = useRoute();
const router = useRouter();
const store = usePositionEmp();
const mixin = useCounterMixin();
const {
dialogConfirm,
showLoader,
hideLoader,
messageError,
success,
dialogMessageNotify,
} = mixin;
const id = ref<string>(route.params.id ? route.params.id.toLocaleString() : "");
const editCheck = ref<boolean>(route.params.id ? true : false);
/**form ตัวชี้วัดตามแผนฯ*/
const planData = reactive({
period: "", //(->APR, ->OCT)
including: "", //
includingName: "", //
target: "", //
unit: "", //
weight: null, //
achievement1: "", // 1
achievement2: "", // 2
achievement3: "", // 3
achievement4: "", // 4
achievement5: "", // 5
meaning: "", //
formula: "", //
node: null, //
nodeId: null, //id
orgRevisionId: "", //RevisionId
strategy: null, //
strategyId: "", //id
documentInfoEvidence: "", //
});
const year = ref<number | null>(0); //
const roundOp = ref<DataOption[]>([
{ id: "APR", name: "รอบเมษายน" },
{ id: "OCT", name: "รอบตุลาคม" },
]);
const nodeplan = ref<any>([]);
const nodeAgency = ref<any>([]);
const filter = ref<string>("");
const filterAgency = ref<string>("");
const expandedPlan = ref<string[]>([]);
const expandedAgency = ref<string[]>([]);
const editStatus = ref<boolean>(false);
const inputRef = ref<any>(null);
/** function fetch หาโครงสร้างที่ใช้งาน*/
function fetchOrganizationActive() {
http
.get(config.API.activeOrganization)
.then((res) => {
const data = res.data.result;
if (data) {
store.fetchDataActive(data);
store.activeId && fetchTreeAgency(store.activeId);
fetchTreeStrategy();
}
})
.catch((err) => {
messageError($q, err);
});
}
/** function fetchTree ยุทธศาสตร์ / แผน*/
function fetchTreeStrategy() {
http
.get(config.API.devStrategy)
.then((res) => {
const data = res.data.result;
nodeplan.value = data;
})
.catch((err) => {
messageError($q, err);
});
}
/** functioon fetchcTree หน่วยงาน/ส่วนราชการ*/
function fetchTreeAgency(id: string) {
http
.get(config.API.orgByid(id.toString()))
.then(async (res) => {
const data = res.data.result;
nodeAgency.value = data;
store.treeId = "";
})
.catch((err) => {
messageError($q, err);
});
}
/** function fetch ข้อมูลตัวชี้วัด*/
function fetchDataById(id: string) {
showLoader();
http
.get(config.API.kpiPlanById(id))
.then((res) => {
const data = res.data.result;
year.value = Number(data.year);
planData.period = data.round;
planData.including = data.including;
planData.includingName = data.includingName;
planData.target = data.target;
planData.unit = data.unit;
planData.weight = data.weight;
planData.achievement1 = data.achievement1;
planData.achievement2 = data.achievement2;
planData.achievement3 = data.achievement3;
planData.achievement4 = data.achievement4;
planData.achievement5 = data.achievement5;
planData.meaning = data.meaning;
planData.formula = data.formula;
planData.node = data.node;
planData.nodeId = data.nodeId;
planData.orgRevisionId = data.orgRevisionId;
planData.strategy = data.strategy;
planData.strategyId = data.strategyId;
planData.documentInfoEvidence = data.documentInfoEvidence;
// /
const arrayexpandedAgency = [
data.root,
data.child1,
data.child2,
data.child3,
data.child4,
];
expandedAgency.value = arrayexpandedAgency
.filter((e) => e !== null)
.slice(0, -1);
// /
const arrayexpandedPlan = [
data.strategyChild1,
data.strategyChild2,
data.strategyChild3,
data.strategyChild4,
data.strategyChild5,
];
expandedPlan.value = arrayexpandedPlan
.filter((e) => e !== null)
.slice(0, -1);
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
setTimeout(() => {
hideLoader();
}, 1000);
});
}
/** funtion เลือกหรืออัปดเดท ยุทธศาสตร์ / แผน*/
function updateSelected(data: any) {
planData.strategyId = data.id;
planData.strategy = data.level;
}
/** funtion เลือกหรืออัปดเดท หน่วยงาน/ส่วนราชการ*/
function updateSelectedAgency(data: any, isUpdate: boolean = false) {
if (
planData.node === data.orgLevel &&
planData.nodeId === data.orgTreeId &&
!isUpdate
) {
planData.node = null;
planData.nodeId = null;
} else {
planData.node = data.orgLevel;
planData.nodeId = data.orgTreeId;
}
planData.orgRevisionId = data.orgRevisionId;
}
/**function ยืนยันการบันทึกข้อมูล */
function onSubmit() {
if (planData.nodeId == null || planData.strategyId == "") {
dialogMessageNotify(
$q,
`กรุณาเลือกหน่วยงาน/ส่วนราชการ หรือ ยุทธศาสตร์/แผน`
);
} else {
dialogConfirm(
$q,
async () => {
const body = {
year: year.value == 0 ? null : year.value?.toString(),
period: planData.period,
includingName: planData.includingName,
target: planData.target,
unit: planData.unit,
weight: planData.weight,
achievement1: planData.achievement1,
achievement2: planData.achievement2,
achievement3: planData.achievement3,
achievement4: planData.achievement4,
achievement5: planData.achievement5,
meaning: planData.meaning,
formula: planData.formula,
node: planData.node,
nodeId: planData.nodeId,
orgRevisionId: planData.orgRevisionId,
strategy: planData.strategy,
strategyId: planData.strategyId,
documentInfoEvidence: planData.documentInfoEvidence,
};
showLoader();
// editStatus.value ? editData(id.value) : addData();
try {
const url = editStatus.value
? config.API.kpiPlanById(id.value)
: config.API.kpiPlan;
const method = editStatus.value ? "put" : "post";
const res = await http[method](url, body);
success($q, "บันทึกข้อมูลสำเร็จ");
editStatus.value
? fetchDataById(id.value)
: router.push(`/KPI-indicator-plan/${res.data.result}`);
} catch (e) {
messageError($q, e);
} finally {
hideLoader();
}
},
"ยืนยันการบันทึกข้อมูล",
"ต้องการยืนยันการบันทึกข้อมูลนี้หรือไม่ ?"
);
}
}
onMounted(() => {
fetchOrganizationActive();
if (id.value) {
editStatus.value = true;
fetchDataById(id.value);
}
});
</script>
<template>
<q-form @submit.prevent greedy @validation-success="onSubmit()">
<div>
<div class="row q-col-gutter-md q-pa-md">
<div class="col-2" v-if="editCheck">
<q-input
outlined
v-model="planData.including"
label="ลำดับ/รหัสตัวชี้วัด"
bg-color="white"
readonly
dense
class="inputgreen"
/>
</div>
<div :class="`${editCheck ? 'col-6' : 'col-8'}`">
<q-input
outlined
v-model="planData.includingName"
label="ชื่อตัวชี้วัด"
bg-color="white"
dense
class="inputgreen"
:rules="[(val) => !!val || `${'กรุณากรอกชิ่อตัวชี้วัด'}`]"
hide-bottom-space
/>
</div>
<div class="col-2">
<datepicker
menu-class-name="modalfix"
v-model="year"
:locale="'th'"
autoApply
year-picker
:enableTimePicker="false"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
dense
outlined
class="inputgreen"
hide-bottom-space
:model-value="!!year ? year + 543 : null"
:label="`${'ปีงบประมาณ'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
<template v-slot:append>
<q-icon
v-if="year"
name="cancel"
class="cursor-pointer"
@click.stop.prevent="year = 0"
/>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-2">
<q-select
ref="inputRef"
dense
outlined
v-model="planData.period"
:options="roundOp"
label="รอบการประเมิน"
option-label="name"
option-value="id"
map-options
emit-value
class="inputgreen"
/>
</div>
<div class="col-4">
<q-input
outlined
v-model="planData.target"
label="ค่าเป้าหมาย"
bg-color="white"
dense
class="inputgreen"
:rules="[(val) => !!val || `${'กรุณากรอกค่าเป้าหมาย'}`]"
hide-bottom-space
/>
</div>
<div class="col-4">
<q-input
outlined
v-model="planData.unit"
label="หน่วยนับ"
bg-color="white"
dense
lazy-rules
class="inputgreen"
:rules="[(val) => !!val || `${'กรุณากรอกหน่วยนับ'}`]"
hide-bottom-space
/>
</div>
<div class="col-4">
<q-input
outlined
v-model="planData.weight"
label="น้ำหนัก"
type="number"
bg-color="white"
dense
class="inputgreen"
:rules="[(val) => !!val || `${'กรุณากรอกน้ำหนัก'}`]"
hide-bottom-space
/>
</div>
<div class="col-12 row">
<div class="col-6">
<q-card flat bordered>
<q-card bordered>
<q-card-actions class="bg-grey-3 row">
<div class="col-4 flex justify-center items-center">
<div>ระดบคะแนน</div>
</div>
<div class="col-8 q-px-xl">ผลสำเรจของงาน</div>
</q-card-actions>
</q-card>
<div class="row">
<div class="col-4 flex justify-center items-center">
<div>5</div>
</div>
<div class="col-8 q-pa-sm">
<q-input
outlined
v-model="planData.achievement5"
label="กรอกผลสำเร็จของงาน"
bg-color="white"
dense
class="inputgreen"
:rules="[(val) => !!val || `${'กรุณากรอกผลสำเร็จของงาน'}`]"
hide-bottom-space
/>
</div>
</div>
<div class="row">
<div class="col-4 flex justify-center items-center">
<div>4</div>
</div>
<div class="col-8 q-pa-sm">
<q-input
outlined
v-model="planData.achievement4"
label="กรอกผลสำเร็จของงาน"
bg-color="white"
dense
class="inputgreen"
:rules="[(val) => !!val || `${'กรุณากรอกผลสำเร็จของงาน'}`]"
hide-bottom-space
/>
</div>
</div>
<div class="row">
<div class="col-4 flex justify-center items-center">
<div>3</div>
</div>
<div class="col-8 q-pa-sm">
<q-input
outlined
v-model="planData.achievement3"
label="กรอกผลสำเร็จของงาน"
bg-color="white"
dense
class="inputgreen"
:rules="[(val) => !!val || `${'กรุณากรอกผลสำเร็จของงาน'}`]"
hide-bottom-space
/>
</div>
</div>
<div class="row">
<div class="col-4 flex justify-center items-center">
<div>2</div>
</div>
<div class="col-8 q-pa-sm">
<q-input
outlined
v-model="planData.achievement2"
label="กรอกผลสำเร็จของงาน"
bg-color="white"
dense
class="inputgreen"
:rules="[(val) => !!val || `${'กรุณากรอกผลสำเร็จของงาน'}`]"
hide-bottom-space
/>
</div>
</div>
<div class="row">
<div class="col-4 flex justify-center items-center">
<div>1</div>
</div>
<div class="col-8 q-pa-sm">
<q-input
outlined
v-model="planData.achievement1"
label="กรอกผลสำเร็จของงาน"
bg-color="white"
dense
class="inputgreen"
:rules="[(val) => !!val || `${'กรุณากรอกผลสำเร็จของงาน'}`]"
hide-bottom-space
/>
</div>
</div>
</q-card>
</div>
</div>
<div class="col-12">
<q-input
outlined
v-model="planData.meaning"
label="นิยามหรือความหมาย"
type="textarea"
bg-color="white"
dense
class="inputgreen"
:rules="[(val) => !!val || `${'กรุณากรอกนิยามหรือความหมาย'}`]"
hide-bottom-space
/>
</div>
<div class="col-12">
<q-input
outlined
v-model="planData.formula"
label="สูตรคำนวณ"
bg-color="white"
type="textarea"
dense
class="inputgreen"
:rules="[(val) => !!val || `${'กรุณากรอกสูตรคำนวณ'}`]"
hide-bottom-space
/>
</div>
<div class="col-6">
<q-card bordered class="col-12">
<div
class="col-xs-12 col-sm-12 text-weight-medium bg-grey-1 q-py-xs q-px-md"
>
หนวยงาน/วนราชการ
</div>
<q-separator />
<q-card-section class="q-pa-sm">
<q-input
dense
outlined
v-model="filterAgency"
label="ค้นหา"
class="inputgreen"
>
<template v-slot:append>
<q-icon
v-if="filterAgency !== ''"
name="clear"
class="cursor-pointer"
@click="filterAgency = ''"
/>
<q-icon v-else name="search" color="grey-5" />
</template>
</q-input>
<q-tree
style="height: 350px; overflow: scroll"
dense
:nodes="nodeAgency"
node-key="orgTreeId"
label-key="orgTreeName"
selected-color="primary"
:filter="filterAgency"
no-results-label="ไม่พบข้อมูลที่ค้นหา"
no-nodes-label="ไม่มีข้อมูล"
v-model:expanded="expandedAgency"
v-model:selected="planData.nodeId"
>
<template v-slot:default-header="prop">
<q-item
clickable
@click.stop="updateSelectedAgency(prop.node)"
:active="planData.nodeId == prop.node.orgTreeId"
active-class="my-list-link text-primary text-weight-medium"
class="row col-12 items-center text-dark q-py-xs q-pl-sm rounded-borders my-list"
>
<div>
<div class="text-weight-medium">
{{ prop.node.orgTreeName }}
</div>
<div class="text-weight-light text-grey-8">
{{
prop.node.orgCode == null ? null : prop.node.orgCode
}}
{{
prop.node.orgTreeShortName == null
? null
: prop.node.orgTreeShortName
}}
</div>
</div>
</q-item>
</template>
</q-tree>
</q-card-section>
</q-card>
</div>
<div class="col-6">
<q-card bordered class="col-12">
<div
class="col-xs-12 col-sm-12 text-weight-medium bg-grey-1 q-py-xs q-px-md"
>
ทธศาสตร / แผน
</div>
<q-separator />
<q-card-section class="q-pa-sm">
<q-input
dense
outlined
v-model="filter"
label="ค้นหา"
class="inputgreen"
>
<template v-slot:append>
<q-icon
v-if="filter !== ''"
name="clear"
class="cursor-pointer"
@click="filter = ''"
/>
<q-icon v-else name="search" color="grey-5" />
</template>
</q-input>
<q-tree
style="height: 350px; overflow: scroll"
dense
:nodes="nodeplan"
selected-color="primary"
node-key="id"
label-key="name"
:filter="filter"
no-results-label="ไม่พบข้อมูลที่ค้นหา"
no-nodes-label="ไม่มีข้อมูล"
v-model:expanded="expandedPlan"
v-model:selected="planData.strategyId"
>
<template v-slot:default-header="prop">
<q-item
clickable
@click.stop="updateSelected(prop.node)"
:active="planData.strategyId == prop.node.id"
active-class="my-list-link text-primary text-weight-medium"
class="row col-12 items-center text-dark q-py-xs q-pl-sm rounded-borders my-list"
>
<div>
<div class="text-weight-medium">
{{ prop.node.name }}
</div>
</div>
</q-item>
</template>
</q-tree>
</q-card-section>
</q-card>
</div>
<div class="col-12">
<q-input
class="inputgreen"
v-model="planData.documentInfoEvidence"
label="ข้อมูลเอกสารหลักฐาน"
outlined
dense
type="textarea"
></q-input>
</div>
</div>
<q-separator color="grey-4" />
</div>
<q-toolbar class="fit row wrap justify-end items-start content-start">
<q-btn
dense
unelevated
label="บันทึก"
id="onSubmit"
type="submit"
color="public"
class="q-px-md"
>
<q-tooltip>นทกขอม</q-tooltip>
</q-btn>
</q-toolbar>
</q-form>
</template>
<style lang="scss" scoped>
.my-list-link {
color: rgb(118, 168, 222);
border-radius: 5px;
background: #a3d3fb48 !important;
font-weight: 600;
border: 1px solid rgba(175, 185, 196, 0.217);
}
</style>

View file

@ -1,640 +0,0 @@
<script setup lang="ts">
import { ref, reactive, onMounted } from "vue";
import { useQuasar } from "quasar";
import { useRouter, useRoute } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import type { FormDataRole } from "@/modules/01_metadata/interface/request/Main";
import type { DataOption } from "@/modules/01_metadata/interface/index/Main";
const $q = useQuasar();
const route = useRoute();
const router = useRouter();
const heightSize = ref<string>("224");
const filter = ref<string>("");
const node = ref<any>([]);
const expanded = ref<string[]>([]);
const orgName = ref<string>("");
const nodeId = ref<string>("");
const id = ref<string>(route.params.id ? route.params.id.toLocaleString() : "");
const {
showLoader,
hideLoader,
messageError,
success,
dialogConfirm,
dialogMessageNotify,
} = useCounterMixin();
const title = ref<string>(route.params.id ? "แก้ไข" : "เพิ่ม");
const modalDialogSelect = ref<boolean>(false);
const form = reactive<FormDataRole>({
position: "", //
year: new Date().getFullYear(), //
round: "", //
org: "", ///
including: "", //
includingName: "", //
target: "", //
unit: "", //
weight: "", //
meaning: "", //
formula: "", //
documentInfoEvidence: "", //
node: null,
nodeId: null,
orgRevisionId: null,
});
const fieldLabels = {
score5: "5",
score4: "4",
score3: "3",
score2: "2",
score1: "1",
};
const formScore = reactive<any>({
score5: "",
score4: "",
score3: "",
score2: "",
score1: "",
});
const positionOp = ref<DataOption[]>([]);
const positionMainOp = ref<DataOption[]>([]);
/** Option รอบการประเมิน*/
const roundOp = ref<DataOption[]>([
{ id: "APR", name: "รอบเมษายน" },
{ id: "OCT", name: "รอบตุลาคม" },
]);
/**
* function นหาขอมลของ Option
* @param val าทองการฟลเตอร
* @param update พเดทค
* @param refData ดาตาทองการฟลเตอร
*/
function filterOption(val: any, update: Function) {
update(() => {
positionOp.value = positionMainOp.value.filter(
(v: any) => v.name.indexOf(val) > -1
);
});
}
/** ดึงข้อมูลตำแหน่ง */
function getOptions() {
http.get(config.API.orgSalaryPosition).then((res) => {
const dataOp = res.data.result;
const uniqueNames = new Set();
const filteredData = dataOp
.filter((item: any) => {
if (!uniqueNames.has(item.positionName)) {
uniqueNames.add(item.positionName);
return true;
}
return false;
})
.map((item: any) => ({
id: item.positionName,
name: item.positionName,
}));
positionMainOp.value = filteredData;
});
}
/** เปิด Dialog หน่วยงาน */
function selectAgency() {
modalDialogSelect.value = true;
}
/** บันทึกข้อมูล */
function onSubmit() {
const url = id.value
? config.API.kpiRoleMainList + `/${id.value}`
: config.API.kpiRoleMainList;
const body = {
year: form.year == 0 ? null : form.year?.toString(),
position: form.position, //
period: form.round, //(->APR, ->OCT)
includingName: form.includingName, //
target: form.target, //
unit: form.unit, //
weight: form.weight, //
achievement1: formScore.score1, // 1
achievement2: formScore.score2, // 2
achievement3: formScore.score3, // 3
achievement4: formScore.score4, // 4
achievement5: formScore.score5, // 5
meaning: form.meaning, //
formula: form.formula, //
documentInfoEvidence: form.documentInfoEvidence, //
node: form.node, //
nodeId: form.nodeId, //id
orgRevisionId: form.orgRevisionId, //RevisionId
};
if (form.nodeId == null) {
dialogMessageNotify($q, "กรุณาเลือกหน่วยงาน/ส่วนราชการ");
} else {
dialogConfirm($q, () => {
showLoader();
http[id.value ? "put" : "post"](url, body)
.then(() => {
success($q, "บันทึกสำเร็จ");
id.value ? getDetail() : router.push(`/KPI-indicator-role`);
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
});
}
}
//
//
function getDetail() {
showLoader();
http
.get(config.API.kpiRoleMainList + `/${id.value}`)
.then((res) => {
const data = res.data.result;
form.position = data.position;
form.year = data.year == null ? 0 : data.year;
form.round = data.round;
form.including = data.including;
form.includingName = data.includingName;
form.target = data.target;
form.unit = data.unit;
form.weight = data.weight;
form.meaning = data.meaning;
form.formula = data.formula;
form.documentInfoEvidence = data.documentInfoEvidence;
formScore.score1 = data.achievement1;
formScore.score2 = data.achievement2;
formScore.score3 = data.achievement3;
formScore.score4 = data.achievement4;
formScore.score5 = data.achievement5;
form.node = data.node;
form.nodeId = data.nodeId;
form.orgRevisionId = data.orgRevisionId;
const arrayExpanded = [
data.root,
data.child1,
data.child2,
data.child3,
data.child4,
];
expanded.value = arrayExpanded.filter((e) => e !== null).slice(0, -1);
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
function fetchActive() {
showLoader();
http
.get(config.API.activeOrganization)
.then((res) => {
const data = res.data.result;
fetchTree(data.activeId);
})
.catch((err) => {
messageError($q, err);
hideLoader();
});
}
async function fetchTree(id: string) {
showLoader();
http
.get(config.API.orgByid(id.toString()))
.then((res) => {
const data = res.data.result;
node.value = data;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
function updateSelected(data: any) {
nodeId.value = data.orgTreeId;
orgName.value = data.orgTreeName;
form.node = data.orgLevel;
form.nodeId = data.orgTreeId;
form.orgRevisionId = data.orgRevisionId;
}
function onResize(size: any) {
heightSize.value = `${size.height - 99}`;
}
function setModel(val: string) {
form.position = val;
}
onMounted(() => {
fetchActive();
getOptions();
if (id.value !== "") {
getDetail();
}
});
</script>
<template>
<div class="toptitle text-dark col-12 row items-center">
<q-btn
flat
round
dense
class="q-mr-sm"
icon="mdi-arrow-left"
color="primary"
@click="router.go(-1)"
/>
{{ `${title}ตัวชี้วัดตามตำแหน่ง` }}
</div>
<q-card flat>
<q-form greedy @submit.prevent @validation-success="onSubmit">
<q-card-section>
<div class="row q-col-gutter-sm">
<div class="col-8">
<q-select
dense
:model-value="form.position"
label="ตำแหน่งในสายงาน"
outlined
emit-value
map-options
fill-input
hide-selected
lazy-rules
:rules="[(val:string) => !!val || `${'กรุณาเลือกตำแหน่งในสายงาน'}`,]"
hide-bottom-space
option-label="name"
option-value="id"
class="inputgreen"
:options="positionOp"
use-input
@input-value="setModel"
@filter="(inputValue:any,doneFn:Function) => filterOption(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-2">
<datepicker
menu-class-name="modalfix"
v-model="form.year"
:locale="'th'"
autoApply
year-picker
:enableTimePicker="false"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
dense
class="inputgreen"
outlined
:model-value="
form.year === 0 ? null : Number(form.year) + 543
"
:label="`${'ปีงบประมาณ'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
<template v-slot:append>
<q-icon
v-if="form.year"
name="cancel"
class="cursor-pointer"
@click.stop.prevent="form.year = 0"
/>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-2">
<q-select
dense
outlined
v-model="form.round"
:options="roundOp"
option-label="name"
option-value="id"
emit-value
map-options
input-class="text-red"
label="รอบการประเมิน"
class="inputgreen"
/>
</div>
<div class="col-2" v-if="id">
<q-input
label="ลำดับ/รหัสตัวชี้วัด"
v-model="form.including"
outlined
readonly
dense
class="inputgreen"
/>
</div>
<div class="col-4">
<q-input
label="ชื่อตัวชี้วัด"
v-model="form.includingName"
outlined
dense
class="inputgreen"
lazy-rules
:rules="[(val:string) => !!val || `${'กรุณากรอกชื่อตัวชี้วัด'}`,]"
hide-bottom-space
/>
</div>
<div class="col-2">
<q-input
label="ค่าเป้าหมาย"
v-model="form.target"
outlined
dense
class="inputgreen"
lazy-rules
:rules="[(val:string) => !!val || `${'กรุณากรอกค่าเป้าหมาย'}`,]"
hide-bottom-space
/>
</div>
<div class="col-2">
<q-input
label="หน่วยนับ"
v-model="form.unit"
outlined
dense
class="inputgreen"
lazy-rules
:rules="[(val:string) => !!val || `${'กรุณากรอกหน่วยนับ'}`,]"
hide-bottom-space
/>
</div>
<div class="col-2">
<q-input
label="น้ำหนัก"
v-model="form.weight"
outlined
dense
class="inputgreen"
lazy-rules
:rules="[(val:string) => !!val || `${'กรุณากรอกน้ำหนัก'}`,]"
hide-bottom-space
/>
</div>
<div class="col-4">
<q-card flat bordered class="full-height">
<q-card-section class="bg-grey-3 q-pa-sm">
<div class="text-dark text-body2 text-weight-medium">
หนวยงาน/วนราชการ
</div>
</q-card-section>
<q-card-section class="q-pa-sm">
<q-input
dense
outlined
v-model="filter"
label="ค้นหา"
class="inputgreen"
>
<template v-slot:append>
<q-icon
v-if="filter !== ''"
name="clear"
class="cursor-pointer"
@click="filter = ''"
/>
<q-icon v-else name="search" color="grey-5" />
</template>
</q-input>
<q-scroll-area
visible
:style="{ height: `${heightSize}px`, marginTop: '5px' }"
>
<q-tree
dense
:nodes="node"
node-key="orgTreeId"
label-key="orgTreeName"
v-model:expanded="expanded"
:filter="filter"
no-results-label="ไม่พบข้อมูลที่ค้นหา"
no-nodes-label="ไม่มีข้อมูล"
>
<template v-slot:default-header="prop">
<q-item
clickable
@click.stop="updateSelected(prop.node)"
:active="form.nodeId === prop.node.orgTreeId"
active-class="my-list-link text-primary text-weight-medium"
class="row col-12 items-center text-dark q-py-xs q-pl-sm rounded-borders my-list"
>
<div>
<div class="text-weight-medium">
{{ prop.node.orgTreeName }}
</div>
<div class="text-weight-light text-grey-8">
{{
prop.node.orgCode == null
? null
: prop.node.orgCode
}}
{{
prop.node.orgTreeShortName == null
? null
: prop.node.orgTreeShortName
}}
</div>
</div>
</q-item>
</template>
</q-tree>
</q-scroll-area>
</q-card-section>
</q-card>
</div>
<div class="col-8">
<q-card flat bordered>
<q-resize-observer @resize="onResize" />
<q-card-section class="bg-grey-3 q-pa-sm">
<div class="row text-dark text-body2 text-weight-medium">
<div class="text-center col-4">ระดบคะแนน</div>
<div class="col-8">ผลสำเรจของงาน</div>
</div>
</q-card-section>
<q-card-section class="q-pa-none">
<div
v-for="(field, index) in Object.keys(fieldLabels)"
:key="index + 1"
>
<div class="row q-pa-sm">
<div
class="col-4 text-center text-body1 text-weight-bold self-center"
>
{{ fieldLabels[field as keyof typeof fieldLabels] }}
</div>
<div class="col-8 text-left">
<!-- <q-field
class="q_field_p_none"
ref="fieldRef"
v-model="formScore[field]"
label-slot
borderless
:rules="[(val) => !!val || 'กรุณากรอกมาตรฐานพฤติกรรม']"
hide-bottom-space
>
<template #control>
<q-editor
class="full-width"
v-model="formScore[field]"
:dense="$q.screen.lt.md"
min-height="5rem"
:toolbar="[
[
'bold',
'italic',
'strike',
'underline',
'subscript',
'superscript',
],
['unordered', 'ordered'],
]"
:fonts="{
arial: 'Arial',
arial_black: 'Arial Black',
comic_sans: 'Comic Sans MS',
courier_new: 'Courier New',
impact: 'Impact',
lucida_grande: 'Lucida Grande',
times_new_roman: 'Times New Roman',
verdana: 'Verdana',
}"
/>
</template>
</q-field> -->
<q-input
v-model="formScore[field]"
dense
outlined
class="inputgreen"
label="กรอกผลสำเร็จของงาน"
:rules="[(val:string) => !!val || `${'กรุณากรอกผลสำเร็จของงาน'}`,]"
hide-bottom-space
/>
</div>
</div>
<div
class="col-12"
v-if="index !== Object.keys(fieldLabels).length - 1"
>
<q-separator />
</div>
</div>
</q-card-section>
</q-card>
</div>
<div class="col-12">
<q-input
v-model="form.meaning"
label="นิยามหรือความหมาย"
dense
outlined
lazy-rules
class="inputgreen"
:rules="[(val:string) => !!val || `${'กรุณากรอกนิยามหรือความหมาย'}`,]"
hide-bottom-space
type="textarea"
/>
</div>
<div class="col-12">
<q-input
v-model="form.formula"
label="สูตรคำนวณ"
dense
outlined
lazy-rules
class="inputgreen"
:rules="[(val:string) => !!val || `${'กรุณากรอกสูตรคำนวณ'}`,]"
hide-bottom-space
type="textarea"
/>
</div>
<div class="col-12">
<q-input
class="inputgreen"
v-model="form.documentInfoEvidence"
label="ข้อมูลเอกสารหลักฐาน"
outlined
dense
type="textarea"
></q-input>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-actions align="right">
<q-btn color="public" label="บันทึก" type="submit" unelevated>
<q-tooltip>นทกขอม</q-tooltip>
</q-btn>
</q-card-actions>
</q-form>
</q-card>
</template>
<style scoped>
.my-list-link {
color: rgb(118, 168, 222);
border-radius: 5px;
background: #a3d3fb48 !important;
font-weight: 600;
border: 1px solid rgba(175, 185, 196, 0.217);
}
</style>

View file

@ -1,270 +0,0 @@
<script setup lang="ts">
import { ref, onMounted, reactive, watch } from "vue";
import type { QTableProps } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useQuasar } from "quasar";
import { useRouter } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import type {
DataOption,
NewPagination,
} from "@/modules/01_metadata/interface/index/Main";
import type { FormQueryCapacity } from "@/modules/01_metadata/interface/request/Main";
import type { ResDataCapacity } from "@/modules/01_metadata/interface/response/Main";
import { useKPIDataStore } from "@/modules/01_metadata/stores/KPIStore";
const total = ref<number>();
const store = useKPIDataStore();
const router = useRouter();
const $q = useQuasar();
const mixin = useCounterMixin();
const { dialogRemove, messageError, showLoader, hideLoader, success } = mixin;
const competencyTypeOp = ref<DataOption[]>([
{
id: "HEAD",
name: "สมรรถนะหลัก",
},
{
id: "GROUP",
name: "สมรรถนะประจำกลุ่มงาน",
},
{
id: "EXECUTIVE",
name: "สมรรถนะประจำผู้บริหารกรุงเทพมหานคร",
},
{
id: "DIRECTOR",
name: "สมรรถนะเฉพาะสำหรับตำแหน่ง ผอ.เขต ผช.ผอ.เขต และหัวหน้าฝ่ายในสังกัด สนง.เขต",
},
{
id: "INSPECTOR",
name: "สมรรถนะเฉพาะสำหรับตำแหน่งผู้ตรวจราชการ กทม. และผู้ตรวจราชการ",
},
]);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ชื่อสมรรถนะ",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<string[]>(["name"]);
const rows = ref<ResDataCapacity[]>([]);
const formQuery = reactive<FormQueryCapacity>({
page: 1,
pageSize: 10,
keyword: "",
});
const totalList = ref<number>(1); //
/** ดึงข้อมูล */
async function fetchList() {
showLoader();
await http
.get(
config.API.kpiCapacity +
`?page=${formQuery.page}&pageSize=${formQuery.pageSize}&keyword=${formQuery.keyword}&type=${store.competencyTypeVal}`
)
.then(async (res) => {
total.value = res.data.result.total;
const data: ResDataCapacity[] = res.data.result.data;
totalList.value = Math.ceil(res.data.result.total / formQuery.pageSize);
rows.value = data;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
async function onViewDetail(id: string) {
router.push(`/KPI-competency/${id}`);
}
function deleteData(id: string) {
dialogRemove($q, () => {
http
.delete(config.API.kpiCapacity + `/${id}`)
.then(() => {
fetchList();
success($q, "ลบข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
});
}
/** เปลี่ยนเป็นหน้าเพิ่มข้อมูล */
function onAdd() {
router.push(`/KPI-competency/add`);
}
function fetchNewList() {
formQuery.page = 1;
fetchList();
}
/**
* function updatePagination
* @param newPagination อม Pagination ใหม
*/
function updatePagination(newPagination: NewPagination) {
formQuery.page = 1;
formQuery.pageSize = newPagination.rowsPerPage;
}
watch(
() => formQuery.pageSize,
() => {
fetchNewList();
}
);
onMounted(() => {
fetchList();
});
</script>
<template>
<q-toolbar style="padding: 0">
<q-select
v-model="store.competencyTypeVal"
outlined
label="ประเภทสมรรถนะ"
dense
option-label="name"
option-value="id"
:options="competencyTypeOp"
style="min-width: 200px"
emit-value
map-options
@update:model-value="fetchNewList"
/>
<q-btn flat round color="primary" icon="add" @click="onAdd()">
<q-tooltip> เพมขอม </q-tooltip>
</q-btn>
<q-space />
<div class="row q-gutter-sm">
<q-input
outlined
dense
v-model="formQuery.keyword"
label="ค้นหา"
@keyup.enter="fetchNewList()"
>
<template v-slot:append>
<q-icon v-if="formQuery.keyword == ''" name="search" />
<q-icon
v-if="formQuery.keyword !== ''"
name="clear"
class="cursor-pointer"
@click="(formQuery.keyword = ''), fetchNewList()"
/>
</template>
</q-input>
<q-select
v-model="visibleColumns"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns"
option-value="name"
options-cover
style="min-width: 150px"
/>
</div>
</q-toolbar>
<d-table
ref="table"
:columns="columns"
:rows="rows"
row-key="id"
flat
bordered
:paging="true"
dense
:rows-per-page-options="[10, 25, 50, 100]"
class="custom-header-table"
:visible-columns="visibleColumns"
@update:pagination="updatePagination"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
<q-th auto-width />
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props" class="cursor-pointer">
<q-td v-for="col in props.cols" :key="col.id">
{{ col.value }}
</q-td>
<q-td auto-width>
<q-btn
color="edit"
flat
dense
round
size="12px"
icon="edit"
clickable
@click.stop="onViewDetail(props.row.id)"
v-close-popup
>
<q-tooltip>แกไข</q-tooltip>
</q-btn>
<q-btn
color="red"
flat
dense
round
icon="mdi-delete"
clickable
@click.stop="deleteData(props.row.id)"
v-close-popup
>
<q-tooltip>ลบขอม</q-tooltip>
</q-btn>
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
งหมด {{ total }} รายการ
<q-pagination
v-model="formQuery.page"
active-color="primary"
color="dark"
:max="Number(totalList)"
size="sm"
boundary-links
direction-links
:max-pages="5"
@update:model-value="fetchList"
></q-pagination>
</template>
</d-table>
</template>

View file

@ -1,352 +0,0 @@
<script setup lang="ts">
import { ref, onMounted, reactive, watch } from "vue";
import type { QTableProps } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useQuasar } from "quasar";
import dialogHeader from "@/components/DialogHeader.vue";
import type {
DataOption,
NewPagination,
} from "@/modules/14_KPI/interface/index/Main";
import http from "@/plugins/http";
import config from "@/app.config";
const total = ref<number>();
const modal = ref<boolean>(false);
const rows = ref<any[]>([]);
const groupName = ref<string>("");
const editStatus = ref<boolean>(false);
const editId = ref<string>("");
const competencyTypeOp = ref<DataOption[]>([
{
id: "ID1",
name: "สมรรถนะหลัก",
},
{
id: "ID2",
name: "สมรรถนะประจำกลุ่มงาน",
},
{
id: "ID3",
name: "สมรรถนะประจำผู้บริหารกรุงเทพมหานคร",
},
{
id: "ID4",
name: "สมรรถนะเฉพาะสำหรับตำแหน่ง ผอ.เขต ผช.ผอ.เขต และหัวหน้าฝ่ายในสังกัด สนง.เขต",
},
{
id: "ID5",
name: "สมรรถนะเฉพาะสำหรับตำแหน่งผู้ตรวจราชการ กทม. และผู้ตรวจราชการ",
},
]);
const columns = ref<QTableProps["columns"]>([
{
name: "nameGroupKPI",
align: "left",
label: "รายการกลุ่มงาน",
sortable: true,
field: "nameGroupKPI",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const $q = useQuasar();
const mixin = useCounterMixin();
const {
dialogRemove,
dialogConfirm,
showLoader,
hideLoader,
messageError,
success,
} = mixin;
const visibleColumns = ref<string[]>(["nameGroupKPI"]);
const formQuery = reactive({
page: 1,
pageSize: 10,
keyword: "",
});
const totalList = ref<number>(1); //
/** ดึงข้อมูล */
async function fetchData() {
showLoader();
await http
.get(
config.API.kpiGroup +
`?page=${formQuery.page}&pageSize=${formQuery.pageSize}&keyword=${formQuery.keyword}`
)
.then(async (res) => {
total.value = res.data.result.total;
const data = res.data.result;
totalList.value = Math.ceil(res.data.result.total / formQuery.pageSize);
rows.value = data.data;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
async function addData() {
await http
.post(config.API.kpiGroup, {
nameGroupKPI: groupName.value,
})
.then(() => {
fetchData();
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
async function editData(id: string) {
await http
.put(config.API.kpiGroupById(id), {
nameGroupKPI: groupName.value,
})
.then(() => {
fetchData();
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
async function deleteData(id: string) {
await http
.delete(config.API.kpiGroupById(id))
.then(() => {
fetchData();
success($q, "ลบข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/** เปลี่ยนเป็นหน้าเพิ่มข้อมูล */
function onAdd() {
modal.value = true;
}
function closeDialog() {
modal.value = false;
editStatus.value = false;
groupName.value = "";
}
function onEdit(data: any) {
modal.value = true;
editStatus.value = true;
groupName.value = data.nameGroupKPI;
editId.value = data.id;
}
async function onSubmit() {
dialogConfirm(
$q,
async () => {
editStatus.value ? editData(editId.value) : addData();
closeDialog();
},
"ยืนยันการบันทึกข้อมูล",
"ต้องการยืนยันการบันทึกข้อมูลนี้หรือไม่ ?"
);
}
/**
* function updatePagination
* @param newPagination อม Pagination ใหม
*/
function updatePagination(newPagination: NewPagination) {
formQuery.page = 1;
formQuery.pageSize = newPagination.rowsPerPage;
}
function fetchNewList() {
formQuery.page = 1;
fetchData();
}
watch(
() => formQuery.pageSize,
() => {
fetchNewList();
}
);
onMounted(async () => {
fetchData();
});
</script>
<template>
<q-toolbar style="padding: 0">
<q-btn flat round color="primary" icon="add" @click="onAdd()">
<q-tooltip> เพมขอม </q-tooltip>
</q-btn>
<q-space />
<div class="row q-gutter-sm">
<q-input
outlined
dense
v-model="formQuery.keyword"
label="ค้นหา"
@keyup.enter="fetchNewList()"
>
<template v-slot:append>
<q-icon v-if="formQuery.keyword == ''" name="search" />
<q-icon
v-if="formQuery.keyword !== ''"
name="clear"
class="cursor-pointer"
@click="(formQuery.keyword = ''), fetchNewList()"
/> </template
></q-input>
<q-select
v-model="visibleColumns"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns"
option-value="name"
options-cover
style="min-width: 150px"
/>
</div>
</q-toolbar>
<d-table
ref="table"
:columns="columns"
:rows="rows"
row-key="id"
flat
bordered
:paging="true"
dense
class="custom-header-table"
:rows-per-page-options="[10, 25, 50, 100]"
:visible-columns="visibleColumns"
@update:pagination="updatePagination"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
<q-th auto-width />
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props" class="cursor-pointer">
<q-td v-for="col in props.cols" :key="col.id">
{{ col.value }}
</q-td>
<q-td auto-width>
<q-btn
color="edit"
flat
dense
round
class="q-mr-xs"
icon="edit"
clickable
@click="onEdit(props.row)"
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<q-btn
color="red"
flat
dense
round
icon="mdi-delete"
clickable
@click.stop="
dialogRemove($q, async () => await deleteData(props.row.id))
"
v-close-popup
>
<q-tooltip>ลบขอม</q-tooltip>
</q-btn>
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
งหมด {{ total }} รายการ
<q-pagination
v-model="formQuery.page"
active-color="primary"
color="dark"
:max="Number(totalList)"
size="sm"
boundary-links
direction-links
:max-pages="5"
@update:model-value="fetchData"
></q-pagination>
</template>
</d-table>
<q-dialog v-model="modal" persistent>
<q-card flat bordered style="min-width: 50vh">
<q-form greedy @submit.prevent @validation-success="onSubmit">
<dialog-header
:tittle="editStatus ? 'แก้ไขกลุ่มงาน' : 'เพิ่มกลุ่มงาน'"
:close="closeDialog"
/>
<q-separator />
<q-card-section>
<q-input
label="กลุ่มงาน"
v-model="groupName"
outlined
dense
class="inputgreen"
:rules="[(val:string) => !!val || `${'กรุณากรอกกลุ่มงาน'}`,]"
hide-bottom-space
/>
</q-card-section>
<q-separator />
<q-card-actions align="right" class="bg-white text-teal">
<q-btn
type="submit"
for="#submitForm"
unelevated
dense
class="q-px-md items-center"
color="public"
label="บันทึก"
/>
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
</template>

View file

@ -1,586 +0,0 @@
<script setup lang="ts">
import { ref, onMounted, reactive, watch } from "vue";
import type { QTableProps } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useQuasar } from "quasar";
import { useRouter } from "vue-router";
import Header from "@/components/DialogHeader.vue";
import type {
DataOption,
NewPagination,
} from "@/modules/01_metadata/interface/index/Main";
import http from "@/plugins/http";
import config from "@/app.config";
const total = ref<number>();
const id = ref<string>("");
const modal = ref<boolean>(false);
const rows = ref<any>([]);
const editStatus = ref<boolean>(false);
const groupName = ref<any>();
const position = ref<any>();
const competency = ref<any>();
const groupNameOp = ref<DataOption[]>([]);
const groupNameOpMain = ref<DataOption[]>([]);
const positionOp = ref<DataOption[]>([]);
const positionMainOp = ref<DataOption[]>([]);
const competencyOp = ref<DataOption[]>([]);
const competencyOpMain = ref<DataOption[]>([]);
const columns = ref<QTableProps["columns"]>([
{
name: "groupName",
align: "left",
label: "กลุ่มงาน",
sortable: true,
field: "groupName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "positions",
align: "left",
label: "ตำแหน่ง",
sortable: true,
field: "positions",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "capacitys",
align: "left",
label: "สมรรถนะประจำกลุ่มงาน",
sortable: true,
field: "capacitys",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const $q = useQuasar();
const mixin = useCounterMixin();
const {
dialogRemove,
messageError,
showLoader,
hideLoader,
success,
dialogConfirm,
} = mixin;
const competencyType = ref<string>("ID1");
const filterKeyword = ref<string>("");
const visibleColumns = ref<string[]>(["groupName", "positions", "capacitys"]);
const formQuery = reactive({
page: 1,
pageSize: 10,
keyword: "",
});
const totalList = ref<number>(1); //
/** ดึงข้อมูล */
async function getData() {
showLoader();
http
.get(
config.API.kpiLink +
`?page=${formQuery.page}&pageSize=${formQuery.pageSize}&keyword=${formQuery.keyword}`
)
.then((res) => {
total.value = res.data.result.total;
const data = res.data.result;
totalList.value = Math.ceil(res.data.result.total / formQuery.pageSize);
rows.value = data.data;
})
.finally(() => {
hideLoader();
});
}
async function deleteData(id: string) {
await http
.delete(config.API.kpiLink + `/${id}`)
.then(() => {
success($q, "ลบข้อมูลสำเร็จ");
close();
getData();
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/** ดึงข้อมูล */
async function getListGroup() {
showLoader();
await http
.get(config.API.kpiGroup + `?pageSize=50`)
.then(async (res) => {
const dataOp = res.data.result.data;
const uniqueNames = new Set();
const filteredData = dataOp
.filter((item: any) => {
if (!uniqueNames.has(item.id)) {
uniqueNames.add(item.nameGroupKPI);
return true;
}
return false;
})
.map((item: any) => ({
id: item.id,
name: item.nameGroupKPI,
}));
groupNameOpMain.value = filteredData;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/** ดึงข้อมูล */
async function getCompetency() {
showLoader();
await http
.get(config.API.kpiCapacity + `?type=GROUP&pageSize=50`)
.then(async (res) => {
const dataOp = res.data.result.data;
const uniqueNames = new Set();
const filteredData = dataOp
.filter((item: any) => {
if (!uniqueNames.has(item.id)) {
uniqueNames.add(item.name);
return true;
}
return false;
})
.map((item: any) => ({
id: item.id,
name: item.name,
}));
competencyOpMain.value = filteredData;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/** เปลี่ยนเป็นหน้าเพิ่มข้อมูล */
function onAdd() {
getOptions();
getListGroup();
getCompetency();
modal.value = true;
}
async function onEdit(data: any) {
id.value = data;
await getOptions();
await getListGroup();
await getCompetency();
await getDataEdit(id.value);
modal.value = true;
editStatus.value = true;
}
function getDataEdit(id: string) {
showLoader();
http
.get(config.API.kpiLink + `/${id}`)
.then((res) => {
const data = res.data.result;
groupName.value = {
id: data.groupId,
name: data.groupName,
};
position.value = data.positions.map((i: any) => i.name);
competency.value = data.capacitys.map((i: any) => ({
id: i.id,
name: i.name,
}));
})
.finally(() => {
hideLoader();
});
}
function onSubmit() {
const url = editStatus.value
? config.API.kpiLink + `/${id.value}`
: config.API.kpiLink;
const body = {
kpiGroupId: groupName.value.id,
positions: position.value,
kpiCapacityIds: competency.value.map((i: any) => i.id),
};
dialogConfirm($q, () => {
http[editStatus.value ? "put" : "post"](url, body)
.then(() => {
success($q, "บันทึกสำเร็จ");
close();
getData();
})
.finally(() => {});
});
}
function close() {
modal.value = false;
editStatus.value = false;
groupName.value = "";
position.value = null;
competency.value = null;
}
function getOptions() {
http.get(config.API.orgSalaryPosition).then((res) => {
const dataOp = res.data.result;
const uniqueNames = new Set();
const filteredData = dataOp
.filter((item: any) => {
if (!uniqueNames.has(item.positionName)) {
uniqueNames.add(item.positionName);
return true;
}
return false;
})
.map((item: any) => ({
id: item.positionName,
name: item.positionName,
}));
positionMainOp.value = filteredData;
});
}
/**
* function นหาขอมลของ Option
* @param val าทองการฟลเตอร
* @param update พเดทค
* @param refData ดาตาทองการฟลเตอร
*/
function filterOptionGroup(val: any, update: Function) {
update(() => {
groupNameOp.value = groupNameOpMain.value.filter(
(v: any) => v.name.indexOf(val) > -1
);
});
}
/**
* function นหาขอมลของ Option
* @param val าทองการฟลเตอร
* @param update พเดทค
* @param refData ดาตาทองการฟลเตอร
*/
function filterOption(val: any, update: Function) {
update(() => {
positionOp.value = positionMainOp.value.filter(
(v: any) => v.name.indexOf(val) > -1
);
});
}
/**
* function นหาขอมลของ Option
* @param val าทองการฟลเตอร
* @param update พเดทค
* @param refData ดาตาทองการฟลเตอร
*/
function filterOptionCompetency(val: any, update: Function) {
update(() => {
competencyOp.value = competencyOpMain.value.filter(
(v: any) => v.name.indexOf(val) > -1
);
});
}
/**
* function updatePagination
* @param newPagination อม Pagination ใหม
*/
function updatePagination(newPagination: NewPagination) {
formQuery.page = 1;
formQuery.pageSize = newPagination.rowsPerPage;
}
function fetchNewList() {
formQuery.page = 1;
getData();
}
watch(
() => formQuery.pageSize,
() => {
fetchNewList();
}
);
onMounted(async () => {
getData();
});
</script>
<template>
<q-toolbar style="padding: 0">
<q-btn flat round color="primary" icon="add" @click="onAdd()">
<q-tooltip> เพมขอม </q-tooltip>
</q-btn>
<q-space />
<div class="row q-gutter-sm">
<q-input
outlined
dense
v-model="formQuery.keyword"
label="ค้นหา"
@keyup.enter="fetchNewList()"
>
<template v-slot:append>
<q-icon v-if="formQuery.keyword == ''" name="search" />
<q-icon
v-if="formQuery.keyword !== ''"
name="clear"
class="cursor-pointer"
@click="(formQuery.keyword = ''), fetchNewList()"
/> </template
></q-input>
<q-select
v-model="visibleColumns"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns"
option-value="name"
options-cover
style="min-width: 150px"
>
</q-select>
</div>
</q-toolbar>
<d-table
ref="table"
:columns="columns"
:rows="rows"
row-key="id"
flat
bordered
dense
class="custom-header-table"
:visible-columns="visibleColumns"
:separator="'cell'"
:rows-per-page-options="[10, 25, 50, 100]"
@update:pagination="updatePagination"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
<q-th auto-width />
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props" class="cursor-pointer">
<q-td v-for="col in props.cols" :key="col.id" class="vertical-top">
<div v-if="col.name == 'positions'">
<div v-if="col.value.length !== 0">
<div v-for="(pos, index) in col.value" :key="pos.id">
{{ pos ? `- ${pos.name}` : "-" }}
</div>
</div>
<div v-else>-</div>
</div>
<div v-else-if="col.name == 'capacitys'">
<div v-if="col.value.length !== 0">
<div v-for="competency in col.value" :key="competency.id">
{{ competency ? `- ${competency.name}` : "-" }}
</div>
</div>
<div v-else>-</div>
</div>
<div v-else>
{{ col.value ? col.value : "-" }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="edit"
flat
dense
round
class="q-mr-xs"
icon="edit"
clickable
@click="onEdit(props.row.id)"
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<q-btn
color="red"
flat
dense
round
icon="mdi-delete"
clickable
@click.stop="
dialogRemove($q, async () => await deleteData(props.row.id))
"
v-close-popup
>
<q-tooltip>ลบขอม</q-tooltip>
</q-btn>
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
งหมด {{ total }} รายการ
<q-pagination
v-model="formQuery.page"
active-color="primary"
color="dark"
:max="Number(totalList)"
size="sm"
boundary-links
direction-links
:max-pages="5"
@update:model-value="getData"
></q-pagination>
</template>
</d-table>
<q-dialog v-model="modal" persistent>
<q-card flat bordered style="min-width: 80vh">
<q-form greedy @submit.prevent @validation-success="onSubmit">
<Header
:tittle="
editStatus ? 'แก้ไขกลุ่มงานและตำแหน่ง' : 'เพิ่มกลุ่มงานและตำแหน่ง'
"
:close="close"
/>
<q-separator />
<q-card-section>
<div class="row q-col-gutter-sm">
<div class="col-4">
<q-select
dense
v-model="groupName"
label="กลุ่มงาน"
outlined
class="inputgreen"
map-options
option-label="name"
option-value="id"
:options="groupNameOp"
use-input
@filter="(inputValue:any,doneFn:Function) => filterOptionGroup(inputValue, doneFn) "
hide-bottom-space
lazy-rules
:rules="[(val:string) => !!val || `${'กรุณาเลือกกลุ่มงาน'}`,]"
>
<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-4">
<q-select
dense
v-model="position"
label="ตำแหน่ง"
outlined
multiple
emit-value
map-options
class="inputgreen"
option-label="name"
option-value="name"
:options="positionOp"
:rules="[(val:string) => !!val || `${'กรุณาเลือกตำแหน่ง'}`,]"
hide-bottom-space
lazy-rules
use-input
@filter="(inputValue:any,doneFn:Function) => filterOption(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-4">
<q-select
dense
class="inputgreen"
v-model="competency"
label="สมรรถนะประจำกลุ่ม"
outlined
multiple
map-options
option-label="name"
option-value="id"
:rules="[(val:string) => !!val || `${'กรุณาเลือกสมรรถนะประจำกลุ่ม'}`,]"
hide-bottom-space
lazy-rules
:options="competencyOp"
use-input
@filter="(inputValue:any,doneFn:Function) => filterOptionCompetency(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>
</q-card-section>
<q-separator />
<q-card-actions align="right" class="bg-white text-teal">
<q-btn
type="submit"
for="#submitForm"
unelevated
dense
class="q-px-md items-center"
color="public"
label="บันทึก"
/>
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
</template>

View file

@ -1,153 +0,0 @@
<script setup lang="ts">
import { ref, reactive, onMounted, watch } from "vue";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
import config from "@/app.config";
import { useQuasar } from "quasar";
const $q = useQuasar();
const dataLevel = ref<any>();
const { showLoader, hideLoader, success } = useCounterMixin();
const fieldLabels = {
score5: "5",
score4: "4",
score3: "3",
score2: "2",
score1: "1",
};
const formScore = reactive<any>({
score5: "",
score4: "",
score3: "",
score2: "",
score1: "",
});
interface FormScore {
score5: string;
score4: string;
score3: string;
score2: string;
score1: string;
[key: string]: any;
}
function onSubmit() {
const body = {
formScore: dataLevel.value.map((item: any) => {
const { level, ...rest } = item;
return rest;
}),
};
http
.put(config.API.kpiEvaluation, body.formScore)
.then((res) => {
success($q, "บันทึกสำเร็จ");
})
.finally(() => {});
}
function getData() {
showLoader();
http
.get(config.API.kpiEvaluation)
.then((res) => {
dataLevel.value = res.data.result.data;
})
.finally(() => {
hideLoader();
});
}
onMounted(() => {
getData();
});
</script>
<template>
<q-card flat bordered>
<q-form greedy @submit.prevent @validation-success="onSubmit">
<q-card-section class="bg-grey-3 q-pa-sm">
<div class="row text-dark text-body2 text-weight-medium">
<div class="text-center col-8">เกณฑการประเม</div>
<div class="text-center col-4">ระดบคะแนน</div>
</div>
</q-card-section>
<q-card-section class="q-pa-none">
<div v-for="(field, index) in dataLevel" :key="field.id">
<div class="row q-pa-sm">
<div class="col-8 text-left">
<q-field
class="q_field_p_none"
ref="fieldRef"
v-model="field.description"
label-slot
borderless
:rules="[(val) => !!val || 'กรุณากรอกมาตรฐานพฤติกรรม']"
hide-bottom-space
>
<template #control>
<q-editor
class="full-width"
v-model="field.description"
:dense="$q.screen.lt.md"
min-height="5rem"
:toolbar="[
[
'bold',
'italic',
'strike',
'underline',
'subscript',
'superscript',
],
['unordered', 'ordered'],
]"
:fonts="{
arial: 'Arial',
arial_black: 'Arial Black',
comic_sans: 'Comic Sans MS',
courier_new: 'Courier New',
impact: 'Impact',
lucida_grande: 'Lucida Grande',
times_new_roman: 'Times New Roman',
verdana: 'Verdana',
}"
/>
</template>
</q-field>
<!-- <q-input
v-model="formScore[field]"
dense
outlined
class="inputgreen"
label="กรอกข้อความเพื่อไว้ใช้อ้างอิงเท่านั้น"
:rules="[(val:string) => !!val || `${'กรุณากรอกข้อความเพื่อไว้ใช้อ้างอิงเท่านั้น'}`,]"
hide-bottom-space
/> -->
</div>
<div
class="col-4 text-center text-body1 text-weight-bold self-center"
>
{{ field.level }}
</div>
</div>
<div
class="col-12"
v-if="index !== Object.keys(fieldLabels).length - 1"
>
<q-separator />
</div>
</div>
</q-card-section>
<q-card-actions align="right" class="bg-white text-teal">
<q-btn label="บันทึก" color="secondary" type="submit"
><q-tooltip>นทกขอม</q-tooltip></q-btn
>
</q-card-actions>
</q-form>
</q-card>
</template>

View file

@ -1,328 +0,0 @@
<script setup lang="ts"></script>
<template>
<div class="display-table">
<q-card flat bordered class="q-mb-lg">
<q-card-section>
<div class="text-h6 text-bold">ประเภทสมรรถนะ</div>
</q-card-section>
<q-card-section class="q-pt-none">
ใหประเมนจากสมรรถนะทเกยวของกบการปฏราชการตามท .. กำหนด
รายละเอยดดงน
</q-card-section>
<q-separator inset />
<div style="border: 1px solid black">
<div class="row text-center" style="background-color: #e0e4f4">
<div class="col-3 text-bold flex justify-center items-center">
ประเภทสมรรถนะ
</div>
<div class="col-5">
<div class="row text-bold flex justify-center">
ประเภทและระดบตำแหน
</div>
<div class="row">
<div class="col-3">
<div class="text-bold">วไป</div>
<div>ปฏงาน</div>
<div>ชำนาญงาน</div>
<div>อาวโส</div>
</div>
<div class="col-3">
<div class="text-bold">ชาการ</div>
<div>ปฏการ</div>
<div>ชำนาญการ</div>
<div>ชำนาญการพเศษ</div>
<div>เชยวชาญ</div>
<div>ทรงคณว</div>
</div>
<div class="col-3">
<div class="text-bold">อำนวยการ</div>
<div> </div>
</div>
<div class="col-3">
<div class="text-bold">บรหาร</div>
<div> </div>
</div>
</div>
</div>
<div class="col-4 column">
<div class="row text-bold flex justify-center">ดำรงตำแหน</div>
<div class="row" style="flex-grow: 1">
<div class="col-6">
ตรวจราชการกรงเทพมหานครและผตรวจราชการ
</div>
<div class="col-6 flex justify-center">อำนวยการเขต</div>
</div>
</div>
</div>
<div class="row">
<div class="col-3 q-pa-sm">
<div class="text-bold">สมรรถนะหล</div>
<div>(5 สมรรถนะ)</div>
</div>
<div class="col-5 column">
<div class="row col-grow">
<div class="col-3 flex items-center justify-center">
<q-icon name="check" size="32px" />
</div>
<div class="col-3 flex items-center justify-center">
<q-icon name="check" size="32px" />
</div>
<div class="col-3 flex items-center justify-center">
<q-icon name="check" size="32px" />
</div>
<div class="col-3 flex items-center justify-center">
<q-icon name="check" size="32px" />
</div>
</div>
</div>
<div class="col-4 column">
<div class="row col-grow">
<div class="col-6 flex items-center justify-center">
<q-icon name="check" size="32px" />
</div>
<div class="col-6 flex items-center justify-center">
<q-icon name="check" size="32px" />
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-3 q-pa-sm">
<div class="text-bold">สมรรถนะประจำกลมงาน</div>
<div>(3 สมรรถนะ ตามกลมงาน)</div>
</div>
<div class="col-5 column">
<div class="row col-grow">
<div class="col-3 flex items-center justify-center">
<q-icon name="check" size="32px" />
</div>
<div class="col-3 flex items-center justify-center">
<q-icon name="check" size="32px" />
</div>
<div class="col-3"></div>
<div class="col-3"></div>
</div>
</div>
<div class="col-4 column">
<div class="row col-grow">
<div class="col-6"></div>
<div class="col-6"></div>
</div>
</div>
</div>
<div class="row">
<div class="col-3 q-pa-sm">
<div class="text-bold">สมรรถนะประจำผบรหารกรงเทพมหานคร</div>
<div>(7 สมรรถนะ)</div>
</div>
<div class="col-5 column">
<div class="row col-grow">
<div class="col-3"></div>
<div class="col-3"></div>
<div class="col-3 flex items-center justify-center">
<q-icon name="check" size="32px" />
</div>
<div class="col-3 flex items-center justify-center">
<q-icon name="check" size="32px" />
</div>
</div>
</div>
<div class="col-4 column">
<div class="row col-grow">
<div class="col-6"></div>
<div class="col-6"></div>
</div>
</div>
</div>
<div class="row">
<div class="col-3 q-pa-sm">
<div class="text-bold">สมรรถนะเฉพาะสำหรบตำแหนงผอำนวยการเขต</div>
<div>(4 สมรรถนะ)</div>
</div>
<div class="col-5 column">
<div class="row col-grow">
<div class="col-3"></div>
<div class="col-3"></div>
<div class="col-3"></div>
<div class="col-3"></div>
</div>
</div>
<div class="col-4 column">
<div class="row col-grow">
<div class="col-6"></div>
<div class="col-6 flex items-center justify-center">
<q-icon name="check" size="32px" />
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-3 q-pa-sm">
<div class="text-bold">
สมรรถนะเฉพาะสำหรบตำแหนงผตรวจราชการกรงเทพมหานครและผตรวจราชการ
</div>
<div>(2 สมรรถนะ)</div>
</div>
<div class="col-5 column">
<div class="row col-grow">
<div class="col-3"></div>
<div class="col-3"></div>
<div class="col-3"></div>
<div class="col-3"></div>
</div>
</div>
<div class="col-4 column">
<div class="row col-grow">
<div class="col-6 flex items-center justify-center">
<q-icon name="check" size="32px" />
</div>
<div class="col-6"></div>
</div>
</div>
</div>
<div class="row text-bold">
<div class="col-3 q-pa-sm">
<div class="text-bold flex justify-end">รวมสมรรถนะ</div>
</div>
<div class="col-5 column">
<div class="row col-grow">
<div class="col-3 flex justify-center items-center">8</div>
<div class="col-3 flex justify-center items-center">8</div>
<div class="col-3 flex justify-center items-center">12</div>
<div class="col-3 flex justify-center items-center">12</div>
</div>
</div>
<div class="col-4 column">
<div class="row col-grow">
<div class="col-6 flex justify-center items-center">7</div>
<div class="col-6 flex justify-center items-center">9</div>
</div>
</div>
</div>
</div>
</q-card>
<q-card flat bordered>
<q-card-section>
<div class="text-h6 text-bold">ระดบสมรรถนะ</div>
</q-card-section>
<q-card-section class="q-pt-none">
สมรรถนะหลกและสมรรถนะประจำกลมงาน
กำหนดระดบสมรรถนะทคาดหวงจำแนกตามประเภทและระดบตำแหนงของขาราชการกรงเทพมหานครสาม
รายละเอยดดงน
</q-card-section>
<q-separator inset />
<div style="border: 1px solid black">
<div
class="row text-bold text-center"
style="background-color: #c0d4ec"
>
<div class="col-3">ประเภทตำแหน</div>
<div class="col-3">ระดบตำแหน</div>
<div class="col-3">สมรรถนะหล</div>
<div class="col-3">สมรรถนะประจำกลมงาน</div>
</div>
<div class="row text-center">
<div class="col-3 flex justify-center items-center">บรหาร</div>
<div class="col-6">
<div class="row">
<div class="col-6"></div>
<div class="col-6">5</div>
</div>
<div class="row">
<div class="col-6"></div>
<div class="col-6">4</div>
</div>
</div>
<div class="col-3" style="background-color: #bcbcc4"></div>
</div>
<div class="row text-center">
<div class="col-3 flex justify-center items-center">อำนวยการ</div>
<div class="col-6">
<div class="row">
<div class="col-6"></div>
<div class="col-6">4</div>
</div>
<div class="row">
<div class="col-6"></div>
<div class="col-6">3</div>
</div>
</div>
<div class="col-3" style="background-color: #bcbcc4"></div>
</div>
<div class="row text-center">
<div class="col-3 flex justify-center items-center">ชาการ</div>
<div class="col-9">
<div class="row">
<div class="col-4">ทรงคณว</div>
<div class="col-4">5</div>
<div class="col-4">5</div>
</div>
<div class="row">
<div class="col-4">เชยวชาญ</div>
<div class="col-4">4</div>
<div class="col-4">4</div>
</div>
<div class="row">
<div class="col-4">ชำนาญการพเศษ</div>
<div class="col-4">3</div>
<div class="col-4">4</div>
</div>
<div class="row">
<div class="col-4">ชำนาญการ</div>
<div class="col-4">2</div>
<div class="col-4">3</div>
</div>
<div class="row">
<div class="col-4">ปฏการ</div>
<div class="col-4">1</div>
<div class="col-4">2</div>
</div>
</div>
</div>
<div class="row text-center">
<div class="col-3 flex justify-center items-center">วไป</div>
<div class="col-9">
<div class="row">
<div class="col-4">กษะพเศษ</div>
<div class="col-4">4</div>
<div class="col-4">4</div>
</div>
<div class="row">
<div class="col-4">อาวโส</div>
<div class="col-4">3</div>
<div class="col-4">3</div>
</div>
<div class="row">
<div class="col-4">ชำนาญงาน</div>
<div class="col-4">2</div>
<div class="col-4">2</div>
</div>
<div class="row">
<div class="col-4">ปฏงาน</div>
<div class="col-4">1</div>
<div class="col-4">1</div>
</div>
</div>
</div>
</div>
</q-card>
</div>
</template>
<style scoped lang="scss">
.display-table {
& .row:not(:last-child) {
border-bottom: 1px solid black;
}
& [class^="col-"]:not(:last-child) {
border-right: 1px solid black;
}
}
</style>

View file

@ -1,121 +0,0 @@
<script setup lang="ts">
import { ref, reactive } from "vue";
import { useRouter } from "vue-router";
import Main from "@/modules/01_metadata/components/competency/Forms/Main.vue";
// import FormMain from "@/modules/14_KPI/components/competency/Forms/01_FormMain.vue";
// import FormGroup from "@/modules/14_KPI/components/competency/Forms/02_FormGroup.vue";
// import FormExecutive from "@/modules/14_KPI/components/competency/Forms/03_FormExecutive.vue";
// import FormExecutivePosition from "@/modules/14_KPI/components/competency/Forms/04_FormExecutivePosition.vue";
// import FormExecutiveLevel from "@/modules/14_KPI/components/competency/Forms/05_FormExecutiveLevel.vue";
import { useKPIDataStore } from "@/modules/01_metadata/stores/KPIStore";
import type { DataOption } from "@/modules/01_metadata/interface/index/Main";
import type { FormCompetency } from "@/modules/01_metadata/interface/request/Main";
const router = useRouter();
const store = useKPIDataStore();
const formData = reactive<FormCompetency>({
competencyType: "",
competencyName: "",
definition: "",
level_1: ["", "", "", "", "", ""],
level_2: "",
level_3: "",
level_4: "",
level_5: "",
evaluation: "",
});
const competencyTypeOp = ref<DataOption[]>([
{
id: "HEAD",
name: "สมรรถนะหลัก",
},
{
id: "GROUP",
name: "สมรรถนะประจำกลุ่มงาน",
},
{
id: "EXECUTIVE",
name: "สมรรถนะประจำผู้บริหารกรุงเทพมหานคร",
},
{
id: "DIRECTOR",
name: "สมรรถนะเฉพาะสำหรับตำแหน่ง ผอ.เขต ผช.ผอ.เขต และหัวหน้าฝ่ายในสังกัด สนง.เขต",
},
{
id: "INSPECTOR",
name: "สมรรถนะเฉพาะสำหรับตำแหน่งผู้ตรวจราชการ กทม. และผู้ตรวจราชการ",
},
]);
const itemsFormCard = ref<any>([
{
id: "",
name: "",
},
]);
function ocClickAdd() {
if (itemsFormCard.value.length !== 6) {
const data = {
id: "",
name: "",
};
itemsFormCard.value.push(data);
}
}
/** บันทึก */
function onSubmit() {
console.log(formData);
}
</script>
<template>
<div>
<q-btn
icon="mdi-arrow-left"
unelevated
round
dense
flat
color="primary"
class="q-mr-sm"
@click="router.go(-1)"
/>
<span class="toptitle text-dark">เพ/แกไขสมรรถนะ</span>
</div>
<q-card flat bordered>
<!-- @submit.prevent @validation-success="onSubmit" -->
<!-- <q-form greedy> -->
<q-card-section>
<div class="row q-col-gutter-sm">
<div class="col-12">
<q-select
v-model="store.competencyTypeVal"
outlined
label="เลือกประเภทสมรรถนะ"
dense
option-label="name"
option-value="id"
:options="competencyTypeOp"
emit-value
map-options
:rules="[(val:string) => !!val || `${'กรุณาเลือกประเภทสมรรถนะ'}`,]"
hide-bottom-space
/>
</div>
<Main />
<!-- <FormMain v-if="store.competencyType === 'ID1'" />
<FormGroup v-else-if="store.competencyType === 'ID2'" />
<FormExecutive v-else-if="store.competencyType === 'ID3'" />
<FormExecutivePosition v-else-if="store.competencyType === 'ID4'" />
<FormExecutiveLevel v-else-if="store.competencyType === 'ID5'" /> -->
</div>
</q-card-section>
</q-card>
</template>

View file

@ -1,205 +0,0 @@
<script setup lang="ts">
import { reactive } from "vue";
import { useCounterMixin } from "@/stores/mixin";
import { useKPIDataStore } from "@/modules/01_metadata/stores/KPIStore";
import { useRouter } from "vue-router";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
const $q = useQuasar();
const mixin = useCounterMixin();
const { dialogConfirm, showLoader, hideLoader, success, messageError } = mixin;
const router = useRouter();
const store = useKPIDataStore();
const formData = reactive({
competencyType: "",
competencyName: "",
definition: "",
levels: [
{
level: "1",
description: "",
},
],
evaluation: "",
});
function ocClickAdd() {
if (formData.levels.length !== 6) {
const levelName = formData.levels.length + 1;
const data = {
level: levelName.toString(),
description: "",
};
formData.levels.push(data);
}
}
function onSubmit() {
dialogConfirm($q, () => {
const body = {
competencyType: store.competencyTypeVal,
competencyName: formData.competencyName,
definition: formData.definition,
levels: formData.levels,
evaluation: formData.evaluation,
};
// showLoader()
// http
// .put(config.API.???,body)
// .then((res)=>{
// success($q,'')
// router.push(`/KPI-competency`)
// }).catch((e)=>{
// messageError($q,e)
// }).finally(()=>{
// hideLoader()
// })
console.log(body);
});
}
</script>
<template>
<q-form greedy @submit.prevent @validation-success="onSubmit" class="col-12">
<div class="row q-col-gutter-sm">
<div class="col-12">
<q-input
v-model="formData.competencyName"
dense
outlined
label="ชื่อสมรรถนะ"
:rules="[(val:string) => !!val || `${'กรุณากรอกชื่อสมรรถนะ'}`,]"
hide-bottom-space
/>
</div>
<div class="col-12">
<q-input
v-model="formData.definition"
label="คำจำกัดความ"
dense
type="textarea"
outlined
:rules="[(val:string) => !!val || `${'กรุณากรอกคำจำกัดความ'}`,]"
hide-bottom-space
/>
</div>
<div class="col-12">
<q-card flat bordered>
<q-card-section class="bg-grey-4">
<div
class="row items-center text-dark text-body2 text-weight-medium"
>
<div class="col-3">
<div class="row items-center">
<div class="col-1">
<q-btn
dense
flat
round
color="primary"
icon="add"
@click="ocClickAdd"
>
<q-tooltip>เพ</q-tooltip></q-btn
>
</div>
<div class="col-11 text-center">
<span>ระด</span>
</div>
</div>
</div>
<div class="col-4">
<span>คำอธบายระด</span>
</div>
</div>
</q-card-section>
<q-card-section>
<div
class="row q-pa-sm"
v-for="(items, index) in formData.levels"
key="index"
>
<div
class="col-3 text-center self-center text-body1 text-weight-medium"
>
<span>{{ items.level }}</span>
</div>
<div class="col-9">
<q-field
class="q_field_p_none"
ref="fieldRef"
v-model="formData.levels[index].description"
label-slot
borderless
:rules="[(val) => !!val || 'กรุณากรอกมาตรฐานพฤติกรรม']"
hide-bottom-space
>
<template #control>
<q-editor
class="full-width"
v-model="formData.levels[index].description"
:dense="$q.screen.lt.md"
min-height="5rem"
:toolbar="[
[
'bold',
'italic',
'strike',
'underline',
'subscript',
'superscript',
],
['unordered', 'ordered'],
]"
:fonts="{
arial: 'Arial',
arial_black: 'Arial Black',
comic_sans: 'Comic Sans MS',
courier_new: 'Courier New',
impact: 'Impact',
lucida_grande: 'Lucida Grande',
times_new_roman: 'Times New Roman',
verdana: 'Verdana',
}"
/>
</template>
</q-field>
</div>
</div>
</q-card-section>
</q-card>
</div>
<div class="col-12">
<q-input
v-model="formData.evaluation"
label="กำหนดเกณฑ์การประเมิน"
dense
type="textarea"
outlined
/>
</div>
<div class="col-12"><q-separator /></div>
<div class="col-12 row justify-end">
<q-btn
dense
unelevated
label="บันทึก"
color="public"
class="q-px-md"
type="submit"
>
<q-tooltip>นทกขอม</q-tooltip>
</q-btn>
</div>
</div>
</q-form>
</template>
<style scoped></style>

View file

@ -1,204 +0,0 @@
<script setup lang="ts">
import { ref, reactive } from "vue";
import { useCounterMixin } from "@/stores/mixin";
import { useKPIDataStore } from "@/modules/01_metadata/stores/KPIStore";
import { useRouter } from "vue-router";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
const $q = useQuasar();
const mixin = useCounterMixin();
const { dialogConfirm, showLoader, hideLoader, success, messageError } = mixin;
const router = useRouter;
const store = useKPIDataStore();
interface DetailLevelType {
level_01: any;
level_02: any;
level_03: any;
level_04: any;
level_05: any;
}
interface FormGroup {
name: string;
definition: string;
detailLevel: DetailLevelType[];
evaluation: string;
}
const fieldLabels = {
score1: "1",
score2: "2",
score3: "3",
score4: "4",
score5: "5",
};
const formScore = reactive<any>({
score1: "",
score2: "",
score3: "",
score4: "",
score5: "",
});
const formData = reactive<FormGroup>({
name: "",
definition: "",
detailLevel: [],
evaluation: "",
});
function onSubmit() {
dialogConfirm($q, () => {
const body = {
competencyType: store.competencyTypeVal,
competencyName: formData.definition,
definition: formData.definition,
levels1: formScore.score1,
levels2: formScore.score2,
levels3: formScore.score3,
levels4: formScore.score4,
levels5: formScore.score5,
evaluation: formData.evaluation,
};
// showLoader()
// http
// .put(config.API.???,body)
// .then((res)=>{
// success($q,'')
// router.push(`/KPI-competency`)
// }).catch((e)=>{
// messageError($q,e)
// }).finally(()=>{
// hideLoader()
// })
console.log(body);
});
}
</script>
<template>
<q-form greedy @submit.prevent @validation-success="onSubmit" class="col-12">
<div class="row q-col-gutter-sm">
<div class="col-12">
<q-input
label="ชื่อสมรรถนะ"
outlined
v-model="formData.name"
dense
:rules="[(val:string) => !!val || `${'กรุณากรอกชื่อสมรรถนะ'}`,]"
hide-bottom-space
/>
</div>
<div class="col-12">
<q-input
label="คำจำกัดความ"
outlined
v-model="formData.definition"
dense
type="textarea"
:rules="[(val:string) => !!val || `${'กรุณากรอกคำจำกัดความ'}`,]"
hide-bottom-space
/>
</div>
<div class="col-12">
<q-card flat bordered>
<q-card-section class="bg-grey-4 q-pa-sm">
<div class="row text-dark text-body2 text-weight-medium">
<div class="text-center col-4">ระด</div>
<div class="col-8">มาตรฐานพฤตกรรม</div>
</div>
</q-card-section>
<q-card-section class="q-pa-none">
<div
v-for="(field, index) in Object.keys(fieldLabels)"
:key="index + 1"
>
<div class="row q-pa-sm">
<div
class="col-4 text-center text-body1 text-weight-bold self-center"
>
{{ fieldLabels[field as keyof typeof fieldLabels] }}
</div>
<div class="col-8 text-left">
<q-field
class="q_field_p_none"
ref="fieldRef"
v-model="formScore[field]"
label-slot
borderless
:rules="[(val) => !!val || 'กรุณากรอกมาตรฐานพฤติกรรม']"
hide-bottom-space
>
<template #control>
<q-editor
class="full-width"
v-model="formScore[field]"
:dense="$q.screen.lt.md"
min-height="5rem"
:toolbar="[
[
'bold',
'italic',
'strike',
'underline',
'subscript',
'superscript',
],
['unordered', 'ordered'],
]"
:fonts="{
arial: 'Arial',
arial_black: 'Arial Black',
comic_sans: 'Comic Sans MS',
courier_new: 'Courier New',
impact: 'Impact',
lucida_grande: 'Lucida Grande',
times_new_roman: 'Times New Roman',
verdana: 'Verdana',
}"
/>
</template>
</q-field>
</div>
</div>
<div
class="col-12"
v-if="index !== Object.keys(fieldLabels).length - 1"
>
<q-separator />
</div>
</div>
</q-card-section>
</q-card>
</div>
<div class="col-12">
<q-input
v-model="formData.evaluation"
label="กำหนดเกณฑ์การประเมิน"
dense
type="textarea"
outlined
/>
</div>
<div class="col-12"><q-separator /></div>
<div class="col-12 row justify-end">
<q-btn
dense
unelevated
label="บันทึก"
color="public"
class="q-px-md"
type="submit"
>
<q-tooltip>นทกขอม</q-tooltip>
</q-btn>
</div>
</div>
</q-form>
</template>

View file

@ -1,321 +0,0 @@
<script setup lang="ts">
import { ref, reactive, onMounted } from "vue";
import { useCounterMixin } from "@/stores/mixin";
import { useKPIDataStore } from "@/modules/01_metadata/stores/KPIStore";
import { useRouter } from "vue-router";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
const $q = useQuasar();
const { dialogConfirm, showLoader, success, hideLoader, messageError } =
useCounterMixin();
const router = useRouter;
const store = useKPIDataStore();
const formData = reactive({
competencyType: "",
competencyName: "",
definition: "",
level: ["", "", "", "", "", ""],
form: [
{
posType: "",
posLevel: "",
description: "",
description2: "",
},
],
evaluation: "",
});
const dataLevel = ref<any>([]);
const typeOp = ref<any>([]);
const levelOp = ref<any>([]);
const typeOpsMain = ref<any>([]);
const levelOpsMain = ref<any>([]);
function ocClickAdd() {
if (formData.form.length !== 6) {
const data = {
posType: "",
posLevel: "",
description: "",
description2: "",
};
formData.form.push(data);
}
}
/** function เรียกรายการประเภทตำแหน่ง */
function fetchType() {
showLoader();
http
.get(config.API.orgPosType)
.then((res) => {
const data = res.data.result;
dataLevel.value = data;
typeOpsMain.value = data.map((e: any) => ({
id: e.id,
name: e.posTypeName,
}));
typeOp.value = typeOpsMain.value;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
function updateSelectType(val: string, index: number) {
const listLevel = dataLevel.value.find((e: any) => e.id === val);
levelOpsMain.value = listLevel.posLevels.map((e: any) => ({
id: e.id,
name: e.posLevelName,
}));
levelOp.value = levelOpsMain.value;
formData.form[index].posLevel = "";
}
function onSubmit() {
dialogConfirm($q, () => {
const body = {
competencyType: store.competencyTypeVal,
competencyName: formData.competencyName,
definition: formData.definition,
postype: formData.form,
evaluation: formData.evaluation,
};
// showLoader()
// http
// .put(config.API.???,body)
// .then((res)=>{
// success($q,'')
// router.push(`/KPI-competency`)
// }).catch((e)=>{
// messageError($q,e)
// }).finally(()=>{
// hideLoader()
// })
console.log(body);
});
}
onMounted(() => {
fetchType();
});
</script>
<template>
<q-form greedy @submit.prevent @validation-success="onSubmit" class="col-12">
<div class="row q-col-gutter-sm">
<div class="col-12">
<q-input
v-model="formData.competencyName"
dense
outlined
label="ชื่อสมรรถนะ"
:rules="[(val:string) => !!val || `${'กรุณากรอกชื่อสมรรถนะ'}`,]"
hide-bottom-space
/>
</div>
<div class="col-12">
<q-input
v-model="formData.definition"
label="คำจำกัดความ"
dense
type="textarea"
outlined
:rules="[(val:string) => !!val || `${'กรุณากรอกคำจำกัดความ'}`,]"
hide-bottom-space
/>
</div>
<div class="col-12">
<q-card flat bordered>
<q-card-section class="bg-grey-4">
<div
class="row items-center text-dark text-body2 text-weight-medium"
>
<div class="col-3">
<div class="row items-center">
<div class="col-1">
<q-btn
dense
flat
round
color="primary"
icon="add"
@click="ocClickAdd"
>
<q-tooltip>เพ</q-tooltip></q-btn
>
</div>
<div class="col-11 text-center">
<span>ประเภทตำแหน</span>
</div>
</div>
</div>
<div class="col-3 text-center">
<span>ระด</span>
</div>
<div class="col-6">
<span>มาตรฐานพฤตกรรม</span>
</div>
</div>
</q-card-section>
<q-card-section>
<div
class="row q-pa-sm q-col-gutter-sm"
v-for="(items, index) in formData.form"
key="index"
>
<div class="col-3 text-center">
<q-select
v-model="formData.form[index].posType"
outlined
label="ประเภทตำแหน่ง"
dense
option-label="name"
option-value="id"
:options="typeOp"
emit-value
map-options
:rules="[(val:string) => !!val || `${'กรุณาเลือกประเภทตำแหน่ง'}`,]"
hide-bottom-space
@update:model-value="
updateSelectType(formData.form[index].posType, index)
"
/>
</div>
<div class="col-3 text-center">
<q-select
v-model="formData.form[index].posLevel"
outlined
label="ระดับตำแหน่ง"
dense
option-label="name"
option-value="id"
:options="levelOp"
emit-value
map-options
:rules="[(val:string) => !!val || `${'กรุณาเลือกระดับตำแหน่ง'}`,]"
hide-bottom-space
/>
</div>
<div class="col-6">
<q-field
class="q_field_p_none"
ref="fieldRef"
v-model="formData.form[index].description"
label-slot
borderless
:rules="[(val) => !!val || 'กรุณากรอกมาตรฐานพฤติกรรม']"
hide-bottom-space
>
<template #control>
<q-editor
class="full-width"
v-model="formData.form[index].description"
:dense="$q.screen.lt.md"
min-height="5rem"
:toolbar="[
[
'bold',
'italic',
'strike',
'underline',
'subscript',
'superscript',
],
['unordered', 'ordered'],
]"
:fonts="{
arial: 'Arial',
arial_black: 'Arial Black',
comic_sans: 'Comic Sans MS',
courier_new: 'Courier New',
impact: 'Impact',
lucida_grande: 'Lucida Grande',
times_new_roman: 'Times New Roman',
verdana: 'Verdana',
}"
/>
</template>
</q-field>
<q-field
class="q_field_p_none"
ref="fieldRef"
v-model="formData.form[index].description2"
label-slot
borderless
:rules="[(val) => !!val || 'กรุณากรอกมาตรฐานพฤติกรรม']"
hide-bottom-space
>
<template #control>
<q-editor
class="full-width"
v-model="formData.form[index].description2"
:dense="$q.screen.lt.md"
min-height="5rem"
:toolbar="[
[
'bold',
'italic',
'strike',
'underline',
'subscript',
'superscript',
],
['unordered', 'ordered'],
]"
:fonts="{
arial: 'Arial',
arial_black: 'Arial Black',
comic_sans: 'Comic Sans MS',
courier_new: 'Courier New',
impact: 'Impact',
lucida_grande: 'Lucida Grande',
times_new_roman: 'Times New Roman',
verdana: 'Verdana',
}"
/>
</template>
</q-field>
</div>
<div class="col-12"><q-separator /></div>
</div>
</q-card-section>
</q-card>
</div>
<div class="col-12">
<q-input
v-model="formData.evaluation"
label="กำหนดเกณฑ์การประเมิน"
dense
type="textarea"
outlined
/>
</div>
<div class="col-12"><q-separator /></div>
<div class="col-12 row justify-end">
<q-btn
dense
unelevated
label="บันทึก"
color="public"
class="q-px-md"
type="submit"
>
<q-tooltip>นทกขอม</q-tooltip>
</q-btn>
</div>
</div>
</q-form>
</template>
<style scoped></style>

View file

@ -1,319 +0,0 @@
<script setup lang="ts">
import { ref, reactive } from "vue";
import type { QTableProps } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useKPIDataStore } from "@/modules/01_metadata/stores/KPIStore";
import { useRouter } from "vue-router";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
const router = useRouter();
const mixin = useCounterMixin();
const $q = useQuasar();
const mode = ref<string>("table");
const {
dialogRemove,
dialogConfirm,
showLoader,
hideLoader,
messageError,
success,
date2Thai,
} = mixin;
const store = useKPIDataStore();
const formData = reactive({
competencyType: "",
competencyName: "",
definition: "",
level1: "",
level2: "",
level3: "",
evaluation: "",
});
function onSubmit() {
dialogConfirm($q, () => {
const body = {
competencyType: store.competencyTypeVal,
competencyName: formData.competencyName,
definition: formData.definition,
levels1: formData.level1,
levels2: formData.level2,
levels3: formData.level3,
evaluation: formData.evaluation,
};
// showLoader()
// http
// .put(config.API.???,body)
// .then((res)=>{
// success($q,'')
// router.push(`/KPI-competency`)
// }).catch((e)=>{
// messageError($q,e)
// }).finally(()=>{
// hideLoader()
// })
console.log(body);
});
}
</script>
<template>
<div class="full-width">
<q-form @submit.prevent greedy @validation-success="onSubmit()">
<div class="col-12">
<q-input
outlined
v-model="formData.competencyName"
dense
label="ชื่อสมรรถนะ"
hide-bottom-space
:rules="[(val) => !!val || `${'กรุณากรอกชื่อสมรรถนะ'}`]"
/>
</div>
<q-card-section class="col-12 q-px-none">
<div>
<q-field
class="q_field_p_none"
ref="fieldRef"
v-model="formData.definition"
label-slot
borderless
:rules="[(val) => !!val || 'กรุณากรอกคำจำกัดความ']"
hide-bottom-space
>
<template #control>
<q-editor
class="full-width"
v-model="formData.definition"
:dense="$q.screen.lt.md"
min-height="7rem"
placeholder="คำจำกัดความ"
:toolbar="[
[
'bold',
'italic',
'strike',
'underline',
'subscript',
'superscript',
],
['unordered', 'ordered'],
]"
:fonts="{
arial: 'Arial',
arial_black: 'Arial Black',
comic_sans: 'Comic Sans MS',
courier_new: 'Courier New',
impact: 'Impact',
lucida_grande: 'Lucida Grande',
times_new_roman: 'Times New Roman',
verdana: 'Verdana',
}"
/>
</template>
</q-field>
</div>
</q-card-section>
<div class="col-12">
<q-card flat bordered>
<q-card-section class="bg-grey-4 q-py-sm">
<div class="row text-dark text-body2 text-weight-medium">
<div class="col-6 q-pl-xl">ระบบตำแหน</div>
<div class="col-6">
คำอธบายระด/พฤตกรรมทคาดหว/พฤตกรรมยอย
</div>
</div>
</q-card-section>
<div class="row items-center">
<q-card-section class="q-pa-none q-pl-xl col-6">
<span class="text-dark text-subtitle1 text-weight-medium">
L1 ระด วหนาฝายในสงก
</span>
</q-card-section>
<q-card-section class="q-pa-none col-6">
<div class="q-mr-md">
<q-field
ref="fieldRef"
v-model="formData.level1"
label-slot
borderless
:rules="[
(val) =>
!!val || 'กรุณาระบุคำอธิบาย L1 ระดับ หัวหน้าฝ่ายในสังกัด',
]"
hide-bottom-space
>
<template #control>
<q-editor
v-model="formData.level1"
:dense="$q.screen.lt.md"
min-height="5rem"
class="full-width"
:toolbar="[
[
'bold',
'italic',
'strike',
'underline',
'subscript',
'superscript',
],
['unordered', 'ordered'],
]"
:fonts="{
arial: 'Arial',
arial_black: 'Arial Black',
comic_sans: 'Comic Sans MS',
courier_new: 'Courier New',
impact: 'Impact',
lucida_grande: 'Lucida Grande',
times_new_roman: 'Times New Roman',
verdana: 'Verdana',
}"
/>
</template>
</q-field>
</div>
</q-card-section>
</div>
<div class="row items-center">
<q-card-section class="q-pa-none q-pl-xl col-6">
<span class="text-dark text-subtitle1 text-weight-medium">
L2 ระด วยผอำนวยการเขต
</span>
</q-card-section>
<q-card-section class="q-pa-none col-6">
<div class="q-mr-md">
<q-field
ref="fieldRef"
v-model="formData.level2"
label-slot
borderless
:rules="[
(val) =>
!!val ||
'กรุณาระบุคำอธิบาย L2 ระดับ ผู้ช่วยผู้อำนวยการเขต',
]"
hide-bottom-space
>
<template #control>
<q-editor
v-model="formData.level2"
:dense="$q.screen.lt.md"
min-height="5rem"
class="full-width"
:toolbar="[
[
'bold',
'italic',
'strike',
'underline',
'subscript',
'superscript',
],
['unordered', 'ordered'],
]"
:fonts="{
arial: 'Arial',
arial_black: 'Arial Black',
comic_sans: 'Comic Sans MS',
courier_new: 'Courier New',
impact: 'Impact',
lucida_grande: 'Lucida Grande',
times_new_roman: 'Times New Roman',
verdana: 'Verdana',
}"
/>
</template>
</q-field>
</div>
</q-card-section>
</div>
<div class="row items-center">
<q-card-section class="q-pa-none q-pl-xl col-6">
<span class="text-dark text-subtitle1 text-weight-medium">
L3 ระด อำนวยการเขต
</span>
</q-card-section>
<q-card-section class="q-pa-none col-6">
<div class="q-mr-md">
<q-field
ref="fieldRef"
v-model="formData.level3"
label-slot
borderless
:rules="[
(val) =>
!!val || 'กรุณาระบุคำอธิบาย L3 ระดับ ผู้อำนวยการเขต',
]"
hide-bottom-space
>
<template #control>
<q-editor
v-model="formData.level3"
:dense="$q.screen.lt.md"
min-height="5rem"
class="full-width"
:toolbar="[
[
'bold',
'italic',
'strike',
'underline',
'subscript',
'superscript',
],
['unordered', 'ordered'],
]"
:fonts="{
arial: 'Arial',
arial_black: 'Arial Black',
comic_sans: 'Comic Sans MS',
courier_new: 'Courier New',
impact: 'Impact',
lucida_grande: 'Lucida Grande',
times_new_roman: 'Times New Roman',
verdana: 'Verdana',
}"
/>
</template>
</q-field>
</div>
</q-card-section>
</div>
</q-card>
<div class="col-12 q-mt-md">
<q-input
v-model="formData.evaluation"
label="กำหนดเกณฑ์การประเมิน"
dense
type="textarea"
outlined
/>
</div>
<q-separator color="grey-4" />
<div class="col-12 row justify-end q-mt-md">
<q-btn
dense
unelevated
label="บันทึก"
color="public"
class="q-px-md"
type="submit"
>
<q-tooltip>นทกขอม</q-tooltip>
</q-btn>
</div>
</div>
</q-form>
</div>
</template>

View file

@ -1,261 +0,0 @@
<script setup lang="ts">
import { ref, reactive } from "vue";
import type { QTableProps } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useKPIDataStore } from "@/modules/01_metadata/stores/KPIStore";
import { useRouter } from "vue-router";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
const router = useRouter();
const mixin = useCounterMixin();
const $q = useQuasar();
const mode = ref<string>("table");
const {
dialogRemove,
dialogConfirm,
showLoader,
hideLoader,
messageError,
success,
date2Thai,
} = mixin;
const store = useKPIDataStore();
const formData = reactive({
competencyType: "",
competencyName: "",
definition: "",
level1: "",
level2: "",
evaluation: "",
});
function onSubmit() {
dialogConfirm($q, () => {
const body = {
competencyType: store.competencyTypeVal,
competencyName: formData.competencyName,
definition: formData.definition,
levels1: formData.level1,
levels2: formData.level2,
evaluation: formData.evaluation,
};
// showLoader()
// http
// .put(config.API.???,body)
// .then((res)=>{
// success($q,'')
// router.push(`/KPI-competency`)
// }).catch((e)=>{
// messageError($q,e)
// }).finally(()=>{
// hideLoader()
// })
console.log(body);
});
}
</script>
<template>
<div class="full-width">
<q-form @submit.prevent greedy @validation-success="onSubmit()">
<div class="col-12">
<q-input
outlined
v-model="formData.competencyName"
dense
hide-bottom-space
:rules="[(val) => !!val || `${'กรุณากรอกชื่อสมรรถนะ'}`]"
label="ชื่อสมรรถนะ"
/>
</div>
<q-card-section class="col-12 q-px-none">
<div>
<q-field
class="q_field_p_none"
ref="fieldRef"
v-model="formData.definition"
label-slot
borderless
:rules="[(val) => !!val || 'กรุณากรอกคำจำกัดความ']"
hide-bottom-space
>
<template #control>
<q-editor
class="full-width"
v-model="formData.definition"
:dense="$q.screen.lt.md"
min-height="7rem"
placeholder="คำจำกัดความ"
:toolbar="[
[
'bold',
'italic',
'strike',
'underline',
'subscript',
'superscript',
],
['unordered', 'ordered'],
]"
:fonts="{
arial: 'Arial',
arial_black: 'Arial Black',
comic_sans: 'Comic Sans MS',
courier_new: 'Courier New',
impact: 'Impact',
lucida_grande: 'Lucida Grande',
times_new_roman: 'Times New Roman',
verdana: 'Verdana',
}"
/>
</template>
</q-field>
</div>
</q-card-section>
<div class="col-12">
<q-card flat bordered>
<q-card-section class="bg-grey-4 q-py-sm">
<div class="row text-dark text-body2 text-weight-medium">
<div class="col-6 q-pl-xl">ระบบตำแหน</div>
<div class="col-6">
คำอธบายระด/พฤตกรรมทคาดหว/พฤตกรรมยอย
</div>
</div>
</q-card-section>
<div class="row items-center">
<q-card-section class="q-pa-none q-pl-xl col-6">
<span class="text-dark text-subtitle1 text-weight-medium">
L1 ประเภทอำนวยการ ระดบส
</span>
</q-card-section>
<q-card-section class="q-pa-none col-6">
<div class="q-mr-md">
<q-field
ref="fieldRef"
v-model="formData.level1"
label-slot
borderless
:rules="[
(val) =>
!!val || 'กรุณาระบุคำอธิบาย L1 ประเภทอำนวยการ ระดับสูง',
]"
hide-bottom-space
>
<template #control>
<q-editor
v-model="formData.level1"
:dense="$q.screen.lt.md"
min-height="5rem"
class="full-width"
:toolbar="[
[
'bold',
'italic',
'strike',
'underline',
'subscript',
'superscript',
],
['unordered', 'ordered'],
]"
:fonts="{
arial: 'Arial',
arial_black: 'Arial Black',
comic_sans: 'Comic Sans MS',
courier_new: 'Courier New',
impact: 'Impact',
lucida_grande: 'Lucida Grande',
times_new_roman: 'Times New Roman',
verdana: 'Verdana',
}"
/>
</template>
</q-field>
</div>
</q-card-section>
</div>
<div class="row items-center">
<q-card-section class="q-pa-none q-pl-xl col-6">
<span class="text-dark text-subtitle1 text-weight-medium">
L2 ประเภทบรหาร ระดบส
</span>
</q-card-section>
<q-card-section class="q-pa-none col-6">
<div class="q-mr-md">
<q-field
ref="fieldRef"
v-model="formData.level2"
label-slot
borderless
:rules="[
(val) =>
!!val || 'กรุณาระบุคำอธิบาย L2 ประเภทบริหาร ระดับสูง',
]"
hide-bottom-space
>
<template #control>
<q-editor
v-model="formData.level2"
:dense="$q.screen.lt.md"
min-height="5rem"
class="full-width"
:toolbar="[
[
'bold',
'italic',
'strike',
'underline',
'subscript',
'superscript',
],
['unordered', 'ordered'],
]"
:fonts="{
arial: 'Arial',
arial_black: 'Arial Black',
comic_sans: 'Comic Sans MS',
courier_new: 'Courier New',
impact: 'Impact',
lucida_grande: 'Lucida Grande',
times_new_roman: 'Times New Roman',
verdana: 'Verdana',
}"
/>
</template>
</q-field>
</div>
</q-card-section>
</div>
</q-card>
<div class="col-12 q-mt-md">
<q-input
v-model="formData.evaluation"
outlined
label="กำหนดเกณฑ์การประเมิน"
type="textarea"
dense
/>
</div>
<q-separator color="grey-4" />
<div class="col-12 row justify-end q-mt-md">
<q-btn
dense
unelevated
label="บันทึก"
color="public"
class="q-px-md"
type="submit"
>
<q-tooltip>นทกขอม</q-tooltip>
</q-btn>
</div>
</div>
</q-form>
</div>
</template>

View file

@ -1,295 +0,0 @@
div
<script setup lang="ts">
import { ref, reactive, onMounted } from "vue";
import { useRouter, useRoute } from "vue-router";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
/** importStore*/
import { useCounterMixin } from "@/stores/mixin";
import { useKPIDataStore } from "@/modules/01_metadata/stores/KPIStore";
/**use*/
const $q = useQuasar();
const mixin = useCounterMixin();
const { dialogConfirm, showLoader, hideLoader, success, messageError } = mixin;
const router = useRouter();
const route = useRoute();
const store = useKPIDataStore();
const competencyId = ref<string>(
route.params.id ? route.params.id.toString() : ""
);
const formData = reactive({
competencyType: "",
competencyName: "",
definition: "",
levels: [
{
level: "1",
description: "",
},
],
});
function fetchDetail() {
showLoader();
http
.get(config.API.kpiCapacity + `/${competencyId.value}`)
.then((res) => {
const data = res.data.result;
formData.competencyType = data.type;
formData.competencyName = data.name;
formData.definition = data.description;
formData.levels = data.capacityDetails;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
function onClickAddLevels() {
const levelName = formData.levels.length + 1;
const data = {
level:
(store.competencyTypeVal === "HEAD" ||
store.competencyTypeVal === "GROUP") &&
levelName <= 6
? levelName.toString()
: "",
description: "",
};
levelName <= 6 && formData.levels.push(data);
}
function onSubmit() {
dialogConfirm($q, async () => {
const formBody = {
type: store.competencyTypeVal,
name: formData.competencyName,
description: formData.definition,
capacityDetails: formData.levels,
};
try {
const url = competencyId.value
? config.API.kpiCapacity + `/${competencyId.value}`
: config.API.kpiCapacity;
const method = competencyId.value ? "put" : "post";
await http[method](url, formBody);
if (!competencyId.value) {
router.push(`/KPI-competency`);
} else {
fetchDetail();
}
success($q, "บันทึกข้อมูลสำเร็จ");
} catch (err) {
messageError($q, err);
} finally {
hideLoader();
}
});
}
function onDeleteLevels(index: number) {
formData.levels.splice(index, 1);
}
onMounted(() => {
if (competencyId.value) {
fetchDetail();
}
});
</script>
<template>
<q-form greedy @submit.prevent @validation-success="onSubmit" class="col-12">
<div class="row">
<div class="col-12">
<q-input
v-model="formData.competencyName"
dense
outlined
label="ชื่อสมรรถนะ"
:rules="[(val:string) => !!val || `${'กรุณากรอกชื่อสมรรถนะ'}`,]"
hide-bottom-space
/>
</div>
<q-card-section class="col-12 q-px-none">
<div>
<q-field
class="q_field_p_none"
ref="fieldRef"
v-model="formData.definition"
label-slot
borderless
:rules="[(val) => !!val || 'กรุณากรอกคำจำกัดความสมรรถนะ']"
hide-bottom-space
>
<template #control>
<q-editor
class="full-width"
v-model="formData.definition"
:dense="$q.screen.lt.md"
min-height="7rem"
placeholder="คำจำกัดความสมรรถนะ"
:toolbar="[
[
'bold',
'italic',
'strike',
'underline',
'subscript',
'superscript',
],
['unordered', 'ordered'],
]"
:fonts="{
arial: 'Arial',
arial_black: 'Arial Black',
comic_sans: 'Comic Sans MS',
courier_new: 'Courier New',
impact: 'Impact',
lucida_grande: 'Lucida Grande',
times_new_roman: 'Times New Roman',
verdana: 'Verdana',
}"
/>
</template>
</q-field>
</div>
</q-card-section>
<div class="col-12">
<q-card flat bordered>
<q-card-section class="bg-grey-4">
<div
class="row items-center text-dark text-body2 text-weight-medium"
>
<div class="col-3">
<div class="row items-center">
<div class="col-1">
<q-btn
dense
flat
round
color="primary"
icon="add"
@click="onClickAddLevels"
>
<q-tooltip>เพ</q-tooltip></q-btn
>
</div>
<div class="col-11 text-center">
<span>ระดบสมรรถนะ</span>
</div>
</div>
</div>
<div class="col-4">
<span>พฤตกรรมทคาดหว/พฤตกรรมยอย</span>
</div>
</div>
</q-card-section>
<q-card-section>
<div
class="row q-pa-sm"
v-for="(items, index) in formData.levels"
key="index"
>
<div class="col-3 align-center q-pr-lg">
<q-input
:readonly="
store.competencyTypeVal === 'HEAD' ||
store.competencyTypeVal === 'GROUP'
"
v-model="formData.levels[index].level"
dense
outlined
:rules="[(val:string) => !!val || `${'กรุณากรอกระดับสมรรถนะ'}`,]"
hide-bottom-space
/>
</div>
<div class="col-9">
<div class="row q-col-gutter-md">
<div class="col-11">
<q-field
class="q_field_p_none"
ref="fieldRef"
v-model="formData.levels[index].description"
label-slot
borderless
:rules="[
(val) =>
!!val || 'กรุณากรอกพฤติกรรมที่คาดหวัง/พฤติกรรมย่อย',
]"
hide-bottom-space
>
<template #control>
<q-editor
class="full-width"
v-model="formData.levels[index].description"
:dense="$q.screen.lt.md"
min-height="5rem"
:toolbar="[
[
'bold',
'italic',
'strike',
'underline',
'subscript',
'superscript',
],
['unordered', 'ordered'],
]"
/>
</template>
</q-field>
</div>
<div class="col-1 text-center">
<q-btn
dense
flat
round
color="red"
icon="delete"
@click="onDeleteLevels(index)"
v-if="
(store.competencyTypeVal === 'HEAD' && index > 4) ||
(store.competencyTypeVal === 'GROUP' && index > 4) ||
((store.competencyTypeVal === 'EXECUTIVE' ||
store.competencyTypeVal === 'DIRECTOR' ||
store.competencyTypeVal === 'INSPECTOR') &&
index > 0)
"
>
<q-tooltip>ลบ</q-tooltip></q-btn
>
</div>
</div>
</div>
</div>
</q-card-section>
</q-card>
</div>
<div class="col-12 q-my-sm"><q-separator /></div>
<div class="col-12 row justify-end">
<q-btn
dense
unelevated
label="บันทึก"
color="public"
class="q-px-md"
type="submit"
>
<q-tooltip>นทกขอม</q-tooltip>
</q-btn>
</div>
</div>
</q-form>
</template>
<style scoped></style>

View file

@ -1,25 +1,23 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
/** importType*/
import type { QTableProps } from "quasar";
/** importComponents*/
import DialogForm from "@/modules/01_metadata/components/personal/DialogForm.vue";
/** importStore*/
import { useCounterMixin } from "@/stores/mixin";
import { usePersonalDataStore } from "@/modules/01_metadata/stores/personalStore";
import type { QTableProps } from "quasar";
import DialogForm from "@/modules/01_metadata/components/personal/DialogForm.vue"; // ,
const $q = useQuasar();
const store = usePersonalDataStore();
const mixin = useCounterMixin();
const { dialogRemove, messageError, showLoader, hideLoader, success } = mixin;
const { messageError, showLoader, hideLoader, success } = useCounterMixin();
/** Table*/
/**
* Table
*/
const TABLE_COLUMNS = [
{
name: "prefix",
@ -73,19 +71,23 @@ const visibleColumns = ref<string[]>([
"lastUpdateFullName",
]);
const filterKeyword = ref<string>("");
const dialog = ref<boolean>(false);
const prefix = ref<string>("");
const editId = ref<string>("");
const dialogStatus = ref<string>("");
const personalName = ref<string>("คำนำหน้าชื่อ");
const filterKeyword = ref<string>(""); //
const dialog = ref<boolean>(false); // ,
const prefix = ref<string>(""); //
const editId = ref<string>(""); // id
const dialogStatus = ref<string>(""); // ,
const personalName = ref<string>("คำนำหน้าชื่อ"); //label input
/**
* fetch อมลรายการ คำนำหนาช
* นทกขอมลลงใน store
*/
async function fetchData() {
showLoader();
await http
.get(config.API.orgPrefix)
.then(async (res) => {
store.save(res.data.result);
await store.save(res.data.result);
})
.catch((err) => {
messageError($q, err);
@ -95,13 +97,18 @@ async function fetchData() {
});
}
/**
* เพมขอมลรายการคำนำหนาช
* แล fetch อมลรายการ คำนำหนาช ใหม
*/
async function addData() {
showLoader();
await http
.post(config.API.orgPrefix, {
name: prefix.value,
})
.then(() => {
fetchData();
.then(async () => {
await fetchData();
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
@ -112,13 +119,19 @@ async function addData() {
});
}
/**
* แกไขขอมลรายการคำนำหนาช
* แล fetch อมลรายการ คำนำหนาช ใหม
* @param id รายการคำนำหนาช
*/
async function editData(id: string) {
showLoader();
await http
.put(config.API.orgPrefixId(id), {
name: prefix.value,
})
.then(() => {
fetchData();
.then(async () => {
await fetchData();
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
@ -129,23 +142,12 @@ async function editData(id: string) {
});
}
async function deleteData(id: string) {
await http
.delete(config.API.orgPrefixId(id))
.then(() => {
fetchData();
success($q, "ลบข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/**
* hook ทำงานเม Components กเรยกใชงาน
* แลวเรยก function fetch อมลรายการคำนำหนาช
*/
onMounted(async () => {
fetchData();
await fetchData();
});
</script>
@ -228,20 +230,6 @@ onMounted(async () => {
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<!-- <q-btn
color="red"
flat
dense
round
icon="mdi-delete"
clickable
@click.stop="
dialogRemove($q, async () => await deleteData(props.row.id))
"
v-close-popup
>
<q-tooltip>ลบขอม</q-tooltip>
</q-btn> -->
</q-td>
<q-td v-for="col in props.cols" :key="col.id">
{{ col.value }}
@ -253,10 +241,10 @@ onMounted(async () => {
<DialogForm
v-model:dialog="dialog"
v-model:data="prefix"
v-model:personalName="personalName"
v-model:dialogStatus="dialogStatus"
v-model:editId="editId"
:addData="addData"
v-model:personal-name="personalName"
v-model:dialog-status="dialogStatus"
v-model:edit-id="editId"
:add-data="addData"
:fetch-data="fetchData"
:edit-data="editData"
/>

View file

@ -1,14 +1,23 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import type { QTableProps } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useRouter } from "vue-router";
import { usePersonalDataStore } from "@/modules/01_metadata/stores/personalStore";
import dialogHeader from "@/components/DialogHeader.vue";
import { useQuasar } from "quasar";
import DialogForm from "@/modules/01_metadata/components/personal/DialogForm.vue";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { usePersonalDataStore } from "@/modules/01_metadata/stores/personalStore";
import type { QTableProps } from "quasar";
import DialogForm from "@/modules/01_metadata/components/personal/DialogForm.vue"; // ,
const $q = useQuasar();
const store = usePersonalDataStore();
const { messageError, showLoader, hideLoader, success } = useCounterMixin();
/**
* Table
*/
const columns = [
{
name: "rank",
@ -55,20 +64,6 @@ const columns = [
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
] as const satisfies QTableProps["columns"];
const store = usePersonalDataStore();
const router = useRouter();
const mixin = useCounterMixin();
const { dialogRemove, messageError, showLoader, hideLoader, success } = mixin;
const $q = useQuasar();
const filterKeyword = ref<string>("");
const dialog = ref<boolean>(false);
const rank = ref<string>("");
const dialogStatus = ref<string>("");
const personalName = ref<string>("ยศ");
const editId = ref<string>("");
const visibleColumns = ref<string[]>([
"rank",
"createdAt",
@ -76,12 +71,23 @@ const visibleColumns = ref<string[]>([
"lastUpdateFullName",
]);
const filterKeyword = ref<string>(""); //
const dialog = ref<boolean>(false); // ,
const rank = ref<string>(""); //
const dialogStatus = ref<string>(""); // ,
const editId = ref<string>(""); // id
const personalName = ref<string>("ยศ"); //label input
/**
* fetch อมลรายการยศ
* นทกขอมลลงใน store
*/
async function fetchData() {
showLoader();
await http
.get(config.API.orgRank)
.then(async (res) => {
store.save(res.data.result);
await store.save(res.data.result);
})
.catch((err) => {
messageError($q, err);
@ -91,13 +97,18 @@ async function fetchData() {
});
}
/**
* เพมขอมลรายการคำนำหนาช
* แล fetch อมลรายการรยศ ใหม
*/
async function addData() {
showLoader();
await http
.post(config.API.orgRank, {
name: rank.value,
})
.then(() => {
fetchData();
.then(async () => {
await fetchData();
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
@ -108,13 +119,19 @@ async function addData() {
});
}
/**
* แกไขขอมลรายการยศ
* แล fetch อมลรายการยศ ใหม
* @param id รายการยศ
*/
async function editData(id: string) {
showLoader();
await http
.put(config.API.orgRankId(id), {
name: rank.value,
})
.then(() => {
fetchData();
.then(async () => {
await fetchData();
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
@ -125,23 +142,12 @@ async function editData(id: string) {
});
}
async function deleteData(id: string) {
await http
.delete(config.API.orgRankId(id))
.then(() => {
fetchData();
success($q, "ลบข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/**
* hook ทำงานเม Components กเรยกใชงาน
* แลวเรยก function fetch อมลรายการยศ
*/
onMounted(async () => {
fetchData();
await fetchData();
});
</script>
@ -224,20 +230,6 @@ onMounted(async () => {
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<!-- <q-btn
color="red"
flat
dense
round
icon="mdi-delete"
clickable
@click.stop="
dialogRemove($q, async () => await deleteData(props.row.id))
"
v-close-popup
>
<q-tooltip>ลบขอม</q-tooltip>
</q-btn> -->
</q-td>
<q-td v-for="col in props.cols" :key="col.id">
<div>
@ -251,10 +243,10 @@ onMounted(async () => {
<DialogForm
v-model:dialog="dialog"
v-model:data="rank"
v-model:personalName="personalName"
v-model:dialogStatus="dialogStatus"
v-model:editId="editId"
:addData="addData"
v-model:personal-name="personalName"
v-model:dialog-status="dialogStatus"
v-model:edit-id="editId"
:add-data="addData"
:fetch-data="fetchData"
:edit-data="editData"
/>

View file

@ -1,19 +1,23 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import type { QTableProps } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useRouter } from "vue-router";
import { usePersonalDataStore } from "@/modules/01_metadata/stores/personalStore";
import dialogHeader from "@/components/DialogHeader.vue";
import { useQuasar } from "quasar";
import DialogForm from "@/modules/01_metadata/components/personal/DialogForm.vue";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { usePersonalDataStore } from "@/modules/01_metadata/stores/personalStore";
import type { QTableProps } from "quasar";
import DialogForm from "@/modules/01_metadata/components/personal/DialogForm.vue"; // ,
const $q = useQuasar();
const store = usePersonalDataStore();
const router = useRouter();
const mixin = useCounterMixin();
const { dialogRemove, messageError, showLoader, hideLoader, success } = mixin;
const { messageError, showLoader, hideLoader, success } = useCounterMixin();
/**
* Table
*/
const columns = [
{
name: "gender",
@ -60,15 +64,6 @@ const columns = [
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
] as const satisfies QTableProps["columns"];
const $q = useQuasar();
const filterKeyword = ref<string>("");
const dialog = ref<boolean>(false);
const gender = ref<string>("");
const editId = ref<string>("");
const dialogStatus = ref<string>("");
const personalName = ref<string>("เพศ");
const visibleColumns = ref<string[]>([
"gender",
"createdAt",
@ -76,12 +71,23 @@ const visibleColumns = ref<string[]>([
"lastUpdateFullName",
]);
const filterKeyword = ref<string>(""); //
const dialog = ref<boolean>(false); // ,
const gender = ref<string>(""); //
const editId = ref<string>(""); // id
const dialogStatus = ref<string>(""); // ,
const personalName = ref<string>("เพศ"); //label input
/**
* fetch อมลรายการ เพศ
* นทกขอมลลงใน store
*/
async function fetchData() {
showLoader();
await http
.get(config.API.orgGender)
.then(async (res) => {
store.save(res.data.result);
await store.save(res.data.result);
})
.catch((err) => {
messageError($q, err);
@ -91,13 +97,18 @@ async function fetchData() {
});
}
/**
* เพมขอมลรายการเพศ
* แล fetch อมลรายการเพศ ใหม
*/
async function addData() {
showLoader();
await http
.post(config.API.orgGender, {
name: gender.value,
})
.then(() => {
fetchData();
.then(async () => {
await fetchData();
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
@ -108,13 +119,19 @@ async function addData() {
});
}
/**
* แกไขขอมลรายการเพศ
* แล fetch อมลรายการเพศ ใหม
* @param id รายการเพศ
*/
async function editData(id: string) {
showLoader();
await http
.put(config.API.orgGenderId(id), {
name: gender.value,
})
.then(() => {
fetchData();
.then(async () => {
await fetchData();
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
@ -125,23 +142,12 @@ async function editData(id: string) {
});
}
async function deleteData(id: string) {
await http
.delete(config.API.orgGenderId(id))
.then(() => {
fetchData();
success($q, "ลบข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/**
* hook ทำงานเม Components กเรยกใชงาน
* แลวเรยก function fetch อมลรายการเพศ
*/
onMounted(async () => {
fetchData();
await fetchData();
});
</script>
@ -224,20 +230,6 @@ onMounted(async () => {
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<!-- <q-btn
color="red"
flat
dense
round
icon="mdi-delete"
clickable
@click.stop="
dialogRemove($q, async () => await deleteData(props.row.id))
"
v-close-popup
>
<q-tooltip>ลบขอม</q-tooltip>
</q-btn> -->
</q-td>
<q-td v-for="col in props.cols" :key="col.id">
<div>
@ -251,10 +243,10 @@ onMounted(async () => {
<DialogForm
v-model:dialog="dialog"
v-model:data="gender"
v-model:personalName="personalName"
v-model:dialogStatus="dialogStatus"
v-model:editId="editId"
:addData="addData"
v-model:personal-name="personalName"
v-model:dialog-status="dialogStatus"
v-model:edit-id="editId"
:add-data="addData"
:fetch-data="fetchData"
:edit-data="editData"
/>

View file

@ -1,18 +1,23 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import type { QTableProps } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useRouter } from "vue-router";
import { usePersonalDataStore } from "@/modules/01_metadata/stores/personalStore";
import { useQuasar } from "quasar";
import DialogForm from "@/modules/01_metadata/components/personal/DialogForm.vue";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { usePersonalDataStore } from "@/modules/01_metadata/stores/personalStore";
import type { QTableProps } from "quasar";
import DialogForm from "@/modules/01_metadata/components/personal/DialogForm.vue"; // ,
const $q = useQuasar();
const store = usePersonalDataStore();
const router = useRouter();
const mixin = useCounterMixin();
const { dialogRemove, messageError, showLoader, hideLoader, success } = mixin;
const { messageError, showLoader, hideLoader, success } = useCounterMixin();
/**
* Table
*/
const columns = [
{
name: "relationship",
@ -59,58 +64,30 @@ const columns = [
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
] as const satisfies QTableProps["columns"];
const $q = useQuasar();
const filterKeyword = ref<string>("");
const dialog = ref<boolean>(false);
const relationship = ref<string>("");
const dialogStatus = ref<string>("");
const personalName = ref<string>("สถานภาพ");
const visibleColumns = ref<string[]>([
"relationship",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
]);
const editId = ref<string>("");
const data = [
{
id: "1",
name: "เคยสมรสแต่ไม่ทราบสถานภาพสมรส",
createdAt: new Date(),
lastUpdatedAt: new Date(),
lastUpdateFullName: "สาวิตรี ศรีสมัย",
},
{
id: "2",
name: "สมรส",
createdAt: new Date(),
lastUpdatedAt: new Date(),
lastUpdateFullName: "System Administrator",
},
{
id: "3",
name: "แยกกันอยู่",
createdAt: new Date(),
lastUpdatedAt: new Date(),
lastUpdateFullName: "คณะกรรมการ ตรวจรับ",
},
{
id: "4",
name: "โสด",
createdAt: new Date(),
lastUpdatedAt: new Date(),
lastUpdateFullName: "คณะกรรมการ ตรวจรับ",
},
];
const filterKeyword = ref<string>(""); //
const dialog = ref<boolean>(false); // ,
const relationship = ref<string>(""); //
const editId = ref<string>(""); // id
const dialogStatus = ref<string>(""); // ,
const personalName = ref<string>("สถานภาพ"); //label input
/**
* fetch อมลรายการสถานภาพ
* นทกขอมลลงใน store
*/
async function fetchData() {
showLoader();
await http
.get(config.API.orgRelationship)
.then(async (res) => {
store.save(res.data.result);
await store.save(res.data.result);
})
.catch((err) => {
messageError($q, err);
@ -120,13 +97,18 @@ async function fetchData() {
});
}
/**
* เพมขอมลรายการสถานภาพ
* แล fetch อมลรายการสถานภาพ ใหม
*/
async function addData() {
showLoader();
await http
.post(config.API.orgRelationship, {
name: relationship.value,
})
.then(() => {
fetchData();
.then(async () => {
await fetchData();
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
@ -136,13 +118,20 @@ async function addData() {
hideLoader();
});
}
/**
* แกไขขอมลรายการสถานภาพ
* แล fetch อมลรายการสถานภาพ ใหม
* @param id รายการสถานภาพ
*/
async function editData(id: string) {
showLoader();
await http
.put(config.API.orgRelationshipId(id), {
name: relationship.value,
})
.then(() => {
fetchData();
.then(async () => {
await fetchData();
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
@ -153,23 +142,12 @@ async function editData(id: string) {
});
}
async function deleteData(id: string) {
await http
.delete(config.API.orgRelationshipId(id))
.then(() => {
fetchData();
success($q, "ลบข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/**
* hook ทำงานเม Components กเรยกใชงาน
* แลวเรยก function fetch อมลรายการสถานภาพ
*/
onMounted(async () => {
fetchData();
await fetchData();
});
</script>
@ -252,20 +230,6 @@ onMounted(async () => {
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<!-- <q-btn
color="red"
flat
dense
round
icon="mdi-delete"
clickable
@click.stop="
dialogRemove($q, async () => await deleteData(props.row.id))
"
v-close-popup
>
<q-tooltip>ลบขอม</q-tooltip>
</q-btn> -->
</q-td>
<q-td v-for="col in props.cols" :key="col.id">
<div>
@ -279,10 +243,10 @@ onMounted(async () => {
<DialogForm
v-model:dialog="dialog"
v-model:data="relationship"
v-model:personalName="personalName"
v-model:dialogStatus="dialogStatus"
v-model:editId="editId"
:addData="addData"
v-model:personal-name="personalName"
v-model:dialog-status="dialogStatus"
v-model:edit-id="editId"
:add-data="addData"
:fetch-data="fetchData"
:edit-data="editData"
/>

View file

@ -1,19 +1,23 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import type { QTableProps } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useRouter } from "vue-router";
import { usePersonalDataStore } from "@/modules/01_metadata/stores/personalStore";
import dialogHeader from "@/components/DialogHeader.vue";
import { useQuasar } from "quasar";
import DialogForm from "@/modules/01_metadata/components/personal/DialogForm.vue";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { usePersonalDataStore } from "@/modules/01_metadata/stores/personalStore";
import type { QTableProps } from "quasar";
import DialogForm from "@/modules/01_metadata/components/personal/DialogForm.vue"; // ,
const $q = useQuasar();
const store = usePersonalDataStore();
const router = useRouter();
const mixin = useCounterMixin();
const { dialogRemove, messageError, showLoader, hideLoader, success } = mixin;
const { messageError, showLoader, hideLoader, success } = useCounterMixin();
/**
* Table
*/
const columns = [
{
name: "bloodGroup",
@ -60,15 +64,6 @@ const columns = [
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
] as const satisfies QTableProps["columns"];
const $q = useQuasar();
const filterKeyword = ref<string>("");
const dialog = ref<boolean>(false);
const editId = ref<string>("");
const bloodGroup = ref<string>("");
const dialogStatus = ref<string>("");
const personalName = ref<string>("กลุ่มเลือด");
const visibleColumns = ref<string[]>([
"bloodGroup",
"createdAt",
@ -76,12 +71,23 @@ const visibleColumns = ref<string[]>([
"lastUpdateFullName",
]);
const filterKeyword = ref<string>(""); //
const dialog = ref<boolean>(false); // ,
const bloodGroup = ref<string>(""); //
const editId = ref<string>(""); // id
const dialogStatus = ref<string>(""); // ,
const personalName = ref<string>("กลุ่มเลือด"); //label input
/**
* fetch อมลรายการ กลมเลอด
* นทกขอมลลงใน store
*/
async function fetchData() {
showLoader();
await http
.get(config.API.orgBloodGroup)
.then(async (res) => {
store.save(res.data.result);
await store.save(res.data.result);
})
.catch((err) => {
messageError($q, err);
@ -91,13 +97,17 @@ async function fetchData() {
});
}
/**
* เพมขอมลรายการกลมเลอด
* แล fetch อมลรายการ กลมเลอด ใหม
*/
async function addData() {
await http
.post(config.API.orgBloodGroup, {
name: bloodGroup.value,
})
.then(() => {
fetchData();
.then(async () => {
await fetchData();
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
@ -108,13 +118,19 @@ async function addData() {
});
}
/**
* แกไขขอมลรายการกลมเลอด
* แล fetch อมลรายการ กลมเลอด ใหม
* @param id รายการกลมเลอด
*/
async function editData(id: string) {
showLoader();
await http
.put(config.API.orgBloodGroupId(id), {
name: bloodGroup.value,
})
.then(() => {
fetchData();
.then(async () => {
await fetchData();
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
@ -125,23 +141,12 @@ async function editData(id: string) {
});
}
async function deleteData(id: string) {
await http
.delete(config.API.orgBloodGroupId(id))
.then(() => {
fetchData();
success($q, "ลบข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/**
* hook ทำงานเม Components กเรยกใชงาน
* แลวเรยก function fetch อมลรายการกลมเลอด
*/
onMounted(async () => {
fetchData();
await fetchData();
});
</script>
@ -224,20 +229,6 @@ onMounted(async () => {
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<!-- <q-btn
color="red"
flat
dense
round
icon="mdi-delete"
clickable
@click.stop="
dialogRemove($q, async () => await deleteData(props.row.id))
"
v-close-popup
>
<q-tooltip>ลบขอม</q-tooltip>
</q-btn> -->
</q-td>
<q-td v-for="col in props.cols" :key="col.id">
<div>
@ -251,10 +242,10 @@ onMounted(async () => {
<DialogForm
v-model:dialog="dialog"
v-model:data="bloodGroup"
v-model:personalName="personalName"
v-model:dialogStatus="dialogStatus"
v-model:editId="editId"
:addData="addData"
v-model:personal-name="personalName"
v-model:dialog-status="dialogStatus"
v-model:edit-id="editId"
:add-data="addData"
:fetch-data="fetchData"
:edit-data="editData"
/>

View file

@ -1,19 +1,23 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import type { QTableProps } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useRouter } from "vue-router";
import { usePersonalDataStore } from "@/modules/01_metadata/stores/personalStore";
import dialogHeader from "@/components/DialogHeader.vue";
import { useQuasar } from "quasar";
import DialogForm from "@/modules/01_metadata/components/personal/DialogForm.vue";
import http from "@/plugins/http";
import config from "@/app.config";
import { usePersonalDataStore } from "@/modules/01_metadata/stores/personalStore";
import { useCounterMixin } from "@/stores/mixin";
import type { QTableProps } from "quasar";
import DialogForm from "@/modules/01_metadata/components/personal/DialogForm.vue"; // ,
const $q = useQuasar();
const store = usePersonalDataStore();
const router = useRouter();
const mixin = useCounterMixin();
const { dialogRemove, messageError, showLoader, hideLoader, success } = mixin;
const { messageError, showLoader, hideLoader, success } = useCounterMixin();
/**
* Table
*/
const columns = [
{
name: "religion",
@ -60,15 +64,6 @@ const columns = [
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
] as const satisfies QTableProps["columns"];
const $q = useQuasar();
const filterKeyword = ref<string>("");
const dialog = ref<boolean>(false);
const religion = ref<string>("");
const editId = ref<string>("");
const dialogStatus = ref<string>("");
const personalName = ref<string>("ศาสนา");
const visibleColumns = ref<string[]>([
"religion",
"createdAt",
@ -76,12 +71,23 @@ const visibleColumns = ref<string[]>([
"lastUpdateFullName",
]);
const filterKeyword = ref<string>(""); //
const dialog = ref<boolean>(false); // ,
const religion = ref<string>(""); //
const editId = ref<string>(""); // id
const dialogStatus = ref<string>(""); // ,
const personalName = ref<string>("ศาสนา"); //label input
/**
* fetch อมลรายการ ศาสนา
* นทกขอมลลงใน store
*/
async function fetchData() {
showLoader();
await http
.get(config.API.orgReligion)
.then(async (res) => {
store.save(res.data.result);
await store.save(res.data.result);
})
.catch((err) => {
messageError($q, err);
@ -91,13 +97,18 @@ async function fetchData() {
});
}
/**
* เพมขอมลรายการศาสนา
* แล fetch อมลรายการ ศาสนา ใหม
*/
async function addData() {
showLoader();
await http
.post(config.API.orgReligion, {
name: religion.value,
})
.then(() => {
fetchData();
.then(async () => {
await fetchData();
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
@ -108,13 +119,19 @@ async function addData() {
});
}
/**
* แกไขขอมลรายการศาสนา
* แล fetch อมลรายการ ศาสนา ใหม
* @param id รายการศาสนา
*/
async function editData(id: string) {
showLoader();
await http
.put(config.API.orgReligionId(id), {
name: religion.value,
})
.then(() => {
fetchData();
.then(async () => {
await fetchData();
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
@ -125,23 +142,12 @@ async function editData(id: string) {
});
}
async function deleteData(id: string) {
await http
.delete(config.API.orgReligionId(id))
.then(() => {
fetchData();
success($q, "ลบข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/**
* hook ทำงานเม Components กเรยกใชงาน
* แลวเรยก function fetch อมลรายการศาสนา
*/
onMounted(async () => {
fetchData();
await fetchData();
});
</script>
@ -224,20 +230,6 @@ onMounted(async () => {
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<!-- <q-btn
color="red"
flat
dense
round
icon="mdi-delete"
clickable
@click.stop="
dialogRemove($q, async () => await deleteData(props.row.id))
"
v-close-popup
>
<q-tooltip>ลบขอม</q-tooltip>
</q-btn> -->
</q-td>
<q-td v-for="col in props.cols" :key="col.id">
<div>
@ -251,10 +243,10 @@ onMounted(async () => {
<DialogForm
v-model:dialog="dialog"
v-model:data="religion"
v-model:personalName="personalName"
v-model:dialogStatus="dialogStatus"
v-model:editId="editId"
:addData="addData"
v-model:personal-name="personalName"
v-model:dialog-status="dialogStatus"
v-model:edit-id="editId"
:add-data="addData"
:fetch-data="fetchData"
:edit-data="editData"
/>

View file

@ -1,18 +1,25 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import type { QTableProps } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useRouter } from "vue-router";
import { usePersonalDataStore } from "@/modules/01_metadata/stores/personalStore";
import { useQuasar } from "quasar";
import DialogForm from "@/modules/01_metadata/components/personal/DialogForm.vue";
import { useRouter } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { usePersonalDataStore } from "@/modules/01_metadata/stores/personalStore";
import type { QTableProps } from "quasar";
import DialogForm from "@/modules/01_metadata/components/personal/DialogForm.vue"; // ,
const $q = useQuasar();
const router = useRouter();
const store = usePersonalDataStore();
const mixin = useCounterMixin();
const { dialogRemove, messageError, showLoader, hideLoader, success } = mixin;
const { messageError, showLoader, hideLoader, success } = useCounterMixin();
/**
* Teble
*/
const columns = [
{
name: "name",
@ -59,15 +66,6 @@ const columns = [
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
] as const satisfies QTableProps["columns"];
const $q = useQuasar();
const editId = ref<string>("");
const filterKeyword = ref<string>("");
const dialog = ref<boolean>(false);
const province = ref<string>("");
const dialogStatus = ref<string>("");
const personalName = ref<string>("จังหวัด");
const visibleColumns = ref<string[]>([
"name",
"createdAt",
@ -75,12 +73,23 @@ const visibleColumns = ref<string[]>([
"lastUpdateFullName",
]);
const filterKeyword = ref<string>(""); //
const dialog = ref<boolean>(false); // ,
const editId = ref<string>(""); // id
const province = ref<string>(""); //
const dialogStatus = ref<string>(""); // ,
const personalName = ref<string>("จังหวัด"); //label input
/**
* fetch อมลรายการ งหว
* นทกขอมลลงใน store
*/
async function fetchData() {
showLoader();
await http
.get(config.API.orgProvince)
.then(async (res) => {
store.save(res.data.result);
await store.save(res.data.result);
})
.catch((err) => {
messageError($q, err);
@ -90,13 +99,18 @@ async function fetchData() {
});
}
/**
* เพมขอมลรายการจงหว
* แล fetch อมลรายการ งหว ใหม
*/
async function addData() {
showLoader();
await http
.post(config.API.orgProvince, {
name: province.value,
})
.then(() => {
fetchData();
.then(async () => {
await fetchData();
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
@ -107,13 +121,19 @@ async function addData() {
});
}
/**
* แกไขขอมลรายการจงหว
* แล fetch อมลรายการ งหว ใหม
* @param id รายการจงหว
*/
async function editData(id: string) {
showLoader();
await http
.put(config.API.orgProvince + `/${id}`, {
name: province.value,
})
.then(() => {
fetchData();
.then(async () => {
await fetchData();
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
@ -124,27 +144,20 @@ async function editData(id: string) {
});
}
async function deleteData(id: string) {
await http
.delete(config.API.orgProvince + `/${id}`)
.then(() => {
fetchData();
success($q, "ลบข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/**
* ไปยงหน รายากรเขต/อำเภอ โดย id ของจงหว
* @param id งหว
*/
function nextPage(id: string) {
router.push(`/master-data/personal/district/${id}`);
}
/**
* hook ทำงานเม Components กเรยกใชงาน
* แลวเรยก function fetch อมลรายการจงหว
*/
onMounted(async () => {
fetchData();
await fetchData();
});
</script>
@ -228,25 +241,11 @@ onMounted(async () => {
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<!-- <q-btn
color="red"
flat
dense
round
icon="mdi-delete"
clickable
@click.stop="
dialogRemove($q, async () => await deleteData(props.row.id))
"
v-close-popup
>
<q-tooltip>ลบขอม</q-tooltip>
</q-btn> -->
</q-td>
<q-td
v-for="col in props.cols"
:key="col.id"
@click="nextPage(props.row.id)"
@click.stop="nextPage(props.row.id)"
>
<div>
{{ col.value }}
@ -259,10 +258,10 @@ onMounted(async () => {
<DialogForm
v-model:dialog="dialog"
v-model:data="province"
v-model:personalName="personalName"
v-model:dialogStatus="dialogStatus"
v-model:editId="editId"
:addData="addData"
v-model:personal-name="personalName"
v-model:dialog-status="dialogStatus"
v-model:edit-id="editId"
:add-data="addData"
:fetch-data="fetchData"
:edit-data="editData"
/>

View file

@ -1,17 +1,20 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import type { QTableProps } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useRouter } from "vue-router";
import { usePersonalDataStore } from "@/modules/01_metadata/stores/personalStore";
import { useQuasar } from "quasar";
import DialogForm from "@/modules/01_metadata/components/personal/DialogForm.vue";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { usePersonalDataStore } from "@/modules/01_metadata/stores/personalStore";
import type { QTableProps } from "quasar";
import DialogForm from "@/modules/01_metadata/components/personal/DialogForm.vue";
const $q = useQuasar();
const store = usePersonalDataStore();
const mixin = useCounterMixin();
const { dialogRemove, messageError, showLoader, hideLoader, success } = mixin;
const { messageError, showLoader, hideLoader, success } = useCounterMixin();
const columns = [
{
name: "name",
@ -69,15 +72,6 @@ const columns = [
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
] as const satisfies QTableProps["columns"];
const $q = useQuasar();
const editId = ref<string>("");
const filterKeyword = ref<string>("");
const dialog = ref<boolean>(false);
const educationLevel = ref<string>("");
const educationRank = ref<number>();
const dialogStatus = ref<string>("");
const personalName = ref<string>("ระดับการศึกษา");
const visibleColumns = ref<string[]>([
"name",
"rank",
@ -86,12 +80,24 @@ const visibleColumns = ref<string[]>([
"lastUpdateFullName",
]);
const filterKeyword = ref<string>(""); //
const dialog = ref<boolean>(false); // ,
const educationRank = ref<number>(); //
const educationLevel = ref<string>(""); //
const editId = ref<string>(""); // id
const dialogStatus = ref<string>(""); // ,
const personalName = ref<string>("ระดับการศึกษา"); //label input
/**
* fetch อมลรายการ ระดบการศกษา
* นทกขอมลลงใน store
*/
async function fetchData() {
showLoader();
await http
.get(config.API.orgEducationLevel)
.then(async (res) => {
store.save(res.data.result);
await store.save(res.data.result);
})
.catch((err) => {
messageError($q, err);
@ -101,14 +107,19 @@ async function fetchData() {
});
}
/**
* เพมขอมลรายการระดบการศกษา
* แล fetch อมลรายการ ระดบการศกษา ใหม
*/
async function addData() {
showLoader();
await http
.post(config.API.orgEducationLevel, {
name: educationLevel.value,
rank: educationRank.value,
})
.then(() => {
fetchData();
.then(async () => {
await fetchData();
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
@ -119,14 +130,20 @@ async function addData() {
});
}
/**
* แกไขขอมลรายการระดบการศกษา
* แล fetch อมลรายการ ระดบการศกษา ใหม
* @param id รายการระดบการศกษา
*/
async function editData(id: string) {
showLoader();
await http
.put(config.API.orgEducationLevelId(id), {
name: educationLevel.value,
rank: educationRank.value,
})
.then(() => {
fetchData();
.then(async () => {
await fetchData();
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
@ -137,21 +154,10 @@ async function editData(id: string) {
});
}
async function deleteData(id: string) {
await http
.delete(config.API.orgEducationLevelId(id))
.then(() => {
fetchData();
success($q, "ลบข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/**
* hook ทำงานเม Components กเรยกใชงาน
* แลวเรยก function fetch อมลรายการระดบการศกษา
*/
onMounted(async () => {
fetchData();
});
@ -239,20 +245,6 @@ onMounted(async () => {
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<!-- <q-btn
color="red"
flat
dense
round
icon="mdi-delete"
clickable
@click.stop="
dialogRemove($q, async () => await deleteData(props.row.id))
"
v-close-popup
>
<q-tooltip>ลบขอม</q-tooltip>
</q-btn> -->
</q-td>
<q-td v-for="col in props.cols" :key="col.id">
<div>
@ -264,13 +256,13 @@ onMounted(async () => {
</d-table>
<DialogForm
v-model:educationRank="educationRank"
v-model:education-rank="educationRank"
v-model:dialog="dialog"
v-model:data="educationLevel"
v-model:personalName="personalName"
v-model:dialogStatus="dialogStatus"
v-model:editId="editId"
:addData="addData"
v-model:personal-name="personalName"
v-model:dialog-status="dialogStatus"
v-model:edit-id="editId"
:add-data="addData"
:fetch-data="fetchData"
:edit-data="editData"
/>

View file

@ -1,28 +1,23 @@
<script setup lang="ts">
import { ref } from "vue";
import { QInput, useQuasar } from "quasar";
/** importComponents*/
import dialogHeader from "@/components/DialogHeader.vue";
/** importStore*/
import { useCounterMixin } from "@/stores/mixin";
/** use*/
import dialogHeader from "@/components/DialogHeader.vue"; // Popup
const $q = useQuasar();
const mixin = useCounterMixin();
const { dialogConfirm } = mixin;
const { dialogConfirm } = useCounterMixin();
/** props*/
const data = defineModel<string>("data", {
required: true,
});
const personalName = defineModel<string>("personalName");
const dialogStatus = defineModel<string>("dialogStatus");
const editId = defineModel<string>("editId");
const dialog = defineModel<boolean>("dialog");
const educationRank = defineModel<number>("educationRank");
const zipCode = defineModel<string>("zipCode");
const personalName = defineModel<string>("personalName"); //label input
const dialogStatus = defineModel<string>("dialogStatus"); // ,
const editId = defineModel<string>("editId"); // id
const dialog = defineModel<boolean>("dialog"); // modal
const educationRank = defineModel<number>("educationRank"); //
const zipCode = defineModel<string>("zipCode"); //
const props = defineProps({
fetchData: {
type: Function,
@ -37,30 +32,19 @@ const props = defineProps({
},
});
const dataRef = ref<QInput | null>(null);
const zipCodeRef = ref<QInput | null>(null);
const educationRankRef = ref<QInput | null>(null);
function closeDialog() {
dialog.value = false;
data.value = "";
}
function validateForm() {
dataRef.value?.validate();
zipCodeRef.value?.validate();
educationRankRef.value?.validate();
onSubmit();
}
/**
* นยนการบนทกขอม
* - dialogStatus เป "create", จะเรยกฟงก props.addData()
* - dialogStatus เปนคาอ, จะเรยกฟงก props.editData(editId.value)
*/
async function onSubmit() {
if (data.value.length > 0) {
dialogConfirm(
$q,
async () => {
dialogStatus.value === "create"
? props.addData()
: props.editData(editId.value);
? await props.addData()
: await props.editData(editId.value);
closeDialog();
educationRank.value = undefined;
},
@ -69,20 +53,26 @@ async function onSubmit() {
);
}
}
/**
* popup
*/
function closeDialog() {
dialog.value = false;
data.value = "";
}
</script>
<template>
<q-dialog v-model="dialog" class="dialog" persistent>
<q-card style="min-width: 350px">
<form @submit.prevent="validateForm">
<q-card-section class="flex justify-between" style="padding: 0">
<dialog-header
:tittle="dialogStatus == 'edit' ? 'แก้ไขข้อมูล' : 'เพิ่มข้อมูล'"
:close="closeDialog"
/>
</q-card-section>
<q-form greedy @submit.prevent @validation-success="onSubmit">
<dialog-header
:tittle="dialogStatus == 'edit' ? 'แก้ไขข้อมูล' : 'เพิ่มข้อมูล'"
:close="closeDialog"
/>
<q-separator color="grey-4" />
<q-separator />
<q-card-section class="q-pa-none">
<div class="col-12 q-ma-md">
<q-input
@ -137,20 +127,13 @@ async function onSubmit() {
/>
</div>
</q-card-section>
<q-separator color="grey-4" />
<q-separator />
<q-card-actions align="right">
<q-btn
id="onSubmit"
type="submit"
dense
unelevated
label="บันทึก"
color="public"
>
<q-btn id="onSubmit" type="submit" label="บันทึก" color="public">
<q-tooltip>นทกขอม</q-tooltip>
</q-btn>
</q-card-actions>
</form>
</q-form>
</q-card>
</q-dialog>
</template>

View file

@ -1,29 +1,26 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import type { QTableProps } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useRouter, useRoute } from "vue-router";
import { usePersonalDataStore } from "@/modules/01_metadata/stores/personalStore";
import { useQuasar } from "quasar";
import DialogForm from "@/modules/01_metadata/components/personal/DialogForm.vue";
import { useRouter, useRoute } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import type { QTableProps } from "quasar";
import type { FormDistrict } from "@/modules/01_metadata/interface/response/personal/personal";
import DialogForm from "@/modules/01_metadata/components/personal/DialogForm.vue"; // ,
const $q = useQuasar();
const router = useRouter();
const route = useRoute();
const id = ref<string>(route.params.id as string);
const store = usePersonalDataStore();
const mixin = useCounterMixin();
const {
dialogRemove,
messageError,
showLoader,
hideLoader,
success,
date2Thai,
} = mixin;
const { messageError, showLoader, hideLoader, success, date2Thai } =
useCounterMixin();
/**
* Table
*/
const columns = [
{
name: "name",
@ -70,16 +67,6 @@ const columns = [
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
] as const satisfies QTableProps["columns"];
const $q = useQuasar();
const editId = ref<string>("");
const filterKeyword = ref<string>("");
const dialog = ref<boolean>(false);
const district = ref<string>("");
const rows = ref<FormDistrict[]>([]);
const dialogStatus = ref<string>("");
const personalName = ref<string>("เขต/อำเภอ");
const visibleColumns = ref<string[]>([
"name",
"createdAt",
@ -87,16 +74,33 @@ const visibleColumns = ref<string[]>([
"lastUpdateFullName",
]);
const id = ref<string>(route.params.id as string); // id
const filterKeyword = ref<string>(""); //
const district = ref<string>(""); // /
const editId = ref<string>(""); // id /
const dialog = ref<boolean>(false); // ,
const dialogStatus = ref<string>(""); // ,
const personalName = ref<string>("เขต/อำเภอ"); //label input
const rows = ref<FormDistrict[]>([]); // /
/**
* fetch อมลรายการ ระดบการเขต/อำเภอ ตาม id ของจงหว
* - ดการกบขอม
* - กำหนด rows.value เทากบขอมลท respones
*/
async function fetchData() {
showLoader();
await http
.get(config.API.orgProvince + `/${id.value}`)
.then(async (res) => {
const data = res.data.result.districts;
const list = data.map((e: any) => ({
const data = await res.data.result.districts;
const list = data.map((e: FormDistrict) => ({
...e,
createdAt: e.createdAt ? date2Thai(e.createdAt) : "",
lastUpdatedAt: e.lastUpdatedAt ? date2Thai(e.lastUpdatedAt) : "",
createdAt: e.createdAt ? date2Thai(new Date(e.createdAt)) : "",
lastUpdatedAt: e.lastUpdatedAt
? date2Thai(new Date(e.lastUpdatedAt))
: "",
}));
rows.value = list;
})
@ -108,14 +112,19 @@ async function fetchData() {
});
}
/**
* เพมขอมลรายการระดบการเขต/อำเภอ
* แล fetch อมลรายการ ระดบการเขต/อำเภอ ใหม
*/
async function addData() {
showLoader();
await http
.post(config.API.orgDistrict, {
name: district.value,
provinceId: id.value,
})
.then(() => {
fetchData();
.then(async () => {
await fetchData();
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
@ -126,13 +135,19 @@ async function addData() {
});
}
/**
* แกไขขอมลรายการระดบการเขต/อำเภอ
* แล fetch อมลรายการ ระดบการเขต/อำเภอ ใหม
* @param id รายการระดบการเขต/อำเภอ
*/
async function editData(id: string) {
showLoader();
await http
.put(config.API.orgDistrict + `/${id}`, {
name: district.value,
})
.then(() => {
fetchData();
.then(async () => {
await fetchData();
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
@ -143,27 +158,20 @@ async function editData(id: string) {
});
}
async function deleteData(id: string) {
await http
.delete(config.API.orgDistrict + `/${id}`)
.then(() => {
fetchData();
success($q, "ลบข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/**
* ไปยงหน รายากรเแขวง/ตำบลโดย id ของเขต/อำเภอ
* @param idSub เขต/อำเภอ
*/
function nextPage(idSub: string) {
router.push(`/master-data/personal/sub-district/${id.value}/${idSub}`);
}
/**
* hook ทำงานเม Components กเรยกใชงาน
* แลวเรยก function fetch อมลรายการระดบการเขต/อำเภอ
*/
onMounted(async () => {
fetchData();
await fetchData();
});
</script>
@ -268,20 +276,6 @@ onMounted(async () => {
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<q-btn
color="red"
flat
dense
round
icon="mdi-delete"
clickable
@click.stop="
dialogRemove($q, async () => await deleteData(props.row.id))
"
v-close-popup
>
<q-tooltip>ลบขอม</q-tooltip>
</q-btn>
</q-td>
<q-td
v-for="col in props.cols"
@ -301,10 +295,10 @@ onMounted(async () => {
<DialogForm
v-model:dialog="dialog"
v-model:data="district"
v-model:personalName="personalName"
v-model:dialogStatus="dialogStatus"
v-model:editId="editId"
:addData="addData"
v-model:personal-name="personalName"
v-model:dialog-status="dialogStatus"
v-model:edit-id="editId"
:add-data="addData"
:fetch-data="fetchData"
:edit-data="editData"
/>

View file

@ -1,30 +1,26 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import type { QTableProps } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useRouter, useRoute } from "vue-router";
import { usePersonalDataStore } from "@/modules/01_metadata/stores/personalStore";
import { useQuasar } from "quasar";
import DialogForm from "@/modules/01_metadata/components/personal/DialogForm.vue";
import { useRouter, useRoute } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import type { FormSubDistrict } from "@/modules/01_metadata/interface/response/personal/personal";
import { useCounterMixin } from "@/stores/mixin";
const rows = ref<FormSubDistrict[]>([]);
import type { FormSubDistrict } from "@/modules/01_metadata/interface/response/personal/personal";
import type { QTableProps } from "quasar";
import DialogForm from "@/modules/01_metadata/components/personal/DialogForm.vue"; // ,
const $q = useQuasar();
const router = useRouter();
const route = useRoute();
const id = ref<string>(route.params.id as string);
const idProvince = ref<string>(route.params.provinceId as string);
const store = usePersonalDataStore();
const mixin = useCounterMixin();
const {
dialogRemove,
messageError,
showLoader,
hideLoader,
success,
date2Thai,
} = mixin;
const { messageError, showLoader, hideLoader, success, date2Thai } =
useCounterMixin();
/**
* Table
*/
const columns = [
{
name: "name",
@ -82,16 +78,6 @@ const columns = [
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
] as const satisfies QTableProps["columns"];
const $q = useQuasar();
const editId = ref<string>("");
const filterKeyword = ref<string>("");
const dialog = ref<boolean>(false);
const subDistrict = ref<string>("");
const zipCode = ref<string>("");
const dialogStatus = ref<string>("");
const personalName = ref<string>("แขวง/ตำบล");
const visibleColumns = ref<string[]>([
"name",
"zipCode",
@ -100,16 +86,33 @@ const visibleColumns = ref<string[]>([
"lastUpdateFullName",
]);
const id = ref<string>(route.params.id as string); // /
const rows = ref<FormSubDistrict[]>([]); // /
const editId = ref<string>(""); // id /
const filterKeyword = ref<string>(""); //
const dialog = ref<boolean>(false); // ,
const subDistrict = ref<string>(""); // / ;
const zipCode = ref<string>(""); //
const dialogStatus = ref<string>(""); // ,
const personalName = ref<string>("แขวง/ตำบล"); //label input
/**
* fetch อมลรายการ ระดบการเขต/อำเภอ ตาม id ของแขวง/ตำบล
* - ดการกบขอม
* - กำหนด rows.value เทากบขอมลท respones
*/
async function fetchData() {
showLoader();
await http
.get(config.API.orgDistrict + `/${id.value}`)
.then(async (res) => {
const data = res.data.result.subDistricts;
const list = data.map((e: any) => ({
const data = await res.data.result.subDistricts;
const list = data.map((e: FormSubDistrict) => ({
...e,
createdAt: e.createdAt ? date2Thai(e.createdAt) : "",
lastUpdatedAt: e.lastUpdatedAt ? date2Thai(e.lastUpdatedAt) : "",
createdAt: e.createdAt ? date2Thai(new Date(e.createdAt)) : "",
lastUpdatedAt: e.lastUpdatedAt
? date2Thai(new Date(e.lastUpdatedAt))
: "",
}));
rows.value = list;
})
@ -121,6 +124,10 @@ async function fetchData() {
});
}
/**
* เพมขอมลรายการแขวง/ตำบล
* แล fetch อมลรายการ แขวง/ตำบล ใหม
*/
async function addData() {
await http
.post(config.API.orgSubDistrict, {
@ -128,8 +135,8 @@ async function addData() {
districtId: id.value,
zipCode: zipCode.value,
})
.then(() => {
fetchData();
.then(async () => {
await fetchData();
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
@ -140,6 +147,11 @@ async function addData() {
});
}
/**
* แกไขขอมลรายการแขวง/ตำบล
* แล fetch อมลรายการ แขวง/ตำบล ใหม
* @param idRow รายการแขวง/ตำบล
*/
async function editData(idRow: string) {
await http
.put(config.API.orgSubDistrict + `/${idRow}`, {
@ -147,8 +159,8 @@ async function editData(idRow: string) {
districtId: id.value,
zipCode: zipCode.value,
})
.then(() => {
fetchData();
.then(async () => {
await fetchData();
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
@ -159,23 +171,12 @@ async function editData(idRow: string) {
});
}
async function deleteData(id: string) {
await http
.delete(config.API.orgSubDistrict + `/${id}`)
.then(() => {
fetchData();
success($q, "ลบข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/**
* hook ทำงานเม Components กเรยกใชงาน
* แลวเรยก function fetch อมลรายการแขวง/ตำบล
*/
onMounted(async () => {
fetchData();
await fetchData();
});
</script>
@ -282,20 +283,6 @@ onMounted(async () => {
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<q-btn
color="red"
flat
dense
round
icon="mdi-delete"
clickable
@click.stop="
dialogRemove($q, async () => await deleteData(props.row.id))
"
v-close-popup
>
<q-tooltip>ลบขอม</q-tooltip>
</q-btn>
</q-td>
<q-td v-for="col in props.cols" :key="col.id">
<div>
@ -312,10 +299,10 @@ onMounted(async () => {
v-model:dialog="dialog"
v-model:data="subDistrict"
v-model:zipCode="zipCode"
v-model:personalName="personalName"
v-model:dialogStatus="dialogStatus"
v-model:editId="editId"
:addData="addData"
v-model:personal-name="personalName"
v-model:dialog-status="dialogStatus"
v-model:edit-id="editId"
:add-data="addData"
:fetch-data="fetchData"
:edit-data="editData"
/>

View file

@ -28,10 +28,16 @@ interface DataAssignment {
year: string;
}
interface MainTabs {
label: string;
value: string;
}
export type {
Pagination,
DataOption,
NewPagination,
ItemsMenu,
DataAssignment,
MainTabs,
};

View file

@ -49,4 +49,4 @@ interface FormSubDistrict {
name: string;
provinceId: string;
}
export type { DataResponse, DataRow,FormDistrict,FormSubDistrict };
export type { DataResponse, DataRow, FormDistrict, FormSubDistrict };

View file

@ -1,72 +1,48 @@
const calendarWorkPage = () =>
import("@/modules/01_metadata/views/calendar.vue");
const masterInsignia = () => import("@/modules/01_metadata/views/insignia.vue");
const detailInsignia = () =>
import("@/modules/01_metadata/components/insignia/InsigniaDetail.vue");
const personalPage = () => import("@/modules/01_metadata/views/personal.vue");
/**
*
*/
const personalPage = () =>
import("@/modules/01_metadata/views/01_personal.vue"); //ข้อมูลเกี่ยวกับบุคคล
const personalDistrict = () =>
import("@/modules/01_metadata/components/personal/province/01_District.vue");
import("@/modules/01_metadata/components/personal/province/01_District.vue"); // เขต/อำเภอ
const personalSubDistrict = () =>
import(
"@/modules/01_metadata/components/personal/province/02_SubDistrict.vue"
"@/modules/01_metadata/components/personal/province/02_SubDistrict.vue" // แขวง/ตำบล
);
const positionPage = () => import("@/modules/01_metadata/views/position.vue");
const positionLevelPage = () =>
import("@/modules/01_metadata/components/position/03ListLevel.vue");
const positionEmployeePage = () =>
import("@/modules/01_metadata/views/positionEmployee.vue");
const positionEmployeeLevelPage = () =>
import("@/modules/01_metadata/components/position-employee/03ListLevel.vue");
const IndicatorByPlan = () =>
import("@/modules/01_metadata/views/indicatorByPlan.vue");
const IndicatorByPlanDetail = () =>
import(
"@/modules/01_metadata/components/Indicators/indicatorByPlan/DetailView.vue"
);
const IndicatorByRole = () =>
import("@/modules/01_metadata/views/indicatorByRole.vue");
const IndicatorByRoleDetail = () =>
import(
"@/modules/01_metadata/components/Indicators/indicatorByRole/DetailView.vue"
);
const competencyPage = () =>
import("@/modules/01_metadata/views/competency.vue");
const competencyAddPage = () =>
import("@/modules/01_metadata/components/competency/AddPage.vue");
const StrategicView = () => import("@/modules/01_metadata/views/Strategic.vue");
const AssignmentView = () =>
import("@/modules/01_metadata/views/Assignment.vue");
const AssignmentDetailView = () =>
import(
"@/modules/01_metadata/components/Indicators/Assignment/DetailView.vue"
);
/**
*
*/
const positionPage = () =>
import("@/modules/01_metadata/views/02_position.vue"); //ข้อมูลตำแหน่งข้าราชการ ฯ
const positionLevelPage = () =>
import("@/modules/01_metadata/components/position/03ListLevel.vue"); //รายการระดับของประเภทตำแหน่งทั่วไป
/**
*
*/
const positionEmployeePage = () =>
import("@/modules/01_metadata/views/03_positionEmployee.vue"); //ข้อมูลตำแหน่งลูกจ้างประจำ
const positionEmployeeLevelPage = () =>
import("@/modules/01_metadata/components/position-employee/03ListLevel.vue"); //รายการระดับชั้นงานบริการพื้นฐาน
/**
*
*/
const calendarWorkPage = () =>
import("@/modules/01_metadata/views/04_calendar.vue"); //ข้อมูลปฏิทินวันหยุด
/**
*
*/
const masterInsignia = () =>
import("@/modules/01_metadata/views/05_insignia.vue"); //ข้อมูลเครื่องราชอิสริยาภรณ์
const detailInsignia = () =>
import("@/modules/01_metadata/components/insignia/InsigniaDetail.vue"); // รายการข้อมูลเครื่องราชอิสริยาภรณ์
export default [
{
path: "/master-data/calendar",
name: "masterCalendarWork",
component: calendarWorkPage,
meta: {
Role: ["SUPER_ADMIN"],
},
},
{
path: "/master-data/insignia",
name: "masterInsigniaPage",
component: masterInsignia,
meta: {
Role: ["SUPER_ADMIN"],
},
},
{
path: "/master-data/insignia/detail/:id",
name: "masterInsigniadetail",
component: detailInsignia,
meta: {
Role: ["SUPER_ADMIN"],
},
},
// ข้อมูลเกี่ยวกับบุคคล
{
path: "/master-data/personal",
name: "masterPersonal",
@ -91,6 +67,8 @@ export default [
Role: ["SUPER_ADMIN"],
},
},
// ข้อมูลตำแหน่งข้าราชการ ฯ
{
path: "/master-data/position",
name: "masterPosition",
@ -107,6 +85,8 @@ export default [
Role: ["SUPER_ADMIN"],
},
},
// ข้อมูลตำแหน่งลูกจ้างประจำ
{
path: "/master-data/position-employee",
name: "masterPositionEmployee",
@ -124,100 +104,29 @@ export default [
},
},
// ข้อมูลปฏิทินวันหยุด
{
path: "/KPI-indicator-plan",
name: "KPIIndicatorByPlan",
component: IndicatorByPlan,
path: "/master-data/calendar",
name: "masterCalendarWork",
component: calendarWorkPage,
meta: {
Role: ["SUPER_ADMIN"],
},
},
// ข้อมูลเครื่องราชอิสริยาภรณ์
{
path: "/KPI-indicator-plan/add",
name: "KPIIndicatorByPlan/Add",
component: IndicatorByPlanDetail,
path: "/master-data/insignia",
name: "masterInsigniaPage",
component: masterInsignia,
meta: {
Role: ["SUPER_ADMIN"],
},
},
{
path: "/KPI-indicator-plan/:id",
name: "KPIIndicatorByPlanByid",
component: IndicatorByPlanDetail,
meta: {
Role: ["SUPER_ADMIN"],
},
},
{
path: "/KPI-indicator-role",
name: "KPIIndicatorByRole",
component: IndicatorByRole,
meta: {
Role: ["SUPER_ADMIN"],
},
},
{
path: "/KPI-indicator-role/add",
name: "KPIIndicatorByRoleAdd",
component: IndicatorByRoleDetail,
meta: {
Role: ["SUPER_ADMIN"],
},
},
{
path: "/KPI-indicator-role/:id",
name: "KPIIndicatorByRoleByid",
component: IndicatorByRoleDetail,
meta: {
Role: ["SUPER_ADMIN"],
},
},
{
path: "/KPI-competency",
name: "KPICompetency",
component: competencyPage,
meta: {
Role: ["SUPER_ADMIN"],
},
},
{
path: "/KPI-competency/add",
name: "KPICompetencyAdd",
component: competencyAddPage,
meta: {
Role: ["SUPER_ADMIN"],
},
},
{
path: "/KPI-competency/:id",
name: "KPICompetencyByid",
component: competencyAddPage,
meta: {
Role: ["SUPER_ADMIN"],
},
},
{
path: "/strategic",
name: "strategic",
component: StrategicView,
meta: {
Role: ["SUPER_ADMIN"],
},
},
{
path: "/assignment",
name: "KPIAssignment",
component: AssignmentView,
meta: {
Role: ["SUPER_ADMIN"],
},
},
{
path: "/assignment/:id",
name: "KPIAssignmentById",
component: AssignmentDetailView,
path: "/master-data/insignia/detail/:id",
name: "masterInsigniadetail",
component: detailInsignia,
meta: {
Role: ["SUPER_ADMIN"],
},

View file

@ -1,18 +1,23 @@
import { defineStore } from "pinia";
import { ref } from "vue";
import { useCounterMixin } from "@/stores/mixin";
import type {
DataResponse,
DataRow,
} from "../interface/response/personal/personal";
import { useCounterMixin } from "@/stores/mixin";
const { date2Thai } = useCounterMixin();
export const usePersonalDataStore = defineStore("PersonalData", () => {
const row = ref<DataRow[]>([]);
const currentTab = ref<string>("list_prefix");
const row = ref<DataRow[]>([]); // ข้อมูลในตาราง
const currentTab = ref<string>("list_prefix"); // Tab ปัจจุบัน
function save(data: DataResponse[]) {
/**
* row.value
* @param data API
*/
async function save(data: DataResponse[]) {
const list = data.map((e) => ({
...e,
createdAt: e.createdAt ? date2Thai(e.createdAt) : "",
@ -20,9 +25,10 @@ export const usePersonalDataStore = defineStore("PersonalData", () => {
}));
row.value = list;
}
return {
save,
row,
currentTab
currentTab,
};
});

View file

@ -1,23 +1,22 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
/** importCompopnents*/
import ListPrefix from "@/modules/01_metadata/components/personal/01ListPrefix.vue";
import ListRank from "@/modules/01_metadata/components/personal/02ListRank.vue";
import ListBloodGroup from "@/modules/01_metadata/components/personal/03ListBloodGroup.vue";
import ListGender from "@/modules/01_metadata/components/personal/04ListGender.vue";
import ListReligion from "@/modules/01_metadata/components/personal/05ListReligion.vue";
import ListRelationship from "@/modules/01_metadata/components/personal/06ListRelationship.vue";
import ListEducation from "@/modules/01_metadata/components/personal/07ListEducationLevel.vue";
import ListProvince from "@/modules/01_metadata/components/personal/08ListProvince.vue";
/** importStores*/
import { usePersonalDataStore } from "@/modules/01_metadata/stores/personalStore";
/** use*/
import type { MainTabs } from "@/modules/01_metadata/interface/index/Main";
import ListPrefix from "@/modules/01_metadata/components/personal/01ListPrefix.vue"; //
import ListRank from "@/modules/01_metadata/components/personal/02ListRank.vue"; //
import ListGender from "@/modules/01_metadata/components/personal/03ListGender.vue"; //
import ListRelationship from "@/modules/01_metadata/components/personal/04ListRelationship.vue"; //
import ListBloodGroup from "@/modules/01_metadata/components/personal/05ListBloodGroup.vue"; //
import ListReligion from "@/modules/01_metadata/components/personal/06ListReligion.vue"; //
import ListProvince from "@/modules/01_metadata/components/personal/07ListProvince.vue"; //
import ListEducation from "@/modules/01_metadata/components/personal/08ListEducationLevel.vue"; //
const store = usePersonalDataStore();
const tabs = ref<Array<any>>([]);
const tabs = ref<Array<MainTabs>>([]); // Tab
/** HOOK*/
onMounted(() => {

View file

@ -1,314 +0,0 @@
<script setup lang="ts">
import { ref, onMounted, reactive, watch } from "vue";
import { useRouter } from "vue-router";
import { useQuasar, type QTableProps } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
/** importType*/
import type {
DataOption,
NewPagination,
DataAssignment,
} from "@/modules/01_metadata/interface/index/Main";
import type { FormFilterAssignment } from "@/modules/01_metadata/interface/request/Main";
import type { ResAssignment } from "@/modules/01_metadata/interface/response/Main";
/** importStore*/
import { useCounterMixin } from "@/stores/mixin";
const $q = useQuasar();
const router = useRouter();
const { showLoader, hideLoader, dialogRemove, success, messageError } =
useCounterMixin();
/** table*/
const columns = ref<QTableProps["columns"]>([
{
name: "including",
align: "left",
label: "รหัสตัวชี้วัด",
sortable: true,
field: "including",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "includingName",
align: "left",
label: "ชื่อตัวชี้วัด",
sortable: true,
field: "includingName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
]);
const visibleColumns = ref<string[]>(["including", "includingName"]);
/** Option รอบการประเมิน*/
const roundOp = ref<DataOption[]>([
{ id: "APR", name: "รอบเมษายน" },
{ id: "OCT", name: "รอบตุลาคม" },
]);
const rows = ref<DataAssignment[]>([]);
const formFilter = reactive<FormFilterAssignment>({
keyword: "",
period: "",
year: new Date().getFullYear(),
pageSize: 10,
page: 1,
});
const totalList = ref<number>(0); //
const maxPage = ref<number>(1);
function fetchList() {
showLoader();
formFilter.year = formFilter.year ? formFilter.year.toString() : null;
http
.post(config.API.kpiSpecial + `/search`, formFilter)
.then((res: ResAssignment) => {
maxPage.value = Math.ceil(res.data.result.total / formFilter.pageSize);
totalList.value = res.data.result.total;
rows.value = res.data.result.data;
})
.catch((err) => {
messageError($q, err);
rows.value = [];
})
.finally(() => {
hideLoader();
});
}
function onClickView(id: string = "") {
router.push(`/assignment/${id}`);
}
function onClickDelete(id: string) {
dialogRemove($q, () => {
showLoader();
http
.delete(config.API.kpiSpecial + `/${id}`)
.then(() => {
fetchList();
success($q, "ลบข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
});
}
function fetchNewList() {
formFilter.page = 1;
fetchList();
}
function updatePageSize(newPagination: NewPagination) {
formFilter.page = 1;
formFilter.pageSize = newPagination.rowsPerPage;
}
watch(
() => formFilter.pageSize,
() => {
fetchList();
}
);
onMounted(() => {
fetchList();
});
</script>
<template>
<div class="toptitle text-dark col-12 row items-center">
รายการงานทไดบมอบหมาย
</div>
<q-card flat bordered class="q-pa-md">
<div class="row q-col-gutter-sm q-pl-sm">
<q-toolbar style="padding: 0">
<div class="row q-gutter-sm">
<datepicker
style="width: 150px"
menu-class-name="modalfix"
v-model="formFilter.year"
:locale="'th'"
autoApply
year-picker
:enableTimePicker="false"
@update:model-value="(formFilter.period = ''), fetchNewList()"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
dense
outlined
:model-value="
formFilter.year === null
? 'ทั้งหมด'
: Number(formFilter.year) + 543
"
:label="`${'ปีงบประมาณ'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
<template v-if="formFilter.year" v-slot:append>
<q-icon
name="cancel"
@click.stop.prevent="
(formFilter.year = null), fetchNewList()
"
class="cursor-pointer"
/>
</template>
</q-input>
</template>
</datepicker>
<q-select
dense
outlined
v-model="formFilter.period"
:model-value="
formFilter.period === '' ? 'ทั้งหมด' : formFilter.period
"
:options="roundOp"
label="รอบการประเมิน"
option-label="name"
option-value="id"
emit-value
map-options
@update:model-value="fetchNewList"
style="width: 160px"
>
<template v-if="formFilter.period" v-slot:append>
<q-icon
name="cancel"
@click.stop.prevent="(formFilter.period = ''), fetchNewList()"
class="cursor-pointer"
/>
</template>
</q-select>
</div>
<q-space />
<div class="row q-gutter-sm">
<q-input
dense
outlined
v-model="formFilter.keyword"
label="ค้นหา"
@keydown.enter="fetchNewList"
>
<template v-slot:append>
<q-icon
v-if="formFilter.keyword !== ''"
name="clear"
class="cursor-pointer"
@click="(formFilter.keyword = ''), fetchNewList()"
/>
<q-icon v-else name="search" color="grey-5" />
</template>
</q-input>
<q-select
v-model="visibleColumns"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns"
option-value="name"
options-cover
style="min-width: 150px"
/>
</div>
</q-toolbar>
</div>
<div class="col-12">
<d-table
for="table"
ref="table"
:columns="columns"
:rows="rows"
row-key="id"
flat
bordered
dense
class="custom-header-table"
:rows-per-page-options="[10, 25, 50, 100]"
:visible-columns="visibleColumns"
@update:pagination="updatePageSize"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
<q-th auto-width />
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props" class="cursor-pointer">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div class="table_ellipsis">
{{ col.value ? col.value : "-" }}
</div>
</q-td>
<q-td auto-width>
<q-btn
flat
round
color="primary"
size="14px"
icon="mdi-eye"
@click.pervent="onClickView(props.row.id)"
>
<q-tooltip>อม</q-tooltip>
</q-btn>
<q-btn
flat
round
color="red"
icon="mdi-delete "
@click.pervent="onClickDelete(props.row.id)"
>
<q-tooltip>ลบขอม</q-tooltip>
</q-btn>
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
งหมด {{ totalList }} รายการ
<q-pagination
v-model="formFilter.page"
active-color="primary"
color="dark"
:max="maxPage"
:max-pages="5"
size="sm"
boundary-links
direction-links
@update:model-value="fetchList"
></q-pagination>
</template>
</d-table>
</div>
</q-card>
</template>
<style scoped></style>

View file

@ -1,375 +0,0 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import type { ItemsMenu } from "@/modules/01_metadata/interface/index/Main";
import type { DataStrategic } from "@/modules/01_metadata/interface/response/Strategic";
import DialogHeader from "@/components/DialogHeader.vue";
import { useCounterMixin } from "@/stores/mixin";
const $q = useQuasar();
const {
showLoader,
hideLoader,
dialogConfirm,
dialogRemove,
messageError,
success,
} = useCounterMixin();
const ListMenu = ref<ItemsMenu[]>([
{
label: "เพิ่ม",
icon: "add",
value: "ADD",
color: "primary",
},
{
label: "แก้ไข",
icon: "edit",
value: "EDIT",
color: "edit",
},
{
label: "ลบ",
icon: "delete",
value: "DEL",
color: "red",
},
]);
const nodes = ref<any[]>([]);
const filter = ref<string>("");
const expanded = ref<Array<string>>([]);
const nodeId = ref<string>("");
const modalDialog = ref<boolean>(false);
const isStatusEdit = ref<boolean>(false);
const strategicName = ref<string>("");
const levelnode = ref<number>(0);
const titleDialog = ref<string>("");
/** ดึงข้อมูล ในรูปแบบ tree */
function fetchDataTree() {
showLoader();
http
.get(config.API.devStrategy)
.then((res) => {
const data: DataStrategic[] = res.data.result;
nodes.value = data;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/**
* เพ ลบ แกไข
* @param type ประเภท node
* @param data อม
*/
function onClickAction(type: string, data: DataStrategic | null = null) {
switch (type) {
case "ADD":
onClickOpenDialog(false, data);
break;
case "EDIT":
onClickOpenDialog(true, data);
break;
case "DEL":
data && onDelete(data);
break;
default:
break;
}
}
/**
* เป dialog
* @param status true/false
* @param data อมลยทธศาสตร
*/
function onClickOpenDialog(
status: boolean = false,
data: DataStrategic | null = null
) {
isStatusEdit.value = status;
if (status) {
if (data) {
nodeId.value = data.id;
strategicName.value = data.name;
levelnode.value = data.level;
titleDialog.value =
data.level === 1
? "ยุทธศาสตร์/แผน"
: data.level === 2
? "ยุทธศาสตร์ที่"
: data.level === 3
? "ยุทธศาสตร์ย่อย"
: data.level === 4
? "กลยุทธ์ที่/เป้าประสงค์ที่"
: "";
}
} else {
if (data) {
titleDialog.value =
data.level === 1
? "ยุทธศาสตร์ที่"
: data.level === 2
? "ยุทธศาสตร์ย่อย"
: data.level === 3
? "กลยุทธ์ที่/เป้าประสงค์ที่"
: "";
levelnode.value = data.level;
nodeId.value = data.id;
} else {
levelnode.value = 0;
titleDialog.value = "ยุทธศาสตร์/แผน";
}
}
modalDialog.value = true;
}
/** ปิด dialog */
function closeDialog() {
modalDialog.value = false;
strategicName.value = "";
}
/** บันทึกข้อมูล */
function onSubmit() {
dialogConfirm($q, async () => {
const formData = {
idnode: levelnode.value === 0 ? "0" : nodeId.value,
levelnode: levelnode.value,
name: strategicName.value,
};
try {
const method = isStatusEdit.value ? "patch" : "post";
await http[method](config.API.devStrategy, formData);
fetchDataTree();
success($q, "บันทึกข้อมูลสำเร็จ");
} catch (err) {
messageError($q, err);
} finally {
hideLoader();
closeDialog();
}
});
}
/** ลบข้อมูลตาม id */
function onDelete(data: DataStrategic) {
dialogRemove($q, () => {
showLoader();
const formData = {
idnode: data.id,
levelnode: data.level,
};
http
.delete(config.API.devStrategy, { data: formData })
.then(() => {
fetchDataTree();
success($q, "ลบข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
});
}
/** ดึงข้อมูลเมื่ออยู่ในหน้า */
onMounted(() => {
fetchDataTree();
});
</script>
<template>
<div class="toptitle text-dark col-12 row items-center">ทธศาสตร</div>
<q-card flat bordered class="q-pa-md">
<div class="row q-col-gutter-sm q-pl-sm">
<q-toolbar class="text-primary">
<q-btn
dense
flat
round
color="primary"
icon="add"
@click.stop="onClickAction('ADD')"
>
<q-tooltip>เพมยทธศาสตร</q-tooltip>
</q-btn>
<q-input dense outlined v-model="filter" label="ค้นหา">
<template v-slot:append>
<q-icon
v-if="filter !== ''"
name="clear"
class="cursor-pointer"
@click="filter = ''"
/>
<q-icon v-else name="search" color="grey-5" />
</template>
</q-input>
</q-toolbar>
</div>
<div class="bg-white tree-container q-pa-xs">
<q-tree
class="q-pa-sm q-gutter-sm"
dense
:nodes="nodes"
node-key="id"
label-key="name"
:filter="filter"
no-results-label="ไม่พบข้อมูลที่ค้นหา"
no-nodes-label="ไม่มีข้อมูล"
v-model:expanded="expanded"
>
<template v-slot:default-header="prop">
<q-item
clickable
@click.stop
:active="nodeId == prop.node.name"
active-class="my-list-link text-primary text-weight-medium"
class="row col-12 items-center text-dark q-py-xs q-pl-sm rounded-borders my-list"
>
<div>
<div class="text-weight-medium">
{{ prop.node.name }}
</div>
</div>
<q-btn
flat
dense
icon="mdi-dots-vertical"
class="q-ml-xs"
color="grey-13"
size="12px"
round
>
<q-menu>
<q-list
dense
v-for="(item, index) in prop.node.level !== 4
? ListMenu
: ListMenu.slice(1, 4)"
:key="index"
style="min-width: 100px"
>
<q-item
clickable
v-close-popup
@click.stop="onClickAction(item.value, prop.node)"
>
<q-item-section avatar style="min-width: 20px">
<q-icon
size="17px"
:color="item.color"
:name="item.icon"
/>
</q-item-section>
<div v-if="item.value === 'ADD'">
<q-item-section v-if="prop.node.level === 1">
{{ `${item.label}ยุทธศาสตร์ที่ 1` }}
</q-item-section>
<q-item-section v-if="prop.node.level === 2">
{{ `${item.label}ยุทธศาสตร์ย่อย` }}
</q-item-section>
<q-item-section v-if="prop.node.level === 3">
{{ `${item.label}กลยุทธ์ที่/เป้าประสงค์` }}
</q-item-section>
</div>
<div v-else-if="item.value === 'EDIT'">
<q-item-section v-if="prop.node.level === 1">
{{ `${item.label}ยุทธศาสตร์/แผน` }}
</q-item-section>
<q-item-section v-if="prop.node.level === 2">
{{ `${item.label}ยุทธศาสตร์ที่` }}
</q-item-section>
<q-item-section v-if="prop.node.level === 3">
{{ `${item.label}ยุทธศาสตร์ย่อย` }}
</q-item-section>
<q-item-section v-if="prop.node.level === 4">
{{ `${item.label}กลยุทธ์ที่/เป้าประสงค์` }}
</q-item-section>
</div>
<div v-else>
<q-item-section>{{ item.label }}</q-item-section>
</div>
</q-item>
</q-list>
</q-menu>
</q-btn>
</q-item>
</template>
</q-tree>
</div>
</q-card>
<q-dialog v-model="modalDialog" persistent>
<q-card style="width: 700px; max-width: 80vw">
<q-form greedy @submit.prevent @validation-success="onSubmit">
<DialogHeader
:tittle="`${
isStatusEdit ? `แก้ไข${titleDialog}` : `เพิ่ม${titleDialog}`
}`"
:close="closeDialog"
/>
<q-separator />
<q-card-section class="q-pt-none">
<div class="row q-pa-md">
<div class="col">
<q-input
dense
outlined
v-model="strategicName"
:label="`ชื่อ${titleDialog}`"
hide-bottom-space
lazy-rules
:rules="[
(val:string) =>
!!val || `${'กรุณากรอกชื่อ'}${titleDialog}`,
]"
/>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-actions align="right" class="bg-white text-teal">
<q-btn
dense
unelevated
label="บันทึก"
id="onSubmit"
type="submit"
color="public"
class="q-px-md"
>
<q-tooltip>นทกขอม</q-tooltip>
</q-btn>
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
</template>
<style lang="scss" scoped>
.tree-container {
overflow: auto;
height: 75vh;
}
</style>

View file

@ -1,72 +0,0 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import ListCompetency from "@/modules/01_metadata/components/competency/01ListCompetency.vue";
import ListLinkPosition from "@/modules/01_metadata/components/competency/02ListLinkPosition.vue";
import ListLinkGroup from "@/modules/01_metadata/components/competency/03ListLinkGroup.vue";
import ListCriteria from "@/modules/01_metadata/components/competency/04ListCriteria.vue";
import ListDetail from "@/modules/01_metadata/components/competency/05ListDetail.vue";
const currentTab = ref<string>("list_competency");
const tabs = ref<Array<any>>([]);
onMounted(() => {
const tab = [
{ label: "รายการสมรรถนะ", value: "list_competency" },
{ label: "กลุ่มงาน", value: "list_linkPosition" },
{ label: "เชื่อมโยงกับกลุ่มงานและตำแหน่ง", value: "list_linkGroup" },
{ label: "เกณฑ์การประเมิน", value: "list_criteria" },
{ label: "การประเมินพฤติกรรมการปฏิบัติราชการ", value: "list_detail" },
];
tabs.value = tab;
});
</script>
<template>
<div class="toptitle text-dark col-12 row items-center">สมรรถนะ</div>
<q-card flat bordered>
<div class="text-subtitle1 text-grey-9">
<q-tabs
dense
v-model="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 tabs"
:key="tab.value"
v-on:click="currentTab = tab.value"
:label="tab.label"
:name="tab.value"
class="q-py-xs"
/>
</q-tabs>
<q-separator />
<!-- person -->
<q-tab-panels v-model="currentTab" animated>
<q-tab-panel name="list_competency">
<ListCompetency v-if="currentTab == 'list_competency'" />
</q-tab-panel>
<q-tab-panel name="list_linkPosition">
<ListLinkPosition v-if="currentTab == 'list_linkPosition'" />
</q-tab-panel>
<q-tab-panel name="list_linkGroup">
<ListLinkGroup v-if="currentTab == 'list_linkGroup'" />
</q-tab-panel>
<q-tab-panel name="list_criteria">
<ListCriteria v-if="currentTab == 'list_criteria'" />
</q-tab-panel>
<q-tab-panel name="list_detail">
<ListDetail v-if="currentTab == 'list_detail'" />
</q-tab-panel>
</q-tab-panels>
</div>
</q-card>
</template>
<style scoped></style>

View file

@ -1,501 +0,0 @@
<script setup lang="ts">
import { ref, reactive, onMounted } from "vue";
import { useQuasar, type QTableProps } from "quasar";
import { useRouter } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import type { DataOption } from "@/modules/01_metadata/interface/index/Main";
import DialogHistory from "@/modules/01_metadata/components/Indicators/DialogHistory.vue";
/** importStore*/
import { useCounterMixin } from "@/stores/mixin";
/** use*/
const dataHistory = ref<any[]>([]);
const modalHistory = ref<boolean>(false);
const isAll = ref<boolean>(false);
const $q = useQuasar();
const router = useRouter();
const { showLoader, hideLoader, dialogRemove, success, messageError } =
useCounterMixin();
/** หัวตาราง */
const rows = ref<any[]>([]);
const columns = ref<QTableProps["columns"]>([
{
name: "including",
align: "left",
label: "ลำดับ/รหัสตัวชี้วัด",
sortable: true,
field: "including",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "includingName",
align: "left",
label: "ชื่อตัวชี้วัด",
sortable: true,
field: "includingName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
]);
const node = ref<any>([]);
const expanded = ref<any>([]);
const filterMain = ref<string>("");
const visibleColumns = ref<string[]>(["including", "includingName"]);
const roundOp = ref<DataOption[]>([
{ id: "APR", name: "รอบเมษายน" },
{ id: "OCT", name: "รอบตุลาคม" },
]);
const totalList = ref<number>(1);
const year = ref<number | null>(new Date().getFullYear());
const nodeData = reactive<any>({
page: 1,
pageSize: 10,
round: "",
nodeId: null,
node: null,
keyword: "",
});
function fetchList() {
showLoader();
http
.post(config.API.kpiPlan + `/search`, {
isAll: isAll.value,
keyword: nodeData.keyword,
node: nodeData.node ? nodeData.node : 0,
nodeId: nodeData.nodeId,
period: nodeData.round,
year: year.value?.toString(),
pageSize: nodeData.pageSize,
page: nodeData.page,
})
.then((res) => {
const data = res.data.result.data;
totalList.value = Math.ceil(res.data.result.total / nodeData.pageSize);
rows.value = data;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
function onClickAddOrView(status: boolean = false, id: string = "") {
status
? router.push(`/KPI-indicator-plan/${id}`)
: router.push("/KPI-indicator-plan/add");
}
function fetchActive() {
showLoader();
http
.get(config.API.activeOrganization)
.then((res) => {
const data = res.data.result;
fetchTree(data.activeId);
})
.catch((err) => {
messageError($q, err);
hideLoader();
});
}
async function fetchTree(id: string) {
showLoader();
http
.get(config.API.orgByid(id.toString()))
.then((res) => {
const data = res.data.result;
node.value = data;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
function updateSelectedTreeMain(data: any) {
if (nodeData.node === data.orgLevel && nodeData.nodeId === data.orgTreeId) {
nodeData.node = null;
nodeData.nodeId = null;
} else {
nodeData.node = data.orgLevel;
nodeData.nodeId = data.orgTreeId;
}
fetchListProjectNew();
}
function fetchListProjectNew() {
nodeData.page = 1;
fetchList();
}
async function deleteData(idData: string) {
dialogRemove($q, () =>
http
.delete(config.API.kpiPlanById(idData))
.then(() => {
fetchList();
success($q, "ลบข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
})
);
}
function clearFilter() {
nodeData.keyword = "";
fetchActive();
fetchListProjectNew();
}
/**
* เป dialog history
* @param id
*/
function onClickHistory(id: string) {
showLoader();
http
.get(config.API.kpiPlan + `/history/${id}`)
.then((res) => {
const data = res.data.result;
dataHistory.value = data;
modalHistory.value = true;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
onMounted(async () => {
await fetchActive();
await fetchList();
});
</script>
<template>
<div class="toptitle text-dark col-12 row items-center">
รายการตวชดตามแผนฯ
</div>
<q-card bordered class="col-12 row caedNone">
<div class="col-xs-12 col-sm-3 row">
<div class="col-12 row no-wrap">
<div class="col-12 q-py-sm q-px-sm">
<div class="q-gutter-sm">
<div class="text-subtitle2 text-bold">หนวยงาน/วนราชการ</div>
<q-input dense outlined v-model="filterMain" label="ค้นหา">
<template v-slot:append>
<q-icon
v-if="filterMain !== ''"
name="clear"
class="cursor-pointer"
@click="filterMain = ''"
/>
<q-icon v-else name="search" color="grey-5" />
</template>
</q-input>
<q-tree
class="tree-container"
dense
:nodes="node"
node-key="orgTreeName"
label-key="labelName"
v-model:expanded="expanded"
:filter="filterMain"
no-results-label="ไม่พบข้อมูลที่ค้นหา"
no-nodes-label="ไม่มีข้อมูล"
v-model:selected="nodeData.nodeId"
>
<template v-slot:default-header="prop">
<q-item
clickable
@click.stop="updateSelectedTreeMain(prop.node)"
:active="nodeData.nodeId === prop.node.orgTreeId"
active-class="my-list-link text-primary text-weight-medium"
class="row col-12 items-center text-dark q-py-xs q-pl-sm rounded-borders my-list"
>
<div>
<div class="text-weight-medium">
{{ prop.node.orgTreeName }}
</div>
<div class="text-weight-light text-grey-8">
{{ prop.node.orgCode == null ? null : prop.node.orgCode }}
{{
prop.node.orgTreeShortName == null
? null
: prop.node.orgTreeShortName
}}
</div>
</div>
</q-item>
</template>
</q-tree>
</div>
</div>
<div class="col-12 row">
<q-separator :vertical="!$q.screen.lt.md" />
</div>
</div>
</div>
<div class="col-xs-12 col-sm-9 q-pa-md row">
<div class="col-12">
<div class="row q-col-gutter-sm items-center q-mb-sm no-wrap">
<datepicker
menu-class-name="modalfix"
v-model="year"
:locale="'th'"
autoApply
year-picker
:enableTimePicker="false"
style="width: 150px"
@update:model-value="fetchListProjectNew"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
dense
outlined
:model-value="year === null ? 'ทั้งหมด' : Number(year) + 543"
:label="`${'ปีงบประมาณ'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
<template v-if="year" v-slot:append>
<q-icon
name="cancel"
@click.stop.prevent="
(year = null), (nodeData.page = 1), fetchListProjectNew()
"
class="cursor-pointer"
/>
</template>
</q-input>
</template>
</datepicker>
<q-select
dense
outlined
v-model="nodeData.round"
:options="roundOp"
label="รอบการประเมิน"
option-label="name"
option-value="id"
emit-value
map-options
@update:model-value="fetchListProjectNew"
style="min-width: 120px"
>
<template v-if="nodeData.round" v-slot:append>
<q-icon
name="cancel"
@click.stop.prevent="
(nodeData.round = ''), fetchListProjectNew()
"
class="cursor-pointer"
/>
</template>
</q-select>
<q-btn
flat
round
dense
icon="add"
color="primary"
@click="onClickAddOrView()"
>
<q-tooltip>เพ</q-tooltip>
</q-btn>
<q-space />
<q-checkbox
keep-color
v-model="isAll"
label="แสดงทั้งหมด"
color="primary"
@update:model-value="fetchListProjectNew"
>
<q-tooltip
>แสดงตำแหนงทงหมดภายใตหนวยงาน/วนราชการทเลอก</q-tooltip
>
</q-checkbox>
<q-input
standout
dense
v-model="nodeData.keyword"
ref="filterRef"
outlined
style="width: 150px"
placeholder="ค้นหา"
@keydown.enter.prevent="fetchListProjectNew"
>
<template v-slot:append>
<q-icon v-if="nodeData.keyword == ''" name="search" />
<q-icon
v-if="nodeData.keyword !== ''"
name="clear"
class="cursor-pointer"
@click="clearFilter"
/>
</template>
</q-input>
<q-select
v-model="visibleColumns"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns"
option-value="name"
options-cover
style="min-width: 120px"
/>
</div>
<div class="col-12">
<d-table
for="table"
ref="table"
:columns="columns"
:rows="rows"
row-key="id"
flat
bordered
dense
class="custom-header-table"
:rows-per-page-options="[10, 25, 50, 100]"
:visible-columns="visibleColumns"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
<q-th auto-width />
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props" class="cursor-pointer">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div class="table_ellipsis">
{{ col.value ? col.value : "-" }}
</div>
</q-td>
<q-td auto-width>
<q-btn flat round color="grey" @click.stop icon="more_vert">
<q-menu>
<q-list style="min-width: 180px">
<q-item
clickable
v-close-popup
@click="onClickAddOrView(true, props.row.id)"
>
<q-item-section
style="min-width: 0px"
avatar
class="q-py-sm"
>
<q-tooltip>แกไขขอม</q-tooltip>
<q-icon
color="edit"
size="xs"
name="mdi-pencil-outline"
/>
</q-item-section>
<q-item-section>แกไขขอม</q-item-section>
</q-item>
<q-item
clickable
v-close-popup
@click="onClickHistory(props.row.id)"
>
<q-item-section
style="min-width: 0px"
avatar
class="q-py-sm"
>
<q-tooltip>ประวการแกไข</q-tooltip>
<q-icon color="info" size="xs" name="mdi-history" />
</q-item-section>
<q-item-section>ประวการแกไข</q-item-section>
</q-item>
<q-item
clickable
v-close-popup
@click.stop.pervent="deleteData(props.row.id)"
>
<q-item-section
style="min-width: 0px"
avatar
class="q-py-sm"
>
<q-tooltip>ลบขอม</q-tooltip>
<q-icon color="red" size="xs" name="mdi-delete" />
</q-item-section>
<q-item-section>ลบขอม</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</q-td>
</q-tr>
</template>
</d-table>
</div>
</div>
</div>
</q-card>
<DialogHistory v-model:modal="modalHistory" :rows="dataHistory" />
</template>
<style lang="scss" scoped>
.tree-container {
overflow: auto;
height: 73vh;
border: 1px solid #e6e6e7;
border-radius: 10px;
}
.my-list-link {
color: rgb(118, 168, 222);
border-radius: 5px;
background: #a3d3fb48 !important;
font-weight: 600;
border: 1px solid rgba(175, 185, 196, 0.217);
}
</style>

View file

@ -1,519 +0,0 @@
<script setup lang="ts">
import { ref, reactive, onMounted, watch } from "vue";
import { useQuasar, type QTableProps } from "quasar";
import { useRouter } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import type { FormListMainByRole } from "@/modules/01_metadata/interface/request/Main";
import type {
DataOption,
NewPagination,
} from "@/modules/01_metadata/interface/index/Main";
import DialogHistory from "@/modules/01_metadata/components/Indicators/DialogHistory.vue";
/** importStore*/
import { useCounterMixin } from "@/stores/mixin";
/** use*/
const dataHistory = ref<any[]>([]);
const modalHistory = ref<boolean>(false);
const total = ref<number>();
const $q = useQuasar();
const router = useRouter();
const { showLoader, hideLoader, dialogRemove, success, messageError } =
useCounterMixin();
const positionOp = ref<DataOption[]>([]);
const positionMainOp = ref<DataOption[]>([]);
const maxPage = ref<number>(1);
const totalList = ref<number>(1); //
/** หัวตาราง */
const rows = ref<any>([]);
const columns = ref<QTableProps["columns"]>([
// {
// name: "no",
// align: "left",
// label: " ",
// sortable: true,
// field: "no",
// headerStyle: "font-size: 14px",
// style: "font-size: 14px",
// },
{
name: "including",
align: "left",
label: "รหัสตัวชี้วัด",
sortable: true,
field: "including",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "includingName",
align: "left",
label: "ชื่อตัวชี้วัด",
sortable: true,
field: "includingName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
]);
const visibleColumns = ref<string[]>(["including", "includingName"]);
const formFilter = reactive<FormListMainByRole>({
page: 1,
pageSize: 10,
position: "",
round: "",
keyword: "",
year: new Date().getFullYear(),
});
const pagination = ref({
page: formFilter.page,
rowsPerPage: formFilter.pageSize,
});
/** Option รอบการประเมิน*/
const roundOp = ref<DataOption[]>([
{ id: "APR", name: "รอบเมษายน" },
{ id: "OCT", name: "รอบตุลาคม" },
]);
function fetchList() {
http
.post(config.API.kpiRoleMainList + `/search`, {
// ?page=${formFilter.page}&pageSize=${formFilter.pageSize}&period=${formFilter.round}&position=${formFilter.position}&keyword=${formFilter.keyword}&year=${formFilter.year}
keyword: formFilter.keyword,
position: formFilter.position,
period: formFilter.round,
node: 0,
nodeId: "",
year: formFilter.year?.toString(),
pageSize: formFilter.pageSize,
page: formFilter.page,
})
.then((res) => {
const data = res.data.result.data;
total.value = res.data.result.total;
maxPage.value = Math.ceil(res.data.result.total / formFilter.pageSize);
rows.value = data;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
function onClickAddOrView(status: boolean = false, id: string = "") {
status
? router.push(`/KPI-indicator-role/${id}`)
: router.push("/KPI-indicator-role/add");
}
function onClickDelete(id: number) {
dialogRemove($q, () => {
showLoader();
http
.delete(config.API.kpiRoleMainList + `/${id}`)
.then(() => {
success($q, "ลบข้อมูลสำเร็จ");
fetchList();
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
});
}
function updatePage(val: number) {
formFilter.page = val;
fetchList();
}
function updatePageSize(newPagination: NewPagination) {
formFilter.page = 1;
formFilter.pageSize = newPagination.rowsPerPage;
}
watch(
() => formFilter.pageSize,
() => {
fetchList();
}
);
/**
* function นหาขอมลของ Option
* @param val าทองการฟลเตอร
* @param update พเดทค
* @param refData ดาตาทองการฟลเตอร
*/
function filterOption(val: any, update: Function) {
update(() => {
positionOp.value = positionMainOp.value.filter(
(v: any) => v.name.indexOf(val) > -1
);
});
}
/** ดึงข้อมูลตำแหน่ง */
function getOptions() {
showLoader();
http
.get(config.API.orgSalaryPosition)
.then((res) => {
const dataOp = res.data.result;
const uniqueNames = new Set();
const filteredData = dataOp
.filter((item: any) => {
if (!uniqueNames.has(item.positionName)) {
uniqueNames.add(item.positionName);
return true;
}
return false;
})
.map((item: any) => ({
id: item.positionName,
name: item.positionName,
}));
positionMainOp.value = filteredData;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
function statusTothai(val: string) {
switch (val) {
case "SPECIAL":
return "รอบพิเศษ";
case "APR":
return "รอบเมษายน";
case "OCT":
return "รอบตุลาคม";
default:
return "-";
}
}
function setModel(val: string) {
formFilter.position = val;
}
/**
* เป dialog history
* @param id
*/
function onClickHistory(id: string) {
showLoader();
http
.get(config.API.kpiRoleMainList + `/history/${id}`)
.then((res) => {
const data = res.data.result;
dataHistory.value = data;
modalHistory.value = true;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
onMounted(async () => {
await getOptions();
await fetchList();
});
</script>
<template>
<div class="toptitle text-dark col-12 row items-center">
รายการตวชดตามตำแหน
</div>
<q-card flat bordered class="q-pa-md">
<div class="row q-gutter-sm no-wrap q-mb-sm">
<q-select
dense
:model-value="formFilter.position"
label="ตำแหน่ง"
outlined
emit-value
map-options
fill-input
hide-selected
hide-bottom-space
option-label="name"
option-value="id"
:options="positionOp"
use-input
@input-value="setModel"
@filter="(inputValue:any,doneFn:Function) => filterOption(inputValue, doneFn) "
@update:model-value="fetchList"
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey"> ไมอม </q-item-section>
</q-item>
</template>
<template v-if="formFilter.position" v-slot:append>
<q-icon
name="cancel"
@click.stop.prevent="
formFilter.position = '';
fetchList();
"
class="cursor-pointer"
/>
</template>
</q-select>
<datepicker
style="width: 150px"
menu-class-name="modalfix"
v-model="formFilter.year"
:locale="'th'"
autoApply
year-picker
:enableTimePicker="false"
@update:model-value="(formFilter.page = 1), fetchList()"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
dense
outlined
:model-value="
formFilter.year === null
? 'ทั้งหมด'
: Number(formFilter.year) + 543
"
:label="`${'ปีงบประมาณ'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
<template v-if="formFilter.year" v-slot:append>
<q-icon
name="cancel"
@click.stop.prevent="
(formFilter.year = null), (formFilter.page = 1), fetchList()
"
class="cursor-pointer"
/>
</template>
</q-input>
</template>
</datepicker>
<q-select
dense
outlined
v-model="formFilter.round"
:options="roundOp"
label="รอบการประเมิน"
option-label="name"
option-value="id"
emit-value
map-options
@update:model-value="fetchList"
style="width: 160px"
>
<template v-if="formFilter.round" v-slot:append>
<q-icon
name="cancel"
@click.stop.prevent="(formFilter.round = ''), fetchList()"
class="cursor-pointer"
/>
</template>
</q-select>
<q-btn
flat
round
dense
icon="add"
color="primary"
@click="onClickAddOrView()"
>
<q-tooltip>เพ</q-tooltip>
</q-btn>
<q-space />
<q-input
standout
dense
v-model="formFilter.keyword"
ref="filterRef"
outlined
debounce="300"
placeholder="ค้นหา"
@keyup.enter="fetchList()"
>
<template v-slot:append>
<q-icon v-if="formFilter.keyword == ''" name="search" />
<q-icon
v-if="formFilter.keyword !== ''"
name="clear"
class="cursor-pointer"
@click="formFilter.keyword = ''"
/>
</template>
</q-input>
<q-select
v-model="visibleColumns"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns"
option-value="name"
options-cover
style="min-width: 150px"
/>
</div>
<div class="col-12">
<d-table
for="table"
ref="table"
:columns="columns"
:rows="rows"
row-key="subject"
flat
bordered
dense
class="custom-header-table"
:visible-columns="visibleColumns"
:rows-per-page-options="[10, 20, 50, 100]"
@update:pagination="updatePageSize"
>
<template v-slot:pagination="scope">
งหมด {{ total }} รายการ
<q-pagination
v-model="formFilter.page"
active-color="primary"
color="dark"
:max="maxPage"
:max-pages="5"
size="sm"
boundary-links
direction-links
@update:model-value="updatePage"
></q-pagination>
</template>
<template v-slot:header="props">
<q-tr :props="props">
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
<q-th auto-width />
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props" class="cursor-pointer">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name === 'no'">
{{
(formFilter.page - 1) * Number(pagination.rowsPerPage) +
props.rowIndex +
1
}}
</div>
<div v-else class="table_ellipsis">
{{ col.value ? col.value : "-" }}
</div>
</q-td>
<q-td auto-width>
<q-btn flat round color="grey" @click.stop icon="more_vert">
<q-menu>
<q-list style="min-width: 180px">
<q-item
clickable
v-close-popup
@click.stop.pervent="onClickAddOrView(true, props.row.id)"
>
<q-item-section
style="min-width: 0px"
avatar
class="q-py-sm"
>
<q-tooltip>แกไขขอม</q-tooltip>
<q-icon
color="edit"
size="xs"
name="mdi-pencil-outline"
/>
</q-item-section>
<q-item-section>แกไขขอม</q-item-section>
</q-item>
<q-item
clickable
v-close-popup
@click="onClickHistory(props.row.id)"
>
<q-item-section
style="min-width: 0px"
avatar
class="q-py-sm"
>
<q-tooltip>ประวการแกไข</q-tooltip>
<q-icon color="info" size="xs" name="mdi-history" />
</q-item-section>
<q-item-section>ประวการแกไข</q-item-section>
</q-item>
<q-item
clickable
v-close-popup
@click.stop.pervent="onClickDelete(props.row.id)"
>
<q-item-section
style="min-width: 0px"
avatar
class="q-py-sm"
>
<q-tooltip>ลบขอม</q-tooltip>
<q-icon color="red" size="xs" name="mdi-delete" />
</q-item-section>
<q-item-section>ลบขอม</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</q-td>
</q-tr>
</template>
</d-table>
</div>
</q-card>
<DialogHistory v-model:modal="modalHistory" :rows="dataHistory" />
</template>
<style scoped></style>