fix:interface
This commit is contained in:
parent
a79a5858b6
commit
c6c1fe93c1
4 changed files with 147 additions and 76 deletions
|
|
@ -1,7 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, reactive, ref, watch } from "vue";
|
||||
import { useQuasar } from "quasar";
|
||||
import axios from "axios";
|
||||
import { storeToRefs } from "pinia";
|
||||
|
||||
import { useCounterMixin } from "@/stores/mixin";
|
||||
|
|
@ -10,6 +9,12 @@ import { useIssueStore } from "@/modules/22_issues/store";
|
|||
import http from "@/plugins/http";
|
||||
import config from "@/app.config";
|
||||
|
||||
import type {
|
||||
IssueData,
|
||||
IssueAttachment,
|
||||
IssueAttachmentWithDownloadUrl,
|
||||
} from "@/modules/22_issues/interface/Main";
|
||||
|
||||
import DialogHeader from "@/components/DialogHeader.vue";
|
||||
|
||||
const $q = useQuasar();
|
||||
|
|
@ -32,22 +37,30 @@ const modal = defineModel<boolean>("modal", {
|
|||
const type = defineModel<string>("type", {
|
||||
default: "edit",
|
||||
});
|
||||
const data = defineModel<any>("data", {
|
||||
const data = defineModel<IssueData | null>("data", {
|
||||
default: null,
|
||||
});
|
||||
|
||||
const props = defineProps<{
|
||||
fetchData: () => Promise<void>;
|
||||
}>();
|
||||
|
||||
const isEdit = computed(() => type.value === "edit");
|
||||
const title = computed(() => (isEdit.value ? "แก้ไขสถานะ" : "รายละเอียดปัญหา"));
|
||||
const optionsStatus = computed(() =>
|
||||
statusOptions.value.filter((item) => item.value !== "")
|
||||
);
|
||||
const splitterModel = computed({
|
||||
get: () => (isEdit.value ? 70 : 100),
|
||||
set: (val: number) => {},
|
||||
});
|
||||
|
||||
const form = reactive({
|
||||
status: "",
|
||||
remark: "",
|
||||
});
|
||||
const fileList = ref<any[]>([]);
|
||||
const images = ref<any[]>([]);
|
||||
const fileList = ref<IssueAttachment[]>([]);
|
||||
const images = ref<IssueAttachmentWithDownloadUrl[]>([]);
|
||||
|
||||
const imageModal = ref(false);
|
||||
const selectedImg = ref("");
|
||||
|
|
@ -63,10 +76,11 @@ function onSubmit() {
|
|||
dialogConfirm($q, async () => {
|
||||
showLoader();
|
||||
try {
|
||||
await http.put(config.API.orgIssues + "/" + data.value.id, {
|
||||
await http.put(config.API.orgIssues + "/" + data?.value?.id, {
|
||||
status: form.status,
|
||||
remark: form.remark,
|
||||
});
|
||||
await props.fetchData();
|
||||
success($q, "บันทึกข้อมูลเรียบร้อย");
|
||||
onClose();
|
||||
} catch (error) {
|
||||
|
|
@ -95,11 +109,11 @@ async function fetchDocument(codeIssue: string, system: string) {
|
|||
|
||||
// 1. แยกไฟล์ที่ไม่ใช่รูปเก็บเข้า list
|
||||
fileList.value = allFiles.filter(
|
||||
(f: any) => !/\.(jpg|jpeg|png|gif|webp)$/i.test(f.fileName)
|
||||
(f: IssueAttachment) => !/\.(jpg|jpeg|png|gif|webp)$/i.test(f.fileName)
|
||||
);
|
||||
|
||||
// 2. แยกเฉพาะรูปภาพแล้วโหลดข้อมูล
|
||||
const images = allFiles.filter((f: any) =>
|
||||
const images = allFiles.filter((f: IssueAttachment) =>
|
||||
/\.(jpg|jpeg|png|gif|webp)$/i.test(f.fileName)
|
||||
);
|
||||
for (const img of images) {
|
||||
|
|
@ -119,12 +133,11 @@ async function getImg(path: string, fileName: string) {
|
|||
.get(config.API.fileByPath(`${path}/${fileName}`))
|
||||
.then((res) => {
|
||||
const data = res.data;
|
||||
const newData = {
|
||||
const newData: IssueAttachmentWithDownloadUrl = {
|
||||
...data,
|
||||
};
|
||||
|
||||
images.value.push(newData);
|
||||
console.log(images.value);
|
||||
})
|
||||
.catch((e) => {
|
||||
messageError($q, e);
|
||||
|
|
@ -141,8 +154,8 @@ function downloadFile(fileName: string) {
|
|||
.get(
|
||||
config.API.fileByFile(
|
||||
"issueAttachments",
|
||||
data.value.system,
|
||||
data.value.codeIssue,
|
||||
data?.value?.system || "",
|
||||
data?.value?.codeIssue || "",
|
||||
fileName
|
||||
)
|
||||
)
|
||||
|
|
@ -158,17 +171,6 @@ function downloadFile(fileName: string) {
|
|||
});
|
||||
}
|
||||
|
||||
watch(
|
||||
() => modal.value,
|
||||
(newData: boolean) => {
|
||||
if (newData) {
|
||||
form.status = data.value.status || "";
|
||||
form.remark = data.value.remark || "";
|
||||
fetchDocument(data.value.codeIssue, data.value.system);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const downloadImage = async (url: string, fileName: string = "image.png") => {
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
|
|
@ -185,24 +187,25 @@ const downloadImage = async (url: string, fileName: string = "image.png") => {
|
|||
document.body.removeChild(link);
|
||||
window.URL.revokeObjectURL(blobUrl);
|
||||
} catch (error) {
|
||||
console.error("ดาวน์โหลดล้มเหลว:", error);
|
||||
messageError($q, error);
|
||||
}
|
||||
};
|
||||
|
||||
const splitterModel = computed({
|
||||
get: () => (isEdit.value ? 70 : 100),
|
||||
set: (val: number) => {
|
||||
// ไม่ต้องทำอะไรเมื่อมีการตั้งค่าใหม่
|
||||
},
|
||||
});
|
||||
watch(
|
||||
() => modal.value,
|
||||
(val: boolean) => {
|
||||
if (val && data.value) {
|
||||
form.status = data.value.status || "";
|
||||
form.remark = data.value.remark || "";
|
||||
fetchDocument(data.value.codeIssue, data.value.system);
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<q-dialog v-model="modal" persistent>
|
||||
<q-card
|
||||
style="width: 900px; max-width: 95vw"
|
||||
class="rounded-borders shadow-2 overflow-hidden"
|
||||
>
|
||||
<q-card class="overflow-hidden" style="min-width: 900px; max-width: 90vw">
|
||||
<q-form greedy @submit.prevent @validation-success="onSubmit">
|
||||
<DialogHeader :tittle="title" :close="onClose" />
|
||||
<q-separator />
|
||||
|
|
@ -210,46 +213,50 @@ const splitterModel = computed({
|
|||
<q-splitter
|
||||
v-model="splitterModel"
|
||||
:limits="isEdit ? [70, 70] : [100, 100]"
|
||||
style="height: 600px"
|
||||
style="height: 800px"
|
||||
:separator-class="!isEdit ? 'hidden' : ''"
|
||||
>
|
||||
<template v-slot:before>
|
||||
<div class="q-pa-lg">
|
||||
<div class="q-gutter-y-sm text-body2">
|
||||
<div class="q-gutter-y-md text-body2">
|
||||
<div class="row">
|
||||
<div class="col-4 text-grey-7">รหัส:</div>
|
||||
<div class="col-8 text-weight-bold">
|
||||
{{ data?.codeIssue }}
|
||||
<div class="col-3 text-grey-7">รหัส:</div>
|
||||
<div class="col-9 text-weight-bold">
|
||||
{{ data?.codeIssue || "-" }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-4 text-grey-7">หัวข้อ:</div>
|
||||
<div class="col-8">{{ data?.title }}</div>
|
||||
<div class="row q-col-gutter-sm">
|
||||
<div class="col-3 text-grey-7">หัวข้อ:</div>
|
||||
<div class="col-9">{{ data?.title || "-" }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-4 text-grey-7">รายละเอียด:</div>
|
||||
<div class="col-8">{{ data?.description }}</div>
|
||||
<div class="row q-col-gutter-sm">
|
||||
<div class="col-3 text-grey-7">รายละเอียด:</div>
|
||||
<div class="col-9">{{ data?.description || "-" }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-4 text-grey-7">ระบบ/เมนู:</div>
|
||||
<div class="col-8">
|
||||
{{ convertSystem(data?.system) }} / {{ data?.menu }}
|
||||
<div class="row q-col-gutter-sm">
|
||||
<div class="col-3 text-grey-7">ระบบ/เมนู:</div>
|
||||
<div class="col-9">
|
||||
{{ convertSystem(data?.system || "") }} / {{ data?.menu }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-4 text-grey-7">ผู้แจ้ง:</div>
|
||||
<div class="col-8">{{ data?.createdFullName }}</div>
|
||||
<div class="row q-col-gutter-sm">
|
||||
<div class="col-3 text-grey-7">ผู้แจ้ง:</div>
|
||||
<div class="col-9">{{ data?.createdFullName || "-" }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-4 text-grey-7">วันที่แจ้ง:</div>
|
||||
<div class="col-8">
|
||||
{{ date2Thai(data?.createdAt, false, true) }}
|
||||
<div class="row q-col-gutter-sm">
|
||||
<div class="col-3 text-grey-7">วันที่แจ้ง:</div>
|
||||
<div class="col-9">
|
||||
{{
|
||||
data?.createdAt
|
||||
? date2Thai(data?.createdAt, false, true)
|
||||
: ""
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-4 text-grey-7">สถานะ:</div>
|
||||
<div class="col-8">
|
||||
{{ convertStatus(data?.status) }}
|
||||
<div class="row q-col-gutter-sm">
|
||||
<div class="col-3 text-grey-7">สถานะ:</div>
|
||||
<div class="col-9">
|
||||
{{ convertStatus(data?.status || "") }}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
|
@ -305,7 +312,7 @@ const splitterModel = computed({
|
|||
<q-icon name="attachment" /> ไฟล์เอกสารแนบ
|
||||
</div>
|
||||
<q-list bordered separator class="rounded-borders">
|
||||
<q-item v-for="file in fileList" :key="file.id" dense>
|
||||
<q-item v-for="file in fileList" :key="file.fileName" dense>
|
||||
<q-item-section avatar
|
||||
><q-icon name="description" color="blue"
|
||||
/></q-item-section>
|
||||
|
|
@ -389,7 +396,7 @@ const splitterModel = computed({
|
|||
</q-card>
|
||||
</q-dialog>
|
||||
|
||||
<q-dialog v-model="imageModal">
|
||||
<q-dialog v-model="imageModal" :maximized="true">
|
||||
<q-btn
|
||||
icon="close"
|
||||
flat
|
||||
|
|
@ -399,7 +406,10 @@ const splitterModel = computed({
|
|||
class="absolute-top-right z-top text-white"
|
||||
/>
|
||||
|
||||
<q-img :src="selectedImg" fit="contain" style="max-height: 90vh" />
|
||||
<q-img
|
||||
:src="selectedImg"
|
||||
style="max-width: 90vw; max-height: 90vh; object-fit: contain"
|
||||
/>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
42
src/modules/22_issues/interface/Main.ts
Normal file
42
src/modules/22_issues/interface/Main.ts
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import type { D } from "@fullcalendar/core/internal-common";
|
||||
|
||||
interface Options {
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface IssueData {
|
||||
codeIssue: string;
|
||||
createdAt: Date;
|
||||
createdFullName: string;
|
||||
createdUserId: string;
|
||||
description: string;
|
||||
id: string;
|
||||
lastUpdateFullName: string;
|
||||
lastUpdateUserId: string;
|
||||
lastUpdatedAt: Date;
|
||||
menu: string;
|
||||
org: string;
|
||||
remark: string;
|
||||
status: "IN_PROGRESS" | "RESOLVED" | "CLOSED" | "NEW";
|
||||
system: "mgt" | "user" | "checkin";
|
||||
title: string;
|
||||
}
|
||||
|
||||
interface IssueAttachment {
|
||||
fileName: string;
|
||||
path: string;
|
||||
pathname: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
interface IssueAttachmentWithDownloadUrl extends IssueAttachment {
|
||||
downloadUrl: string;
|
||||
}
|
||||
|
||||
export type {
|
||||
Options,
|
||||
IssueData,
|
||||
IssueAttachment,
|
||||
IssueAttachmentWithDownloadUrl,
|
||||
};
|
||||
|
|
@ -1,15 +1,16 @@
|
|||
import { ref } from "vue";
|
||||
import { defineStore } from "pinia";
|
||||
import type { Options } from "@/modules/22_issues/interface/Main";
|
||||
|
||||
export const useIssueStore = defineStore("issue", () => {
|
||||
const systemOptions = ref<any[]>([
|
||||
const systemOptions = ref<Options[]>([
|
||||
{ label: "ทั้งหมด", value: "" },
|
||||
{ label: "ระบบบริหารจัดการ", value: "MGT" },
|
||||
{ label: "ระบบผู้ใช้งาน", value: "USER" },
|
||||
{ label: "ระบบลงเวลา", value: "CHECKIN" },
|
||||
]);
|
||||
|
||||
const statusOptions = ref<any[]>([
|
||||
const statusOptions = ref<Options[]>([
|
||||
{ label: "ทั้งหมด", value: "" },
|
||||
{ label: "ใหม่", value: "NEW" },
|
||||
{ label: "กำลังดำเนินการ", value: "IN_PROGRESS" },
|
||||
|
|
@ -29,7 +30,7 @@ export const useIssueStore = defineStore("issue", () => {
|
|||
case "CLOSED":
|
||||
return "ปิดแล้ว";
|
||||
default:
|
||||
return status;
|
||||
return "-";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -42,6 +43,8 @@ export const useIssueStore = defineStore("issue", () => {
|
|||
return "ระบบผู้ใช้งาน";
|
||||
case "CHECKIN":
|
||||
return "ระบบลงเวลา";
|
||||
default:
|
||||
return "-";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { useCounterMixin } from "@/stores/mixin";
|
|||
import { useIssueStore } from "@/modules/22_issues/store";
|
||||
|
||||
import type { QTableProps } from "quasar";
|
||||
import type { IssueData } from "@/modules/22_issues/interface/Main";
|
||||
|
||||
import DialogViewIssue from "@/modules/22_issues/components/DialogViewIssue.vue";
|
||||
|
||||
|
|
@ -98,16 +99,17 @@ const columns = ref<QTableProps["columns"]>([
|
|||
format: (val: string) => convertStatus(val),
|
||||
},
|
||||
]);
|
||||
const filterKeyword = ref<string>("");
|
||||
const systemFilter = ref<string>("");
|
||||
const statusFilter = ref<string>("NEW");
|
||||
const rows = ref<any[]>([]);
|
||||
const rowsData = ref<any[]>([]);
|
||||
const filterKeyword = ref<string>(""); // ค้นหา
|
||||
const systemFilter = ref<string>(""); // กรองระบบ
|
||||
const statusFilter = ref<string>("NEW"); // กรองสถานะ
|
||||
const rows = ref<IssueData[]>([]); // ข้อมูลตาราง
|
||||
const rowsData = ref<IssueData[]>([]); // ข้อมูลตารางทั้งหมด
|
||||
|
||||
const modal = ref<boolean>(false);
|
||||
const typeModal = ref<string>("view");
|
||||
const dataIssue = ref<any>(null);
|
||||
const modal = ref<boolean>(false); // modal แสดงรายละเอียด
|
||||
const typeModal = ref<string>("view"); // ประเภท modal
|
||||
const dataIssue = ref<IssueData | null>(null); // ข้อมูลรายงานปัญหา
|
||||
|
||||
/** fetch รายการรายงานปัญหา */
|
||||
async function fetchListIssues() {
|
||||
try {
|
||||
showLoader();
|
||||
|
|
@ -121,6 +123,7 @@ async function fetchListIssues() {
|
|||
}
|
||||
}
|
||||
|
||||
/** ค้นหารายการรายงานปัญหา*/
|
||||
function onSearch() {
|
||||
let filtered = onSearchDataTable(
|
||||
filterKeyword.value,
|
||||
|
|
@ -144,12 +147,18 @@ function onSearch() {
|
|||
rows.value = filtered;
|
||||
}
|
||||
|
||||
function onViewDetail(row: any, type: string) {
|
||||
/**
|
||||
* แสดงรายละเอียดรายงานปัญหา
|
||||
* @param row ข้อมูลรายงานปัญหา
|
||||
* @param type ประเภทของ modal
|
||||
*/
|
||||
function onViewDetail(row: IssueData, type: string) {
|
||||
typeModal.value = type;
|
||||
dataIssue.value = row;
|
||||
modal.value = true;
|
||||
}
|
||||
|
||||
/** โหลดข้อมูลเมื่อเข้าหน้า */
|
||||
onMounted(async () => {
|
||||
await fetchListIssues();
|
||||
});
|
||||
|
|
@ -300,7 +309,9 @@ onMounted(async () => {
|
|||
</q-btn>
|
||||
</q-td>
|
||||
<q-td v-for="col in props.cols" :key="col.id">
|
||||
<div>
|
||||
<div
|
||||
:class="col.name === 'description' ? 'table_ellipsis' : ''"
|
||||
>
|
||||
{{ col.value ? col.value : "-" }}
|
||||
</div>
|
||||
</q-td>
|
||||
|
|
@ -311,7 +322,12 @@ onMounted(async () => {
|
|||
</div>
|
||||
</q-card>
|
||||
|
||||
<DialogViewIssue v-model:modal="modal" :type="typeModal" :data="dataIssue" />
|
||||
<DialogViewIssue
|
||||
v-model:modal="modal"
|
||||
:type="typeModal"
|
||||
:data="dataIssue"
|
||||
:fetch-data="fetchListIssues"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue