Merge branch 'develop'

This commit is contained in:
Warunee Tamkoo 2025-08-05 11:00:41 +07:00
commit 3c7c9392fb
19 changed files with 383 additions and 640 deletions

View file

@ -5,7 +5,7 @@ const profile = `${env.API_URI}/profile/keycloak`;
export default {
profileBykeycloak: () => `${profile}`,
positionBykeycloak: () => `${env.API_URI}/org/profile/keycloak/position`,
// positionBykeycloak: () => `${env.API_URI}/org/profile/keycloak/position`,
appealMainList: (
status: string,

View file

@ -0,0 +1,36 @@
<script setup lang="ts">
import { computed } from "vue";
/** importType*/
import type { QTableProps } from "quasar";
const columns = defineModel<QTableProps["columns"]>("columns", {
required: true,
});
/** จำนวนคอลัมน์ */
const skeletonColumns = computed(() => columns.value?.length || 5);
/** ตัวอย่างการใช้งาน */
/// <SkeletonTable v-if="isLoading" :columns="columns" />
</script>
<template>
<q-markup-table flat bordered>
<thead>
<tr>
<th v-for="(n, idx) in skeletonColumns" :key="idx" style="width: 150px">
<q-skeleton type="text" />
</th>
</tr>
</thead>
<tbody>
<tr v-for="n in 5" :key="n" :class="n % 2 === 0 ? 'bg-grey-2' : ''">
<td v-for="(col, idx) in skeletonColumns" :key="idx">
<q-skeleton type="text" width="80px" />
</td>
</tr>
</tbody>
</q-markup-table>
</template>

View file

@ -10,7 +10,7 @@ interface ProfileData {
posNo: string;
profileId: string;
citizenId?: string;
salary?: number|null;
salary?: number | null;
birthDate?: string;
keycloakId?: string;
org?: string;
@ -35,4 +35,64 @@ interface InformationData {
email: string;
}
export type { ProfileData, InformationData };
interface DataProfile {
amountSpecial: number;
avatar: string;
avatarName: string;
birthDate: string;
child1: string;
child1DnaId: string;
child1Id: string;
child1ShortName: string;
child2: string;
child2DnaId: string;
child2Id: string;
child2ShortName: string;
child3: string;
child3DnaId: string;
child3Id: string;
child3ShortName: string;
child4: string | null;
child4DnaId: string | null;
child4Id: string | null;
child4ShortName: string | null;
citizenId: string;
dateRetireLaw: string;
dateStart: string;
firstName: string;
isDirector: boolean;
isProbation: boolean;
keycloak: string;
lastName: string;
leaveDate: string | null;
node: number;
nodeDnaId: string;
nodeId: string;
nodeShortName: string;
posExecutiveId: string | null;
posExecutiveName: string | null;
posExecutivePriority: number | null;
posLevelId: string;
posLevelName: string;
posLevelRank: number;
posMaster: number;
posMasterNo: number;
posNo: string;
posTypeId: string;
posTypeName: string;
posTypeRank: number;
position: string;
positionArea: string | null;
positionExecutiveField: string | null;
prefix: string;
profileId: string;
profileType: string;
rank: string | null;
root: string;
rootDnaId: string;
rootId: string;
rootShortName: string;
salary: number;
}
export type { ProfileData, InformationData, DataProfile };

View file

@ -9,8 +9,10 @@ import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useEvaluateDetailStore } from "@/modules/06_evaluate/stores/evaluteDetail";
import { useEvaluateStore } from "@/modules/06_evaluate/store";
import { useDataStore } from "@/stores/data";
/** importType*/
import type { DataProfile } from "@/interface/Main";
import type {
EducationForm,
CertificatesForm,
@ -24,6 +26,7 @@ import HeaderDialog from "@/components/DialogHeader.vue";
const mixin = useCounterMixin();
const store = useEvaluateDetailStore();
const storeEva = useEvaluateStore();
const storeData = useDataStore();
const $q = useQuasar();
const route = useRoute();
const { showLoader, hideLoader, messageError, date2Thai, findOrgNameHtml } =
@ -75,34 +78,39 @@ const formDetail = reactive<any>({
/** function เรียกข้อมูลตรวจสอบคุณสมบัติ*/
async function fetchDetail() {
await http
.get(config.API.positionBykeycloak())
.then(async (res) => {
const data = await res.data.result;
formDetail.root = data.root;
formDetail.rootId = data.rootId;
formDetail.userId = data.id;
formDetail.citizenId = data.citizenId;
formDetail.prefix = data.prefix;
formDetail.fullName = `${data.firstName} ${data.lastName}`;
formDetail.firstName = data.firstName;
formDetail.lastName = data.lastName;
formDetail.position = data.position;
formDetail.oc = data.rootShortName;
formDetail.positionLevel = data.posLevelName;
formDetail.posNo = data.posNo ?? "";
formDetail.birthDate = data.birthDate;
// formDetail.govAge = data.govAge; //
formDetail.salary = data.salary;
formDetail.posExecutive = data.posExecutive;
formDetail.positionArea = data.positionArea;
await fetchDataAllDetail();
try {
if (!storeData.dataprofilePosition) {
const res = await http.get(config.API.profilePosition());
await updateFormDetail(res.data.result);
} else {
await updateFormDetail(storeData.dataprofilePosition);
}
} catch (error) {
messageError($q, error);
}
}
emit("update:formDeital", formDetail);
})
.catch((err) => {
messageError($q, err);
});
async function updateFormDetail(data: DataProfile) {
formDetail.root = data.root;
formDetail.rootId = data.rootId;
formDetail.userId = data.profileId;
formDetail.citizenId = data.citizenId;
formDetail.prefix = data.prefix;
formDetail.fullName = `${data.firstName} ${data.lastName}`;
formDetail.firstName = data.firstName;
formDetail.lastName = data.lastName;
formDetail.position = data.position;
formDetail.oc = data.rootShortName;
formDetail.positionLevel = data.posLevelName;
formDetail.posNo = data.posNo ?? "";
formDetail.birthDate = data.birthDate;
// formDetail.govAge = data.govAge; //
formDetail.salary = data.salary;
formDetail.posExecutive = data.posExecutiveName;
formDetail.positionArea = data.positionArea;
await fetchDataAllDetail();
emit("update:formDeital", formDetail);
}
async function fetchDataAllDetail() {

View file

@ -7,6 +7,7 @@ import http from "@/plugins/http";
import config from "@/app.config";
import { useEvaluateStore } from "@/modules/06_evaluate/store";
import { useCounterMixin } from "@/stores/mixin";
import { useDataStore } from "@/stores/data";
/** import Components*/
import TableListEvaluate from "@/modules/06_evaluate/components/TableListEvaluate.vue"; //
@ -20,6 +21,7 @@ import type { OptionStatus } from "@/modules/06_evaluate/interface/main";
const $q = useQuasar();
const mixin = useCounterMixin();
const store = useEvaluateStore();
const dataStore = useDataStore();
const router = useRouter();
const { showLoader, hideLoader, messageError } = mixin;
@ -86,7 +88,6 @@ async function fetchEvaluteList() {
);
total.value = res.data.result.total;
store.fetchEvaluateList(res.data.result.data);
await getProfileCheck();
})
.catch((err) => {
messageError($q, err);
@ -99,24 +100,33 @@ async function fetchEvaluteList() {
/** function เรียกรายการประเมิน*/
const statusSubmit = ref<boolean>(true);
async function getProfileCheck() {
await http
.get(config.API.profilePosition())
.then(async (res: any) => {
const data = res.data.result;
if (
data.posTypeRank != 2 ||
(data.posTypeRank == 2 && data.posLevelRank >= 4)
) {
statusSubmit.value = false;
} else {
listMenu.value = await listMenu.value.filter(
(x: ListMenu) => x.level > data.posLevelRank
);
}
})
.catch((err) => {
messageError($q, err);
});
if (!dataStore.dataprofilePosition) {
await http
.get(config.API.profilePosition())
.then(async (res: any) => {
const data = res.data.result;
checkProfilePosition(data);
})
.catch((err) => {
messageError($q, err);
});
} else {
const data = dataStore.dataprofilePosition;
checkProfilePosition(data);
}
}
function checkProfilePosition(data: any) {
if (
data.posTypeRank != 2 ||
(data.posTypeRank == 2 && data.posLevelRank >= 4)
) {
statusSubmit.value = false;
} else {
listMenu.value = listMenu.value.filter(
(x: ListMenu) => x.level > data.posLevelRank
);
}
}
const selectedStatus = ref<string[]>([
@ -191,6 +201,7 @@ watch(
/** hook lifecycle*/
onMounted(async () => {
await fetchEvaluteList();
await getProfileCheck();
});
</script>

View file

@ -6,15 +6,20 @@ import { useRouter, useRoute } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useDataStore } from "@/stores/data";
import Form from "@/modules/07_appealComplain/views/Form.vue";
import type { DataProfile } from "@/interface/Main";
import type {
FormProfile,
FormDataType,
} from "@/modules/07_appealComplain/interface/response/mainType";
const router = useRouter();
const $q = useQuasar();
const mixin = useCounterMixin();
const storeData = useDataStore();
const { findOrgName, success, messageError, showLoader, hideLoader } = mixin;
@ -27,24 +32,28 @@ const formProfile = reactive<FormProfile>({
});
/** ดึงข้อมูลจาก keycloak*/
function getProFile() {
showLoader();
http
.get(config.API.positionBykeycloak())
.then((res) => {
const data = res.data.result;
formProfile.profileId = data.profileId;
formProfile.fullname = `${data.prefix}${data.firstName} ${data.lastName}`;
formProfile.citizenId = data.citizenId;
formProfile.oc = findOrgName(data);
formProfile.position = data.position;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
async function getProFile() {
try {
showLoader();
if (!storeData.dataprofilePosition) {
const res = await http.get(config.API.profilePosition());
await updateFormProfile(res.data.result);
} else {
await updateFormProfile(storeData.dataprofilePosition);
}
} catch (error) {
messageError($q, error);
} finally {
hideLoader();
}
}
async function updateFormProfile(data: DataProfile) {
formProfile.profileId = data.profileId;
formProfile.fullname = `${data.prefix}${data.firstName} ${data.lastName}`;
formProfile.citizenId = data.citizenId;
formProfile.oc = findOrgName(data);
formProfile.position = data.position;
}
/**

View file

@ -2,6 +2,7 @@ import { defineStore } from "pinia";
import { ref, reactive } from "vue";
import type { DataOptions } from "./interface/index/Main";
import type { FormQuery } from "@/modules/08_KPI/interface/request/index";
import type { DataProfile } from "@/interface/Main";
export const useKpiDataStore = defineStore("KPIDate", () => {
const mainRowData = ref<any>();
@ -17,36 +18,64 @@ export const useKpiDataStore = defineStore("KPIDate", () => {
const selected = ref([]);
const work = ref<boolean>(false);
const tabMain = ref<string>("");
const dataProfile = ref<any>({
profileId: null,
prefix: "",
rank: "",
firstName: "",
lastName: "",
const dataProfile = ref<DataProfile>({
amountSpecial: 0,
avatar: "",
avatarName: "",
birthDate: "",
child1: "",
child1DnaId: "",
child1Id: "",
child1ShortName: "",
child2: "",
child2DnaId: "",
child2Id: "",
child2ShortName: "",
child3: "",
child3DnaId: "",
child3Id: "",
child3ShortName: "",
child4: "",
child4DnaId: "",
child4Id: "",
child4ShortName: "",
citizenId: "",
position: "",
posMaster: null,
posLevelName: null,
posLevelRank: null,
posLevelId: null,
posTypeName: null,
posTypeRank: null,
posTypeId: null,
posExecutiveName: "",
posExecutivePriority: null,
dateRetireLaw: "",
dateStart: "",
firstName: "",
isDirector: false,
isProbation: false,
keycloak: "",
lastName: "",
leaveDate: null,
node: 0,
nodeDnaId: "",
nodeId: "",
nodeShortName: "",
posExecutiveId: null,
rootId: null,
posExecutiveName: null,
posExecutivePriority: null,
posLevelId: "",
posLevelName: "",
posLevelRank: 0,
posMaster: 0,
posMasterNo: 0,
posNo: "",
posTypeId: "",
posTypeName: "",
posTypeRank: 0,
position: "",
positionArea: null,
positionExecutiveField: null,
prefix: "",
profileId: "",
profileType: "",
rank: null,
root: "",
child1Id: null,
child1: null,
child2Id: null,
child2: null,
child3Id: null,
child3: null,
child4Id: null,
child4: null,
node: null,
nodeId: null,
rootDnaId: "",
rootId: "",
rootShortName: "",
salary: 0,
});
const dataEvaluation = ref<any>({

View file

@ -478,15 +478,17 @@ async function fetchProfileEvaluator(id: string) {
/** ดึงข้อมูลโปรไฟล์ */
async function getProfile() {
await http
.get(config.API.profilePosition())
.then(async (res) => {
const data = await res.data.result;
store.dataProfile = await data;
})
.catch((e) => {
messageError($q, e);
});
if (!store.dataProfile.profileId) {
await http
.get(config.API.profilePosition())
.then((res) => {
const data = res.data.result;
store.dataProfile = data;
})
.catch((e) => {
messageError($q, e);
});
}
}
async function downloadReport() {

View file

@ -9,6 +9,7 @@ import http from "@/plugins/http";
import { useCounterMixin } from "@/stores/mixin";
import { useKpiDataStore } from "@/modules/08_KPI/store";
import type { DataProfile } from "@/interface/Main";
import type {
DataOptions,
MainListKpi,
@ -179,8 +180,13 @@ async function fetchRoundOption(type: string) {
}));
if (type === "main") {
roundMainOp.value = list;
round.value = "";
await fetchList();
if (data.length === 0) {
round.value = "";
rows.value = [];
} else {
round.value = roundMainOp.value[0].id;
await fetchList();
}
} else {
roundDialgOp.value = list;
formRound.kpiPeriodId = { id: "", name: "", isClosed: false };
@ -205,6 +211,7 @@ async function fetchList() {
kpiPeriodId: round.value,
status: formQuery.status === "" ? undefined : formQuery.status,
results: formQuery.results === "" ? undefined : formQuery.results,
year: year.value,
};
await http
.get(config.API.kpiEvaluation, {
@ -285,26 +292,34 @@ function onSubmit() {
}
/** ดึงข้อมูล */
function getProfile() {
http
.get(config.API.profilePosition())
.then(async (res) => {
const data = await res.data.result;
store.dataProfile = data;
async function getProfile() {
if (store.dataProfile.profileId) {
assignProfileToForm(store.dataProfile);
} else {
await http
.get(config.API.profilePosition())
.then(async (res) => {
const data = await res.data.result;
store.dataProfile = data;
assignProfileToForm(data);
})
.catch((e) => {
messageError($q, e);
});
}
}
formRound.profileId = data.profileId;
formRound.prefix = data.prefix;
formRound.firstName = data.firstName;
formRound.lastName = data.lastName;
formRound.position = data.position;
formRound.posLevelName = data.posLevelName;
formRound.posTypeName = data.posTypeName;
formRound.posExecutiveName = data.posExecutiveName;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {});
function assignProfileToForm(profile: DataProfile) {
formRound.profileId = profile.profileId ? profile.profileId : "";
formRound.prefix = profile.prefix ? profile.prefix : "";
formRound.firstName = profile.firstName ? profile.firstName : "";
formRound.lastName = profile.lastName ? profile.lastName : "";
formRound.position = profile.position ? profile.position : "";
formRound.posLevelName = profile.posLevelName ? profile.posLevelName : "";
formRound.posTypeName = profile.posTypeName ? profile.posTypeName : "";
formRound.posExecutiveName = profile.posExecutiveName
? profile.posExecutiveName
: "";
}
/** เช็ครอบการประเมิน ปิด */

View file

@ -93,7 +93,7 @@ const maxPage = ref<number>(1);
* งขอมลรายการขอรบประเมนผลการปฏราชการระดบบคคล
* @param type
*/
async function fetchRoundOption(type: boolean = false) {
async function fetchRoundOption() {
showLoader();
await http
.get(
@ -101,21 +101,25 @@ async function fetchRoundOption(type: boolean = false) {
`?page=${1}&pageSize=${10}&keyword=${""}&year=${store.yearRound}`
)
.then(async (res) => {
const data = await res.data.result.data;
const list = data.map((e: ResRound) => ({
id: e.id,
name:
e.durationKPI === "OCT"
? "รอบที่ 2 ตุลาคม"
: e.durationKPI === "APR"
? "รอบที่ 1 เมษายน"
: "",
}));
const data = res.data.result.data;
const list =
data.map((e: ResRound) => ({
id: e.id,
name:
e.durationKPI === "OCT"
? "รอบที่ 2 ตุลาคม"
: e.durationKPI === "APR"
? "รอบที่ 1 เมษายน"
: "",
})) ?? [];
roundOp.value = list;
if (type) {
if (data.length === 0) {
store.formQuery.round = "";
dataListMain.value = [];
} else {
store.formQuery.round = roundOp.value[0].id;
await fetchList();
}
await fetchList();
})
.catch((err) => {
messageError($q, err);
@ -131,8 +135,9 @@ async function fetchList() {
const body = {
page: store.formQuery.page,
pageSize: store.formQuery.pageSize,
kpiPeriodId: store.formQuery.round,
kpiPeriodId: store.formQuery.round ?? "",
keyword: store.formQuery.keyword,
year: store.yearRound,
status:
store.tabMainevaluator === "2"
? "NEW"
@ -225,7 +230,7 @@ onMounted(async () => {
year-picker
:enableTimePicker="false"
@update:model-value="
(store.formQuery.page = 1), fetchRoundOption(true)
(store.formQuery.page = 1), fetchRoundOption()
"
>
<template #year="{ year }">{{ year + 543 }}</template>

View file

@ -5,6 +5,7 @@ import { useQuasar, type QTableProps } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import { useDataStore } from "@/stores/data";
import { useCounterMixin } from "@/stores/mixin";
import type {
@ -17,7 +18,7 @@ const { showLoader, hideLoader, messageError } = mixin;
const router = useRouter();
const $q = useQuasar();
const dataStore = useDataStore();
const profilId = ref<string>("");
const currentPage = ref<number>(1);
const page = ref<number>(1);
@ -123,19 +124,22 @@ function onEdit(id: string) {
// );
async function getProfileId() {
showLoader();
await http
.get(config.API.profilePosition())
.then(async (res) => {
profilId.value = res.data.result.profileId;
await getData();
})
.catch((e) => {
if (dataStore.profileId) {
profilId.value = dataStore.profileId;
} else {
showLoader();
try {
const res = await http.get(config.API.profilePosition());
dataStore.profileId = res.data.result.profileId;
profilId.value = dataStore.profileId;
} catch (e) {
messageError($q, e);
})
.finally(() => {
} finally {
hideLoader();
});
}
}
await getData();
}
function convertType(val: string) {

View file

@ -16,7 +16,7 @@ import { useCounterMixin } from "@/stores/mixin";
* use
*/
const $q = useQuasar();
const link = ref<string>('')
const link = ref<string>("");
const store = useRequestEditStore();
const dataStore = useDataStore();
const { dialogConfirm, showLoader, hideLoader, messageError, success } =
@ -167,20 +167,16 @@ function filterOption(val: string, update: Function) {
/**
* function fetch profileId
*/
function fetchProfile() {
showLoader();
http
.get(config.API.profilePosition())
.then((res) => {
const data = res.data.result;
profileId.value = data.profileId;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
async function fetchProfile() {
try {
isReadOnly.value = dataStore.officerType === "OFFICER";
const res = await http.get(config.API.profilePosition());
return res.data.result.profileId;
} catch (err) {
messageError($q, err);
} finally {
hideLoader();
}
}
/** popup รายละเอียดของ ขอปรับปรุงข้อมูลจากกรมการปกครอง */
@ -194,7 +190,10 @@ function onInfo(val: string) {
watch(
() => modal.value,
async () => {
modal.value && fetchProfile();
profileId.value = dataStore.profileId
? dataStore.profileId
: await fetchProfile();
link.value = await dataStore.getProFileType();
}
);

View file

@ -1,5 +1,4 @@
// registry
const probationPage = () => import("@/modules/11_probation/views/main.vue");
const probationDetail = () =>
import("@/modules/11_probation/views/mainDetail.vue");
@ -34,15 +33,6 @@ const probationAddevaluascore = () =>
import("@/modules/11_probation/component/addPage/04_addevaluascore.vue");
export default [
{
path: "/probation",
name: "probationMain",
component: probationPage,
meta: {
Auth: true,
Key: [11],
},
},
{
path: "/probation-detail/:id",
name: "probationMainDetail",

View file

@ -1,430 +0,0 @@
<script setup lang="ts">
import avatar from "@/assets/avatar_user.jpg";
import { ref, reactive, onMounted } from "vue";
import { useCounterMixin } from "@/stores/mixin";
import { useRouter } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import { useQuasar, type QTableProps } from "quasar";
import type { ListMain } from "@/modules/11_probation/interface/index/main";
const profileId = ref<string>("");
const rows = ref<ListMain[]>([]);
const rowsData = ref<ListMain[]>([]);
const $q = useQuasar();
const mixin = useCounterMixin();
const {
messageError,
dialogConfirm,
findOrgName,
showLoader,
hideLoader,
date2Thai,
onSearchDataTable
} = mixin;
const filter = ref<string>("");
const mode = ref<any>($q.screen.gt.xs);
const profileImg = ref<string>("");
const router = useRouter();
const formData = reactive<any>({
prefix: "",
firstName: "",
lastName: "",
position: "",
posExecutiveName: "",
posTypeName: "",
posLevelName: "",
org: "",
});
const sizeImg = ref<string>("");
/** ข้อมูลที่เเสดงในตาราง */
const visibleColumns = ref<string[]>([
"no",
"date_start",
"date_finish",
"mentors",
"commander",
]);
/** หัวตาราง */
const columns = ref<QTableProps["columns"]>([
{
name: "no",
align: "left",
label: "ลำดับ",
sortable: false,
field: "no",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "date_start",
align: "left",
label: "ตั้งแต่วันที่",
sortable: true,
field: "date_start",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format: (v) => date2Thai(v),
},
{
name: "date_finish",
align: "left",
label: "ถึงวันที่",
sortable: true,
field: "date_finish",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format: (v) => date2Thai(v),
},
{
name: "mentors",
align: "left",
label: "ผู้ดูแล",
sortable: true,
field: "mentors",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "commander",
align: "left",
label: "ผู้บังคับบัญชา",
sortable: true,
field: "commander",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
]);
function onResize(size: any) {
const width = size.width > 100 ? 100 : size.width;
sizeImg.value = `${width}px`;
}
function onMobile(type: string) {
router.push(`/registry/${type}`);
}
function getMain() {
showLoader();
http
.get(config.API.profilePosition())
.then(async (res) => {
const data = res.data.result;
formData.prefix = data.prefix;
formData.firstName = data.firstName;
formData.lastName = data.lastName;
formData.position = data.position;
formData.posTypeName = data.posTypeName;
formData.posExecutiveName = data.posExecutiveName;
formData.posLevelName = data.posLevelName;
formData.org = findOrgName(data);
profileId.value = data.profileId;
if (data.avatarName) {
getImg(data.profileId, data.avatarName);
} else {
profileImg.value = avatar;
}
await getList(data.profileId);
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
function getList(id: string) {
http
.get(config.API.probationMain(id))
.then((res) => {
const data = res.data.data;
rows.value = data;
rowsData.value = data;
})
.catch((e) => {})
.finally(() => {});
}
function getImg(id: string, pathName: string) {
http
.get(config.API.fileByFile("ทะเบียนประวัติ", "โปรไฟล์", id, pathName))
.then((res) => {
profileImg.value = res.data.downloadUrl;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {});
}
function onDetail(id: string) {
router.push(`/probation/detail/${profileId.value}/${id}`);
}
function onSearch() {
rows.value = onSearchDataTable(
filter.value,
rowsData.value,
columns.value ? columns.value : []
);
}
onMounted(async () => {
await getMain();
});
</script>
<template>
<div class="row justify-center">
<div class="col-xs-12 col-sm-12 col-md-11">
<div class="toptitle text-white col-12 row items-center">
รายละเอยดงานทไดบมอบหมาย
</div>
<div class="row q-col-gutter-md">
<div v-if="$q.screen.gt.xs" class="col-12">
<q-card>
<div class="bg-grey-1 row q-pa-sm items-center">
<span class="text-teal text-weight-bold text-body2">{{
formData.firstName
? `${formData.prefix}${formData.firstName} ${formData.lastName}`
: "-"
}}</span>
</div>
<q-resize-observer @resize="onResize" />
<q-card-section class="q-pa-md">
<div class="row">
<div class="col-2 text-center self-center">
<q-avatar :size="sizeImg" rounded>
<img
:src="profileImg"
style="border-radius: 10px; object-fit: cover"
/>
</q-avatar>
</div>
<div class="col-10 column justify-center no-wrap">
<div class="row text-grey-6">
<div class="col-4">ตำแหนงในสายงาน</div>
<div class="col-4">ระด</div>
<div class="col-4">งก</div>
</div>
<div class="row">
<div class="col-4">
{{ formData.position ? formData.position : "-" }}
</div>
<div class="col-4">
{{ formData.posLevelName ? formData.posLevelName : "-" }}
</div>
<div class="col-4">
{{ formData.org ? formData.org : "-" }}
</div>
</div>
</div>
</div>
</q-card-section>
</q-card>
</div>
<div v-else class="col-12">
<q-card bordered>
<div class="bg-grey-1 row q-pa-sm items-center">
<span class="text-teal text-weight-bold text-body2">{{
formData.firstName
? `${formData.prefix}${formData.firstName} ${formData.lastName}`
: "-"
}}</span>
</div>
<q-resize-observer @resize="onResize" />
<q-card-section>
<div class="text-center q-mt-md">
<q-avatar :size="sizeImg" rounded>
<img
:src="profileImg"
style="border-radius: 10px; object-fit: cover"
/>
</q-avatar>
</div>
</q-card-section>
<q-list class="q-mt-md">
<q-item>
<q-item-section>
<q-item-label class="text-grey-6"
>ตำแหนงในสายงาน</q-item-label
>
<q-item-label>{{
formData.position ? formData.position : "-"
}}</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-item-label class="text-grey-6">ระด</q-item-label>
<q-item-label>{{
formData.posLevelName ? formData.posLevelName : "-"
}}</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-item-label class="text-grey-6">งก</q-item-label>
<q-item-label>{{
formData.org ? formData.org : "-"
}}</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-card>
</div>
<div class="col-12 row">
<q-card bordered class="col-12 q-pa-md">
<div class="row">
<q-btn
@click="router.push(`/probation/add/${profileId}`)"
flat
round
color="primary"
icon="mdi-plus"
>
<q-tooltip>เพมงานทไดบมอบหมาย</q-tooltip>
</q-btn>
<q-space />
<q-input
class="inputgreen"
outlined
dense
v-model="filter"
label="ค้นหา"
:style="mode ? `max-width: 200px` : `max-width: 150px`"
@keydown.enter.prevent="onSearch"
>
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
<q-select
v-if="$q.screen.gt.xs"
class="q-ml-sm"
dense
multiple
outlined
emit-value
map-options
options-dense
option-value="name"
style="min-width: 140px"
v-model="visibleColumns"
:options="columns"
:display-value="$q.lang.table.columns"
/>
</div>
<div class="q-mt-sm">
<d-table
flat
dense
bordered
ref="table"
virtual-scroll
:rows="rows"
:columns="columns"
:grid="!$q.screen.gt.xs"
:rows-per-page-options="[10, 25, 50, 100]"
:visible-columns="visibleColumns"
:virtual-scroll-sticky-size-start="48"
>
<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-if="$q.screen.gt.xs" v-slot:body="props">
<q-tr :props="props" class="cursor-pointer">
<q-td
v-for="(col, index) in props.cols"
:key="col.name"
@click="onDetail(props.row.id)"
>
<div v-if="col.name == 'no'">
{{ props.rowIndex + 1 }}
</div>
<div v-else-if="col.name == 'status'">
{{ props.row.status ? props.row.status : "-" }}
</div>
<div v-else>
{{ col.value ? col.value : "-" }}
</div>
</q-td>
</q-tr>
</template>
<template v-else v-slot:item="props">
<div class="q-mb-xs col-xs-12 col-sm-6 col-md-4 col-lg-3">
<q-card bordered flat>
<q-list dense class="q-mt-lg relative-position">
<q-btn
icon="info"
color="info"
flat
dense
round
size="14px"
class="absolute_button"
@click="onDetail(props.row.id)"
>
<q-tooltip>ประวแกไขตำแหน/เงนเดอน</q-tooltip>
</q-btn>
<q-item v-for="col in props.cols" :key="col.name">
<q-item-section class="fix_top">
<q-item-label
class="text-grey-6 text-weight-medium"
>{{ col.label }}</q-item-label
>
</q-item-section>
<q-item-section class="fix_top">
<q-item-label
class="text-dark text-weight-medium"
>{{ col.value ? col.value : "-" }}</q-item-label
>
</q-item-section>
</q-item>
</q-list>
</q-card>
</div>
</template>
<template v-slot:no-data>
<div
class="full-width row flex-center q-pa-sm rounded-borders text-weight-medium"
>
<span> ไมพบขอม </span>
</div>
</template>
</d-table>
</div>
</q-card>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.absolute_button {
position: absolute;
right: 5px;
top: -20px;
}
.fix_top {
justify-content: start !important;
}
</style>

View file

@ -56,11 +56,11 @@ async function save() {
showLoader();
await http
.post(config.API.summarySurveyDetail(store.assignId), data)
.then((res: any) => {
.then(async () => {
await props.getSurveyData?.();
success($q, "บันทึกสำเร็จ");
props.getSurveyData?.();
})
.catch((e: any) => {
.catch((e) => {
messageError($q, e);
})
.finally(() => {
@ -93,17 +93,16 @@ watch(
}
);
/** get ค่า เมื่อโหลดหน้า */
onMounted(() => {
if (store.tabMain === "SURVEY") {
if (dataSurvey.value !== null) {
answer1.value = dataSurvey.value.answer1;
answer2.value = dataSurvey.value.answer2;
answer3.value = dataSurvey.value.answer3;
status.value = false;
}
if (dataSurvey.value !== null) {
answer1.value = dataSurvey.value.answer1;
answer2.value = dataSurvey.value.answer2;
answer3.value = dataSurvey.value.answer3;
status.value = false;
}
}
});
</script>
<template>

View file

@ -67,7 +67,6 @@ const formData = ref<ProbationReportType>({
* @param type type file
*/
async function clickdownloadFile() {
console.log(props.page);
showLoader();
await http
.get(
@ -80,13 +79,13 @@ async function clickdownloadFile() {
.then(async (res) => {
const data = res.data.downloadUrl;
window.open(data);
hideLoader();
})
.catch(async (e) => {
messageError($q, JSON.parse(await e.response.data.text()));
hideLoader();
})
.finally(() => {});
.finally(() => {
hideLoader();
});
}
async function getData() {

View file

@ -185,11 +185,13 @@ async function dataEdit(id: string) {
const data = putDataEdit(id);
http
.put(config.API.saveEditAssign(id), data)
.then(() => {})
.then(async () => {
await getAssign();
})
.catch(() => {})
.finally(async () => {
isEdit.value = false;
getAssign();
hideLoader();
});
// } else {

View file

@ -6,7 +6,7 @@ import config from "@/app.config";
import { useQuasar } from "quasar";
import { useRegistryInFormationStore } from "@/modules/10_registry/store/registry";
import { useCounterMixin } from "./mixin";
import type { ProfileData } from "@/interface/Main";
import type { ProfileData, DataProfile } from "@/interface/Main";
export const useDataStore = defineStore("dataMain", () => {
const dataProfile = ref<any>();
@ -16,6 +16,8 @@ export const useDataStore = defineStore("dataMain", () => {
const { messageError, showLoader, hideLoader, findPosMasterNo, findOrgName } =
mixin;
// ref() คือการประกาศ state เหมือน vuex
const profileId = ref<string>("");
const dataprofilePosition = ref<DataProfile | undefined>(undefined);
const formData = reactive<ProfileData>({
profileId: "",
rank: "",
@ -101,6 +103,8 @@ export const useDataStore = defineStore("dataMain", () => {
async function getData(dataPerson: any) {
const data = await dataPerson;
dataprofilePosition.value = data;
profileId.value = data.profileId;
isProbation.value = data.isProbation;
formData.profileId = data.profileId;
formData.rank = data.rank;
@ -166,6 +170,8 @@ export const useDataStore = defineStore("dataMain", () => {
officerLink,
getProFileType,
dataProfile,
profileId,
dataprofilePosition,
};
});

View file

@ -16,6 +16,7 @@ import {
} from "@/plugins/auth";
import { useDataStore } from "@/stores/data";
import { useKpiDataStore } from "@/modules/08_KPI/store";
// landing page config url
const configParam = {
@ -27,6 +28,7 @@ const router = useRouter();
const $q = useQuasar();
const dataStore = useDataStore();
const kpiDataStore = useKpiDataStore();
const mixin = useCounterMixin();
const {
@ -44,15 +46,13 @@ const notiList = ref<any>([]);
const notiTrigger = ref(false);
const currentRouteName = router.currentRoute.value.name;
const tab = ref<any>(currentRouteName);
const link = ref<string>("");
const isSsoToken = ref(false);
/**
* เรยกฟงกนทงหมดตอนเรยกใชไฟล
*/
onMounted(async () => {
await checkUser();
await fetchTotolNotificate();
await Promise.all([checkUser(), fetchTotolNotificate()]);
const user = await tokenParsed();
const SSO_TOKEN = await getCookie("SSO");
isSsoToken.value = SSO_TOKEN === "y" ? true : false;
@ -63,9 +63,10 @@ async function checkUser() {
await http
.get(config.API.profilePosition())
.then(async (res) => {
const data = await res.data.result;
const data = res.data.result;
await dataStore.getData(data);
await dataStore.getProFileType();
kpiDataStore.dataProfile = data; // Set dataProfile in kpiDataStore
if (data.avatarName) {
await getImg(data.profileId, data.avatarName);
} else {
@ -77,17 +78,19 @@ async function checkUser() {
component: CustomComponent,
componentProps: {
title: "ข้อความแจ้งเตือน",
message: err.response.data.message,
message:
err.response?.data?.message || "เกิดข้อผิดพลาดที่ไม่ทราบสาเหตุ",
icon: "warning",
color: "red",
onlycancel: true,
},
}).onCancel(async () => {
}).onCancel(() => {
showLoader();
await logout();
setTimeout(() => {
hideLoader();
}, 1000);
logout().then(() => {
setTimeout(() => {
hideLoader();
}, 1000);
});
});
});
}
@ -97,11 +100,7 @@ function getImg(id: string, pathName: string) {
.get(config.API.fileByFile("ทะเบียนประวัติ", "โปรไฟล์", id, pathName))
.then((res) => {
dataStore.profileImg = res.data.downloadUrl;
})
.catch((e) => {
// messageError($q, e);
})
.finally(() => {});
});
}
const totalNoti = ref<number>(0);
@ -160,7 +159,7 @@ const doLogout = () => {
async () => {
await http.post(config.API.keycloakLogSSO, { text: "ออกจากระบบ" });
// authen with client
await logoutSSO();
logoutSSO();
},
"ยืนยันการออกจากระบบ",
"ต้องการออกจากระบบใช่หรือไม่"