feat:issue

This commit is contained in:
DESKTOP-1R2VSQH\Lenovo ThinkPad E490 2026-02-03 09:39:38 +07:00
parent c132b077c0
commit f4b7767476
7 changed files with 902 additions and 0 deletions

View file

@ -0,0 +1,327 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { useQuasar } from "quasar";
import { storeToRefs } from "pinia";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useIssueStore } from "@/modules/07_issues/store";
import type { QTableProps } from "quasar";
import type { IssueData } from "@/modules/07_issues/interface/Main";
import DialogViewIssue from "@/modules/07_issues/components/DialogViewIssue.vue";
const $q = useQuasar();
const store = useIssueStore();
const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } =
useCounterMixin();
const { convertStatus, convertSystem } = store;
const { systemOptions, statusOptions } = storeToRefs(store);
const visibleColumns = ref<string[]>([
"title",
"description",
"system",
"menu",
"createdAt",
"createdFullName",
"status",
]);
const columns = ref<QTableProps["columns"]>([
{
name: "title",
align: "left",
label: "หัวข้อปัญหา",
sortable: false,
field: "title",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "description",
align: "left",
label: "รายละเอียด",
sortable: false,
field: "description",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "system",
align: "left",
label: "ระบบ",
sortable: false,
field: "system",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format: (val: string) => convertSystem(val),
},
{
name: "menu",
align: "left",
label: "เมนู",
sortable: false,
field: "menu",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "createdAt",
align: "left",
label: "วันที่สร้าง",
sortable: false,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format: (val: string) => date2Thai(new Date(val), false, true),
},
{
name: "createdFullName",
align: "left",
label: "ชื่อผู้สร้าง",
sortable: false,
field: "createdFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "status",
align: "left",
label: "สถานะ",
sortable: false,
field: "status",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format: (val: string) => convertStatus(val),
},
]);
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); // modal
const typeModal = ref<string>("view"); // modal
const dataIssue = ref<IssueData | null>(null); //
/** fetch รายการรายงานปัญหา */
async function fetchListIssues() {
try {
showLoader();
const res = await http.get(config.API.orgIssues + "/lists");
rowsData.value = res.data.result;
onSearch();
} catch (error) {
messageError($q, error);
} finally {
hideLoader();
}
}
/** ค้นหารายการรายงานปัญหา*/
function onSearch() {
let filtered = onSearchDataTable(
filterKeyword.value,
rowsData.value,
columns.value ? columns.value : [],
);
if (systemFilter.value) {
filtered = filtered.filter(
(item) =>
item.system &&
item.system.toUpperCase() === systemFilter.value.toUpperCase(),
);
}
if (statusFilter.value) {
filtered = filtered.filter(
(item) =>
item.status &&
item.status.toUpperCase() === statusFilter.value.toUpperCase(),
);
}
rows.value = filtered;
}
/**
* แสดงรายละเอยดรายงานปญหา
* @param row อมลรายงานปญหา
* @param type ประเภทของ modal
*/
function onViewDetail(row: IssueData, type: string) {
typeModal.value = type;
dataIssue.value = row;
modal.value = true;
}
/** โหลดข้อมูลเมื่อเข้าหน้า */
onMounted(async () => {
await fetchListIssues();
});
</script>
<template>
<div class="row items-center">
<div class="toptitle text-dark row items-center q-py-xs">
รายการรายงานปญหา
</div>
</div>
<q-card flat bordered class="q-pa-md">
<div class="row col-12 q-col-gutter-sm">
<div class="col-12">
<div class="row q-col-gutter-xs items-end">
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-3">
<div class="row q-col-gutter-sm">
<div class="col-xs-12 col-sm-8 col-md-6">
<q-select
dense
outlined
v-model="systemFilter"
:options="systemOptions"
option-value="value"
option-label="label"
map-options
label="ระบบ"
emit-value
@update:modelValue="onSearch"
>
<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-xs-12 col-sm-8 col-md-6">
<q-select
dense
outlined
v-model="statusFilter"
:options="statusOptions"
option-value="value"
option-label="label"
map-options
label="สถานะ"
emit-value
@update:modelValue="onSearch"
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
ไมอม
</q-item-section>
</q-item>
</template>
</q-select>
</div>
</div>
</div>
<div class="col-xs-0 col-sm-1 col-md-3 col-lg-5"></div>
<div class="col-xs-12 col-sm-5 col-md-3 col-lg-4">
<div class="row q-col-gutter-xs">
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-7">
<q-input
standout
dense
v-model="filterKeyword"
outlined
placeholder="ค้นหา"
@keydown.enter.prevent="onSearch"
>
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
</div>
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-5">
<q-select
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>
</div>
</div>
</div>
<div class="col-12">
<d-table
ref="table"
:columns="columns"
:rows="rows"
row-key="id"
flat
bordered
:paging="true"
dense
:rows-per-page-options="[10, 25, 50, 100]"
:visible-columns="visibleColumns"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width></q-th>
<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">
<q-td auto-width>
<q-btn
round
color="info"
flat
dense
icon="mdi-eye"
@click.prevent.stop="onViewDetail(props.row, 'view')"
>
<q-tooltip>รายละเอยด</q-tooltip>
</q-btn>
<q-btn
round
color="edit"
flat
dense
icon="edit"
@click.prevent.stop="onViewDetail(props.row, 'edit')"
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
</q-td>
<q-td v-for="col in props.cols" :key="col.id">
<div
:class="col.name === 'description' ? 'table_ellipsis' : ''"
>
{{ col.value ? col.value : "-" }}
</div>
</q-td>
</q-tr>
</template>
</d-table>
</div>
</div>
</q-card>
<DialogViewIssue
v-model:modal="modal"
:type="typeModal"
:data="dataIssue"
:fetch-data="fetchListIssues"
/>
</template>
<style scoped></style>