Merge branch 'develop' into nice_dev

This commit is contained in:
DESKTOP-1R2VSQH\Lenovo ThinkPad E490 2024-01-30 14:19:07 +07:00
commit 7b7d6f628c
11 changed files with 867 additions and 194 deletions

1
env.d.ts vendored
View file

@ -1 +1,2 @@
/// <reference types="vite/client" /> /// <reference types="vite/client" />
declare module 'quasar-ui-q-draggable-table';

View file

@ -58,6 +58,7 @@
"node-sass": "^9.0.0", "node-sass": "^9.0.0",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"prettier": "^2.7.1", "prettier": "^2.7.1",
"quasar-ui-q-draggable-table": "^1.0.1",
"sass": "^1.69.4", "sass": "^1.69.4",
"start-server-and-test": "^1.15.2", "start-server-and-test": "^1.15.2",
"typescript": "~4.7.4", "typescript": "~4.7.4",

View file

@ -2,7 +2,10 @@ import { createApp, defineAsyncComponent } from "vue";
import App from "./App.vue"; import App from "./App.vue";
import router from "./router"; import router from "./router";
import { Dialog, Notify, Quasar, Loading } from "quasar"; import { Dialog, Notify, Quasar, Loading } from "quasar";
import quasarUserOptions from "./quasar-user-options"; import "./quasar-user-options";
import qDraggableTable from 'quasar-ui-q-draggable-table';
import 'quasar-ui-q-draggable-table/dist/index.css';
import "quasar/src/css/index.sass"; import "quasar/src/css/index.sass";
import th from "quasar/lang/th"; import th from "quasar/lang/th";
@ -29,6 +32,7 @@ app.config.globalProperties.$filters = filters;
app.use(router); app.use(router);
app.use(pinia); app.use(pinia);
app.use(qDraggableTable);
app.use( app.use(
Quasar, Quasar,

View file

@ -17,7 +17,6 @@ const router = useRouter();
const route = useRoute(); const route = useRoute();
const $q = useQuasar(); const $q = useQuasar();
const store = useInsigniaDataStore(); const store = useInsigniaDataStore();
const row = ref<DetailRow[]>();
const mixin = useCounterMixin(); const mixin = useCounterMixin();
const { date2Thai, messageError, hideLoader, showLoader } = mixin; const { date2Thai, messageError, hideLoader, showLoader } = mixin;
const id = ref<string>(route.params.id.toString()); const id = ref<string>(route.params.id.toString());
@ -40,9 +39,10 @@ async function fetchData(id: string) {
} }
onMounted(async () => { onMounted(async () => {
fetchData(id.value); await fetchData(id.value);
}); });
</script> </script>
<template> <template>
<div class="toptitle text-dark col-12 row items-center"> <div class="toptitle text-dark col-12 row items-center">
<q-btn <q-btn
@ -59,7 +59,7 @@ onMounted(async () => {
</div> </div>
<q-card flat bordered> <q-card flat bordered>
<InsigniaList :data="row" /> <InsigniaList :fetchData="fetchData"/>
</q-card> </q-card>
</template> </template>

View file

@ -5,12 +5,20 @@ import { useCounterMixin } from "@/stores/mixin";
import { useRouter, useRoute } from "vue-router"; import { useRouter, useRoute } from "vue-router";
import { useInsigniaDataStore } from "@/modules/01_metadataNew/stores/InsigniaStore"; import { useInsigniaDataStore } from "@/modules/01_metadataNew/stores/InsigniaStore";
import dialogHeader from "@/components/DialogHeader.vue"; import dialogHeader from "@/components/DialogHeader.vue";
import TableDraggable from "@/modules/01_metadataNew/components/insignia/TableDraggable.vue";
import { useQuasar } from "quasar"; import { useQuasar } from "quasar";
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
const store = useInsigniaDataStore(); const store = useInsigniaDataStore();
const router = useRouter(); const router = useRouter();
const mixin = useCounterMixin(); const mixin = useCounterMixin();
const props = defineProps({
fetchData: {
type: Function,
default: ()=>"",
}
})
const { const {
date2Thai, date2Thai,
dialogRemove, dialogRemove,
@ -22,17 +30,14 @@ const {
const $q = useQuasar(); const $q = useQuasar();
const columns = ref<QTableProps["columns"]>([ const columns = ref<QTableProps["columns"]>([
{ {
name: "level", name: "no",
align: "left", align: "left",
label: "ลำดับ", label: "ลำดับ",
sortable: true, sortable: false,
field: "level", field: "no",
headerStyle: "font-size: 14px; width:0px", headerStyle: "font-size: 14px; width:0px",
style: "font-size: 14px", style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
}, },
{ {
name: "name", name: "name",
align: "left", align: "left",
@ -143,7 +148,7 @@ const shortNameRef = ref<any>(null);
const dialogStatus = ref<string>(""); const dialogStatus = ref<string>("");
const editId = ref<string>(""); const editId = ref<string>("");
const visibleColumns = ref<string[]>([ const visibleColumns = ref<string[]>([
"level", "no",
"name", "name",
"shortName", "shortName",
"insigniaType", "insigniaType",
@ -164,24 +169,24 @@ function validateForm() {
onSubmit(); onSubmit();
} }
async function fetchData(id: string) { // async function fetchData(id: string) {
showLoader(); // showLoader();
await http // await http
.get(config.API.insigniaTypeNewId(id)) // .get(config.API.insigniaTypeNewId(id))
.then(async (res) => { // .then(async (res) => {
insigniaTypeId.value = res.data.result.name; // insigniaTypeId.value = res.data.result.name;
store.fetchData(res.data.result.insignias, res.data.result.name); // store.fetchData(res.data.result.insignias, res.data.result.name);
}) // })
.catch((err) => { // .catch((err) => {
messageError($q, err); // messageError($q, err);
}) // })
.finally(() => { // .finally(() => {
hideLoader(); // hideLoader();
}); // });
} // }
onMounted(async () => { // onMounted(async () => {
fetchData(id.value); // fetchData(id.value);
}); // });
async function onSubmit() { async function onSubmit() {
if (name.value.length > 0 && shortName.value.length > 0) { if (name.value.length > 0 && shortName.value.length > 0) {
@ -209,7 +214,7 @@ async function addData() {
note: note.value == "" ? "-" : note.value, note: note.value == "" ? "-" : note.value,
insigniaTypeId: id.value, insigniaTypeId: id.value,
}); });
fetchData(id.value); props.fetchData(id.value);
} }
async function editData(idData: string) { async function editData(idData: string) {
@ -220,17 +225,18 @@ async function editData(idData: string) {
note: note.value == "" ? "-" : note.value, note: note.value == "" ? "-" : note.value,
insigniaTypeId: id.value, insigniaTypeId: id.value,
}); });
fetchData(id.value); props.fetchData(id.value);
} }
async function deleteData(idData: string) { async function deleteData(idData: string) {
await http.delete(config.API.insigniaNewId(idData)); await http.delete(config.API.insigniaNewId(idData));
fetchData(id.value); props.fetchData(id.value);
} }
import { defineEmits } from "vue"; import { defineEmits } from "vue";
const emit = defineEmits(["nameType"]); const emit = defineEmits(["nameType"]);
const dialogOrder = ref<boolean>(false);
</script> </script>
<template> <template>
@ -250,6 +256,16 @@ const emit = defineEmits(["nameType"]);
> >
<q-tooltip> เพมขอม </q-tooltip> <q-tooltip> เพมขอม </q-tooltip>
</q-btn> </q-btn>
<q-btn
flat
round
color="blue-6"
icon="mdi-sort"
@click.stop="() => (dialogOrder = true)"
>
<q-tooltip> ดลำดบการแสดงผล </q-tooltip>
</q-btn>
<TableDraggable v-model:modal="dialogOrder" />
<q-space /> <q-space />
<div class="row q-gutter-sm"> <div class="row q-gutter-sm">
<q-input outlined dense v-model="filterKeyword" label="ค้นหา"></q-input> <q-input outlined dense v-model="filterKeyword" label="ค้นหา"></q-input>
@ -293,8 +309,11 @@ const emit = defineEmits(["nameType"]);
</template> </template>
<template v-slot:body="props"> <template v-slot:body="props">
<q-tr :props="props" class="cursor-pointer"> <q-tr :props="props" class="cursor-pointer">
<q-td v-for="col in props.cols" :key="col.id"> <q-td v-for="(col, index) in props.cols" :key="col.id">
<div v-if="col.name == 'isActive'"> <div v-if="col.name == 'no'">
{{ props.rowIndex + 1 }}
</div>
<div v-else-if="col.name == 'isActive'">
<q-icon <q-icon
v-if="col.value == false" v-if="col.value == false"
name="mdi-close" name="mdi-close"

View file

@ -0,0 +1,155 @@
<script setup lang="ts">
import { ref, watch } from "vue";
import type { QTableProps } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useRouter, useRoute } from "vue-router";
import { useInsigniaDataStore } from "@/modules/01_metadataNew/stores/InsigniaStore";
import dialogHeader from "@/components/DialogHeader.vue";
import { useQuasar } from "quasar";
import DialogHeader from "@/components/DialogHeader.vue";
import http from "@/plugins/http";
import config from "@/app.config";
const store = useInsigniaDataStore();
const mixin = useCounterMixin();
const { dialogRemove, dialogConfirm, showLoader, hideLoader, messageError } =
mixin;
const $q = useQuasar();
const route = useRoute();
const modal = defineModel("modal", { type: Boolean });
const columns = ref<QTableProps["columns"]>([
{
name: "name",
required: true,
label: "ชื่อเครื่องราชฯ",
align: "left",
field: "name",
sortable: true,
},
{
name: "shortName",
align: "center",
label: "ชื่อย่อ",
field: "shortName",
},
{
name: "insigniaType",
align: "left",
label: "ลำดับชั้นเครื่องราชฯ",
field: "insigniaType",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sortable: true,
},
]);
function onDrop(from: any, to: any) {
onDropRow(from, to);
}
const rows = ref<any>([]);
function onDropRow(from: any, to: any) {
rows.value.splice(to, 0, rows.value.splice(from, 1)[0]);
}
async function save() {
const dataPost = await rows.value.map((obj:any) => {
return obj.id;
});
console.log("post data===>", dataPost);
modal.value = false
// showLoader();
// await http
// .put(config.API.insigniaTypeNewId(id), dataPost)
// .then(async (res) => {
// })
// .catch((err) => {
// messageError($q, err);
// })
// .finally(() => {
// hideLoader();
store.row = rows.value
// });
}
async function onSubmit() {
dialogConfirm($q, async () => {
save();
});
}
watch(modal, () => {
if (modal.value === true) {
// rows.value = store.row;
rows.value = [...store.row]; // sort store
}
});
</script>
<template>
<q-dialog v-model="modal" class="dialog" persistent>
<q-card style="min-width: 50vw" class="bg-grey-11">
<form @submit.prevent="onSubmit">
<DialogHeader
tittle="จัดลำดับการแสดงผล"
:close="() => (modal = false)"
/>
<q-separator />
<q-card-section class="q-pa-md bg-grey-1">
<q-table
v-draggable-table="{
options: {
mode: 'row',
onlyBody: true,
dragHandler: 'th,td',
},
onDrop,
}"
flat
bordered
:rows="rows"
:columns="columns"
:rows-per-page-options="[100]"
row-key="name"
hide-bottom
hide-pagination
hide-header
/>
<!-- <q-table
v-draggable-table="{
options: {
mode: 'row',
onlyBody: true,
dragHandler: 'tr',
},
onDrop,
}"
ref="table"
:columns="columns"
:rows="rows"
row-key="name"
flat
bordered
hide-bottom
/> -->
</q-card-section>
<q-separator />
<q-card-actions align="right">
<q-btn
type="submit"
dense
unelevated
label="บันทึก"
color="public"
class="q-px-md"
>
<!-- icon="mdi-content-save-outline" -->
<q-tooltip>นทกขอม</q-tooltip>
</q-btn>
</q-card-actions>
</form>
</q-card>
</q-dialog>
</template>

View file

@ -9,11 +9,11 @@ import { useCounterMixin } from "@/stores/mixin";
const { date2Thai } = useCounterMixin(); const { date2Thai } = useCounterMixin();
export const useInsigniaDataStore = defineStore("insigniaData", () => { export const useInsigniaDataStore = defineStore("insigniaData", () => {
const row = ref<DataRow[]>(); const row = ref<DataRow[]>([]);
function fetchData(data: DataResponse[], insigniaType?: string) { function fetchData(data: DataResponse[], insigniaType?: string) {
data.forEach((row, index) => { // data.forEach((row, index) => {
row.level = index + 1; // row.level = index + 1;
}); // });
const list = data.map((e) => ({ const list = data.map((e) => ({
...e, ...e,
insigniaType: insigniaType, insigniaType: insigniaType,

View file

@ -8,6 +8,9 @@ import type {
FormDataPosition, FormDataPosition,
FormPositionRef, FormPositionRef,
DataOption, DataOption,
FormPositionSelect,
RowDetailPositions,
ListMenu,
} from "@/modules/02_organizationalNew/interface/index/Main"; } from "@/modules/02_organizationalNew/interface/index/Main";
const props = defineProps({ const props = defineProps({
@ -15,23 +18,56 @@ const props = defineProps({
close: Function, close: Function,
}); });
const isReadonly = ref<boolean>(false); //
const $q = useQuasar(); const $q = useQuasar();
const mixin = useCounterMixin(); const mixin = useCounterMixin();
const { dialogConfirm } = mixin; const { dialogConfirm } = mixin;
const selected = ref<any>([]);
const search = ref<string>("");
const type = ref<string>("positionName");
const typeOps = ref<DataOption[]>([
{ id: "positionName", name: "ตำแหน่งในสายงาน" },
{ id: "positionField", name: "สายงาน" },
{ id: "positionType", name: "ประเภทตำแหน่ง" },
{ id: "positionLevel", name: "ระดับตำแหน่ง" },
{ id: "positionExecutive", name: "ตำแหน่งทางการบริหาร" },
{ id: "positionExecutiveField", name: "ด้านทางการบริหาร" },
{ id: "positionArea", name: "ด้าน/สาขา" },
]);
const rows = ref<any[]>([]); const listMenu = ref<ListMenu[]>([
{
label: "คัดลอก",
icon: "mdi-content-copy",
type: "copy",
color: "orange",
},
]);
const rows = ref<RowDetailPositions[]>([]);
const rowsPositionSelect = ref<RowDetailPositions[]>([]);
const ocLevelOp = ref<DataOption[]>([]); const ocLevelOp = ref<DataOption[]>([]);
const prefixNoRef = ref<Object | null>(null); const prefixNoRef = ref<Object | null>(null);
const positionNoRef = ref<Object | null>(null); const positionNoRef = ref<Object | null>(null);
const formData = reactive<FormDataPosition>({ const formData = reactive<FormDataPosition>({
shortName: "สกจ.",
prefixNo: "", prefixNo: "",
positionNo: "", positionNo: "",
suffixNo: "", suffixNo: "",
confirm: false, confirm: false,
}); });
const formPositionSelect = reactive<FormPositionSelect>({
positionName: "",
positionField: "",
positionType: "",
positionLevel: "",
positionExecutive: "",
positionExecutiveField: "",
positionArea: "",
});
/** maping ref เข้าตัวแปรเพื่อเตรียมตรวจสอบ */ /** maping ref เข้าตัวแปรเพื่อเตรียมตรวจสอบ */
const objectPositionRef: FormPositionRef = { const objectPositionRef: FormPositionRef = {
prefixNo: prefixNoRef, prefixNo: prefixNoRef,
@ -39,60 +75,89 @@ const objectPositionRef: FormPositionRef = {
}; };
const columns = ref<QTableProps["columns"]>([ const columns = ref<QTableProps["columns"]>([
{ {
name: "no", name: "no",
align: "left", align: "left",
label: "ลำดับ", label: "ลำดับ",
sortable: false, sortable: false,
field: "no", field: "no",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px", style: "font-size: 14px",
}, },
{ {
name: "positionType", name: "positionName",
align: "left", align: "left",
label: "ประเภทตำเเหน่ง", label: "ตำแหน่งในสายงาน",
sortable: true, sortable: true,
field: "positionType", field: "positionName",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px", style: "font-size: 14px",
}, },
{ {
name: "positionLevel", name: "positionField",
align: "left", align: "left",
label: "ระดับตำแหน่ง ด้าน/สาขา", label: "สายงาน",
sortable: true, sortable: true,
field: "positionLevel", field: "positionField",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px", style: "font-size: 14px",
}, },
{ {
name: "positionAdmin", name: "positionType",
align: "left", align: "left",
label: "ตำแหน่งทางการบริหาร", label: "ประเภทตำเเหน่ง",
sortable: true, sortable: true,
field: "positionAdmin", field: "positionType",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px", style: "font-size: 14px",
}, },
{ {
name: "other", name: "positionLevel",
align: "left", align: "left",
label: "ฯลฯ", label: "ระดับตำแหน่ง",
sortable: true, sortable: true,
field: "other", field: "positionLevel",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px", style: "font-size: 14px",
}, },
{
]); name: "positionExecutive",
const visibleColumns = ref<string[]>([ align: "left",
"no", label: "ตำแหน่งทางการบริหาร",
"positionType", sortable: true,
"positionLevel", field: "positionExecutive",
"positionAdmin", headerStyle: "font-size: 14px",
"other", style: "font-size: 14px",
]); },
{
name: "positionExecutiveField",
align: "left",
label: "ด้านทางการบริหาร",
sortable: true,
field: "positionExecutiveField",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "positionArea",
align: "left",
label: "ด้าน/สาขา",
sortable: true,
field: "positionArea",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
]);
const visibleColumns = ref<string[]>([
"no",
"positionName",
"positionField",
"positionType",
"positionLevel",
"positionExecutive",
"positionExecutiveField",
"positionArea",
]);
/** ฟังก์ชั่นตรวจสอบความถูกต้องของข้อมูลในฟอร์ม */ /** ฟังก์ชั่นตรวจสอบความถูกต้องของข้อมูลในฟอร์ม */
function validateForm() { function validateForm() {
@ -112,27 +177,120 @@ function validateForm() {
} }
} }
/** ฟังก์ชั่นตรวจสอบความถูกต้องของข้อมูลในฟอร์ม */
function validateFormPositionEdit() {
// const hasError = [];
// for (const key in objectPositionRef) {
// if (Object.prototype.hasOwnProperty.call(objectPositionRef, key)) {
// const property = objectPositionRef[key];
// if (property.value && typeof property.value.validate === "function") {
// const isValid = property.value.validate();
// hasError.push(isValid);
// }
// }
// }
// if (hasError.every((result) => result === true)) {
onSubmitSelectEdit();
// } else {
// }
}
/** ฟังชั่น บันทึก */ /** ฟังชั่น บันทึก */
function onSubmit() { function onSubmit() {
dialogConfirm($q, () => { dialogConfirm($q, () => {
console.log(formData); console.log(formData);
}); });
} }
/** ฟังชั่น บันทึก */
function onSubmitSelectEdit() {
dialogConfirm($q, () => {
console.log(formPositionSelect);
});
}
/** update เมื่อเปลี่ยน option */
function updateSelect() {
search.value = "";
}
/** input ค้นหา */
const searchRef = ref<any>(null);
async function searchInput() {
searchRef.value.validate();
if (!searchRef.value.hasError) {
//
const dataList = [
{
positionName: "test1",
positionField: "test1",
positionType: "test1",
positionLevel: "test1",
positionExecutive: "test1",
positionExecutiveField: "test1",
positionArea: "test1",
},
{
positionName: "test2",
positionField: "test2",
positionType: "test2",
positionLevel: "test2",
positionExecutive: "test2",
positionExecutiveField: "test2",
positionArea: "test2",
},
{
positionName: "test3",
positionField: "test3",
positionType: "test3",
positionLevel: "test3",
positionExecutive: "test3",
positionExecutiveField: "test3",
positionArea: "test3",
},
];
rowsPositionSelect.value = dataList;
}
}
/**
* ดลอกขอม
* @param data อมลตำแหน
*/
function copyDetiail(data: RowDetailPositions) {
formPositionSelect.positionName = data.positionName;
formPositionSelect.positionField = data.positionField;
formPositionSelect.positionType = data.positionType;
formPositionSelect.positionLevel = data.positionLevel;
formPositionSelect.positionExecutive = data.positionExecutive;
formPositionSelect.positionExecutiveField = data.positionExecutiveField;
formPositionSelect.positionArea = data.positionArea;
}
/**
* งค css ออกไปตามเงอนไข
* @param val true/false
*/
function inputEdit(val: boolean) {
return {
"full-width cursor-pointer inputgreen ": val,
"full-width cursor-pointer inputgreen": !val,
};
}
watch( watch(
() => props.modal, () => props.modal,
() => { () => {
if (props.modal === true) { if (props.modal === true) {
ocLevelOp.value = [ }
{ }
id: "id1", );
name: "id1", watch(
}, () => selected.value,
{ () => {
id: "id2", if (selected.value.length > 0) {
name: "id2", rows.value = selected.value;
}, } else {
]; rows.value = [];
} }
} }
); );
@ -140,101 +298,411 @@ watch(
<template> <template>
<template> <template>
<q-dialog v-model="props.modal" persistent> <q-dialog v-model="props.modal" persistent>
<q-card style="min-width: 50vw"> <q-card style="min-width: 96vw">
<form @submit.prevent="validateForm"> <DialogHeader :tittle="`เพิ่มตำแหน่ง`" :close="props.close" />
<DialogHeader :tittle="`เพิ่มตำแหน่ง`" :close="props.close" /> <q-separator />
<q-separator />
<q-card-section> <q-card-section class="q-pa-sm">
<div class="row q-col-gutter-sm"> <div class="row q-col-gutter-sm">
<div class="col-4"> <div class="col-5">
<q-input <form @submit.prevent="validateForm">
v-model="formData.prefixNo" <q-card
ref="prefixNoRef"
dense
outlined
for="#prefixNo"
label="Prefix เลขที่ตำเเหน่ง"
hide-bottom-space
:rules="[
(val) => !!val || `${'กรุณากรอกPrefix เลขที่ตำเเหน่ง'}`,
]"
/>
</div>
<div class="col-4">
<q-input
v-model="formData.positionNo"
ref="positionNoRef"
dense
outlined
for="#positionNo"
label="เลขที่ตำแหน่ง"
hide-bottom-space
:rules="[(val) => !!val || `${'กรุณากรอกเลขที่ตำแหน่ง'}`]"
/>
</div>
<div class="col-4">
<q-input
v-model="formData.suffixNo"
dense
outlined
for="#suffixNo"
label="Suffix เลขที่ตำแหน่ง"
/>
</div>
<div class="col-12">
<d-table
ref="table"
:columns="columns"
:rows="rows"
row-key="idcard"
flat
bordered bordered
:paging="true" class="col-12"
dense style="border: 1px solid #d6dee1"
class="custom-header-table"
:visible-columns="visibleColumns"
> >
<template v-slot:header="props"> <div
<q-tr :props="props"> class="col-12 text-weight-medium bg-grey-1 q-py-xs q-px-md"
<q-th >
v-for="col in props.cols" รายการตำแหน
:key="col.name" </div>
:props="props" <div class="col-12"><q-separator /></div>
style="color: #000000; font-weight: 500" <div class="row q-col-gutter-sm col-12 q-pa-sm">
<div class="col-3">
<q-input
v-model="formData.shortName"
dense
outlined
readonly
for="#shortName"
label="ชื่อย่อหน่วยงาน"
/>
</div>
<div class="col-3">
<q-input
v-model="formData.prefixNo"
:class="inputEdit(isReadonly)"
ref="prefixNoRef"
dense
outlined
for="#prefixNo"
label="Prefix เลขที่ตำเเหน่ง"
/>
</div>
<div class="col-3">
<q-input
v-model="formData.positionNo"
:class="inputEdit(isReadonly)"
ref="positionNoRef"
dense
outlined
for="#positionNo"
label="เลขที่ตำแหน่ง"
lazy-rules
hide-bottom-space
:rules="[
(val) => !!val || `${'กรุณากรอกเลขที่ตำแหน่ง'}`,
]"
/>
</div>
<div class="col-3">
<q-input
v-model="formData.suffixNo"
:class="inputEdit(isReadonly)"
dense
outlined
for="#suffixNo"
label="Suffix เลขที่ตำแหน่ง"
/>
</div>
<div class="col-12">
<d-table
ref="table"
:columns="columns"
:rows="rows"
row-key="idcard"
flat
bordered
:paging="true"
dense
class="custom-header-table"
:visible-columns="visibleColumns"
> >
<span class="text-weight-medium">{{ col.label }}</span> <template v-slot:header="props">
</q-th> <q-tr :props="props">
</q-tr> <q-th
</template> v-for="col in props.cols"
<template v-slot:body="props"> :key="col.name"
<q-tr :props="props" class="cursor-pointer"> :props="props"
<q-td style="color: #000000; font-weight: 500"
v-for="col in props.cols" >
:key="col.name" <span class="text-weight-medium">{{
:props="props" col.label
> }}</span>
<div v-if="col.name == 'no'"> </q-th>
{{ props.rowIndex + 1 }} </q-tr>
</div> </template>
<div v-else> <template v-slot:body="props">
{{ col.value }} <q-tr :props="props" class="cursor-pointer">
</div> <q-td
</q-td> v-for="col in props.cols"
</q-tr> :key="col.name"
</template> :props="props"
</d-table> >
</div> <div v-if="col.name == 'no'">
<div class="col-12 q-mt-sm"> {{ props.rowIndex + 1 }}
<q-checkbox dense v-model="formData.confirm" label="ไม่ผูกกับตำแหน่งก่อนหน้า" color="teal" /> </div>
</div> <div v-else>
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</d-table>
</div>
<div class="col-12 q-mt-sm">
<q-checkbox
dense
v-model="formData.confirm"
label="ไม่ผูกกับตำแหน่งก่อนหน้า"
color="teal"
/>
</div>
</div>
<q-separator />
<q-card-actions
align="right"
class="bg-white text-teal q-pa-xs"
>
<q-btn type="submit" :label="`บันทึก`" color="public" />
</q-card-actions>
</q-card>
</form>
</div> </div>
</q-card-section>
<q-separator /> <div class="col-5">
<q-card bordered class="col-12" style="border: 1px solid #d6dee1">
<div
class="col-12 text-weight-medium bg-grey-1 q-py-xs q-px-md"
>
เลอกตำแหน
</div>
<div class="col-12"><q-separator /></div>
<div class="q-pa-sm">
<div class="row col-12 q-col-gutter-sm items-start">
<div class="col-12 col-sm-6 col-md-3">
<q-select
label="ค้นหาจาก"
v-model="type"
:options="typeOps"
emit-value
dense
@update:model-value="updateSelect"
map-options
outlined
option-label="name"
option-value="id"
/>
</div>
<div class="col-12 col-sm-6 col-md-6">
<q-input
ref="searchRef"
:class="inputEdit(isReadonly)"
v-model="search"
outlined
clearable
dense
lazy-rules
label="คำค้น"
hide-bottom-space
:rules="[(val) => !!val || `กรุณากรอกคำค้น`]"
/>
</div>
<div class="col-12 col-sm-6 col-md-3">
<q-btn
color="primary"
icon="search"
label="ค้นหา"
class="full-width q-pa-sm"
@click="searchInput()"
>
</q-btn>
</div>
</div>
<div class="full-width q-mt-sm">
<d-table
ref="table"
:columns="columns"
:rows="rowsPositionSelect"
row-key="positionName"
flat
bordered
:paging="true"
dense
class="custom-header-table"
:visible-columns="visibleColumns"
selection="multiple"
v-model:selected="selected"
>
<template v-slot:header-selection="scope">
<q-checkbox
keep-color
color="primary"
dense
v-model="scope.checkBox"
/>
</template>
<template v-slot:header="props">
<q-tr :props="props">
<q-th class="text-center">
<q-checkbox
keep-color
color="primary"
dense
v-model="props.selected"
/>
</q-th>
<q-th
v-for="col in props.cols"
:key="col.name"
:props="props"
style="color: #000000; font-weight: 500"
>
<span class="text-weight-medium">{{
col.label
}}</span>
</q-th>
<q-th auto-width></q-th>
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props" class="cursor-pointer">
<td class="text-center">
<q-checkbox
keep-color
color="primary"
dense
v-model="props.selected"
/>
</td>
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
>
<div v-if="col.name == 'no'">
{{ props.rowIndex + 1 }}
</div>
<div v-if="col.name === 'fullName'">
{{ props.prefix }}
</div>
<div v-else-if="col.name === 'salary'">
{{ props.row.salary.toLocaleString() }}
</div>
<div v-else>
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
flat
dense
icon="mdi-dots-vertical"
class="q-pa-none q-ml-xs"
color="grey-13"
>
<q-menu anchor="bottom middle" self="top middle">
<q-list
dense
v-for="(item, index) in listMenu"
:key="index"
>
<q-item
clickable
v-close-popup
@click="
item.type === 'copy'
? copyDetiail(props.row)
: ''
"
>
<q-item-section avatar>
<q-icon
:color="item.color"
:name="item.icon"
size="sm"
/>
</q-item-section>
<q-item-section>{{
item.label
}}</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</q-td>
</q-tr>
</template>
</d-table>
</div>
</div>
</q-card>
</div>
<div class="col-2">
<form @submit.prevent="validateFormPositionEdit">
<q-card
bordered
class="col-12"
style="border: 1px solid #d6dee1"
>
<div
class="col-12 text-weight-medium bg-grey-1 q-py-xs q-px-md"
>
เลอกตำแหน
</div>
<div class="col-12"><q-separator /></div>
<div class="row q-col-gutter-sm col-12 q-pa-sm">
<div class="col-12">
<q-input
v-model="formPositionSelect.positionName"
:class="inputEdit(isReadonly)"
dense
outlined
for="#positionName"
label="ตำแหน่งในสายงาน"
/>
</div>
<div class="col-12">
<q-input
v-model="formPositionSelect.positionField"
:class="inputEdit(isReadonly)"
dense
outlined
for="#positionField"
label="สายงาน"
/>
</div>
<div class="col-12">
<q-input
v-model="formPositionSelect.positionType"
:class="inputEdit(isReadonly)"
dense
outlined
for="#positionType"
label="ประเภทตำแหน่ง"
/>
</div>
<div class="col-12">
<q-input
v-model="formPositionSelect.positionLevel"
:class="inputEdit(isReadonly)"
dense
outlined
for="#positionLevel"
label="ระดับตำแหน่ง"
/>
</div>
<div class="col-12">
<q-input
v-model="formPositionSelect.positionExecutive"
:class="inputEdit(isReadonly)"
dense
outlined
for="#positionExecutive"
label="ตำแหน่งทางการบริหาร"
/>
</div>
<div class="col-12">
<q-input
v-model="formPositionSelect.positionExecutiveField"
:class="inputEdit(isReadonly)"
dense
outlined
for="#positionExecutiveField"
label="ด้านทางการบริหาร"
/>
</div>
<div class="col-12">
<q-input
v-model="formPositionSelect.positionArea"
:class="inputEdit(isReadonly)"
dense
outlined
for="#positionArea"
label="ด้าน/สาขา"
/>
</div>
</div>
<q-separator />
<q-card-actions
align="right"
class="bg-white text-teal q-pa-xs"
>
<q-btn type="submit" :label="`บันทึก`" color="public" />
</q-card-actions>
</q-card>
</form>
</div>
</div>
</q-card-section>
<!-- <q-separator />
<q-card-actions align="right" class="bg-white text-teal"> <q-card-actions align="right" class="bg-white text-teal">
<q-btn type="submit" :label="`บันทึก`" color="public" /> <q-btn type="submit" :label="`บันทึก`" color="public" />
</q-card-actions> </q-card-actions> -->
</form>
</q-card> </q-card>
</q-dialog> </q-dialog>
</template> </template>

View file

@ -103,13 +103,13 @@ watch(
</div> </div>
</div> </div>
<div class="col-8 text-grey-8"> <div class="col-8 text-grey-8">
<p class="q-ma-none">ภายนอก {{ formData.orgPhoneEx }}</p> <p class="q-ma-none">{{ formData.orgPhoneEx ? `ภายนอก ${formData.orgPhoneEx}`:'' }}</p>
</div> </div>
</div> </div>
<div class="row q-col-gutter-sm"> <div class="row q-col-gutter-sm">
<div class="offset-4 col-8 text-grey-8"> <div class="offset-4 col-8 text-grey-8">
<p>ภายใน {{ formData.orgPhoneIn }}</p> <p>{{ formData.orgPhoneIn ? `ภายใน ${formData.orgPhoneIn}`:'' }}</p>
</div> </div>
</div> </div>

View file

@ -25,6 +25,7 @@ interface FormDataAgency {
} }
interface FormDataPosition { interface FormDataPosition {
shortName: string;
prefixNo: string; prefixNo: string;
positionNo: string; positionNo: string;
suffixNo: string; suffixNo: string;
@ -71,7 +72,27 @@ interface HistoryType {
orgRevisionName: string; orgRevisionName: string;
orgRevisionIsCurrent: boolean; orgRevisionIsCurrent: boolean;
orgRevisionIsDraft: boolean; orgRevisionIsDraft: boolean;
orgRevisionCreatedAt: any; orgRevisionCreatedAt: Date | string;
}
interface FormPositionSelect {
positionName: string;
positionField: string;
positionType: string;
positionLevel: string;
positionExecutive: string;
positionExecutiveField: string;
positionArea: string;
}
interface RowDetailPositions {
positionName: string
positionField: string
positionType: string
positionLevel: string
positionExecutive: string
positionExecutiveField: string
positionArea: string
} }
export type { export type {
Pagination, Pagination,
@ -85,4 +106,6 @@ export type {
FormNewStructureRef, FormNewStructureRef,
HistoryType, HistoryType,
ListMenu, ListMenu,
FormPositionSelect,
RowDetailPositions
}; };

View file

@ -13,6 +13,8 @@
], ],
"compilerOptions": { "compilerOptions": {
"typeRoots": ["./typings", "./node_modules/@types"],
"types": ["quasar-ui-q-draggable-table"],
/* other configs */ /* other configs */
"paths": { "paths": {
"@/*": [ "@/*": [