ui Check Workflow
This commit is contained in:
parent
7fcd4968c5
commit
a75773b747
4 changed files with 534 additions and 0 deletions
|
|
@ -99,4 +99,7 @@ export default {
|
|||
/** หมอบหมาย*/
|
||||
commandSysAssign: `${organization}/commandSys/assign`,
|
||||
posAssign: `${organization}/pos/assign`,
|
||||
|
||||
/** View Work Flow*/
|
||||
viewWorkflow: `${organization}/view-workflow`,
|
||||
};
|
||||
|
|
|
|||
73
src/interface/viewWorkflow/response.ts
Normal file
73
src/interface/viewWorkflow/response.ts
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
interface DataWorkflow {
|
||||
name: string;
|
||||
sysName: string;
|
||||
}
|
||||
|
||||
interface WorkflowLists {
|
||||
createdAt: string;
|
||||
createdFullName: string;
|
||||
createdUserId: string;
|
||||
id: string;
|
||||
lastUpdateFullName: string;
|
||||
lastUpdateUserId: string;
|
||||
lastUpdatedAt: string;
|
||||
metaWorkflowId: string;
|
||||
name: string;
|
||||
order: number;
|
||||
type: string;
|
||||
metaStateOperators: MetaStateOperators[];
|
||||
}
|
||||
|
||||
interface MetaStateOperators {
|
||||
canCancel: boolean;
|
||||
canChangeState: boolean;
|
||||
canComment: boolean;
|
||||
canDelete: boolean;
|
||||
canOperate: boolean;
|
||||
canSign: boolean;
|
||||
canUpdate: boolean;
|
||||
canView: boolean;
|
||||
createdAt: string;
|
||||
createdFullName: string;
|
||||
createdUserId: string;
|
||||
id: string;
|
||||
lastUpdateFullName: string;
|
||||
lastUpdateUserId: string;
|
||||
lastUpdatedAt: string;
|
||||
metaStateId: string;
|
||||
operator: string;
|
||||
}
|
||||
|
||||
interface OptionsType {
|
||||
id: string;
|
||||
name: string;
|
||||
posLevels: PosLevel[];
|
||||
}
|
||||
|
||||
interface OptionsLevel {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface PosType {
|
||||
id: string;
|
||||
posTypeName: string;
|
||||
posTypeRank: number;
|
||||
posLevels: PosLevel[];
|
||||
}
|
||||
|
||||
interface PosLevel {
|
||||
id: string;
|
||||
posLevelAuthority: string;
|
||||
posLevelName: string;
|
||||
posLevelRank: number;
|
||||
}
|
||||
|
||||
export type {
|
||||
WorkflowLists,
|
||||
DataWorkflow,
|
||||
OptionsType,
|
||||
OptionsLevel,
|
||||
PosType,
|
||||
PosLevel,
|
||||
};
|
||||
|
|
@ -4,6 +4,7 @@ const MainLayout = () => import("@/views/MainLayout.vue");
|
|||
const Dashboard = () => import("@/views/Dashboard.vue");
|
||||
const Error404NotFound = () => import("@/views/Error404NotFound.vue");
|
||||
const loginView = () => import("@/views/login.vue");
|
||||
const CheckWorkflow = () => import("@/views/CheckWorkflow.vue");
|
||||
|
||||
import ModuleMetadata from "@/modules/01_metadata/router";
|
||||
import ModuleUser from "@/modules/02_users/router";
|
||||
|
|
@ -32,6 +33,16 @@ const router = createRouter({
|
|||
Role: ["SUPER_ADMIN", "ADMIN"],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/check-workflow",
|
||||
name: "check-workflow",
|
||||
component: CheckWorkflow,
|
||||
meta: {
|
||||
Auth: true,
|
||||
Key: [7],
|
||||
Role: ["SUPER_ADMIN", "ADMIN"],
|
||||
},
|
||||
},
|
||||
...ModuleMetadata,
|
||||
...ModuleUser,
|
||||
...ModuleLogs,
|
||||
|
|
|
|||
447
src/views/CheckWorkflow.vue
Normal file
447
src/views/CheckWorkflow.vue
Normal file
|
|
@ -0,0 +1,447 @@
|
|||
<script setup lang="ts">
|
||||
import { onMounted, reactive, ref } from "vue";
|
||||
import { useQuasar } from "quasar";
|
||||
|
||||
import { useCounterMixin } from "@/stores/mixin";
|
||||
import http from "@/plugins/http";
|
||||
import config from "@/app.config";
|
||||
|
||||
import type { QTableProps } from "quasar";
|
||||
import type {
|
||||
WorkflowLists,
|
||||
DataWorkflow,
|
||||
OptionsType,
|
||||
OptionsLevel,
|
||||
PosType,
|
||||
PosLevel,
|
||||
} from "@/interface/viewWorkflow/response";
|
||||
|
||||
const $q = useQuasar();
|
||||
const { showLoader, hideLoader, messageError } = useCounterMixin();
|
||||
|
||||
const isSearch = ref<boolean>(false);
|
||||
const formFilter = reactive({
|
||||
name: "",
|
||||
type: "",
|
||||
level: "",
|
||||
});
|
||||
|
||||
const dataWorkflow = ref<DataWorkflow[]>([]);
|
||||
const dataType = ref<OptionsType[]>([]);
|
||||
const dataLevel = ref<OptionsLevel[]>([]);
|
||||
const optionName = ref<DataWorkflow[]>([]);
|
||||
const optionType = ref<OptionsType[]>([]);
|
||||
const optionLevel = ref<OptionsLevel[]>([]);
|
||||
|
||||
const rows = ref<WorkflowLists[]>([]);
|
||||
const expanded = ref<string[]>(["รอดำเนินการ"]);
|
||||
const columns = ref<QTableProps["columns"]>([
|
||||
{
|
||||
name: "name",
|
||||
align: "left",
|
||||
label: "ขั้นตอนการทำงาน",
|
||||
sortable: false,
|
||||
field: "name",
|
||||
headerStyle: "font-size: 14px",
|
||||
style: "font-size: 14px",
|
||||
},
|
||||
]);
|
||||
const columnsExpanded = ref<QTableProps["columns"]>([
|
||||
{
|
||||
name: "operator",
|
||||
align: "left",
|
||||
label: "ผู้ดำเนินการ",
|
||||
sortable: false,
|
||||
field: "operator",
|
||||
headerStyle: "font-size: 14px",
|
||||
style: "font-size: 14px",
|
||||
},
|
||||
{
|
||||
name: "canCancel",
|
||||
align: "left",
|
||||
label: "canCancel",
|
||||
sortable: false,
|
||||
field: "canCancel",
|
||||
headerStyle: "font-size: 14px",
|
||||
style: "font-size: 14px",
|
||||
},
|
||||
{
|
||||
name: "canChangeState",
|
||||
align: "left",
|
||||
label: "canChangeState",
|
||||
sortable: false,
|
||||
field: "canChangeState",
|
||||
headerStyle: "font-size: 14px",
|
||||
style: "font-size: 14px",
|
||||
},
|
||||
{
|
||||
name: "canComment",
|
||||
align: "left",
|
||||
label: "canComment",
|
||||
sortable: false,
|
||||
field: "canComment",
|
||||
headerStyle: "font-size: 14px",
|
||||
style: "font-size: 14px",
|
||||
},
|
||||
{
|
||||
name: "canDelete",
|
||||
align: "left",
|
||||
label: "canDelete",
|
||||
sortable: false,
|
||||
field: "canDelete",
|
||||
headerStyle: "font-size: 14px",
|
||||
style: "font-size: 14px",
|
||||
},
|
||||
{
|
||||
name: "canOperate",
|
||||
align: "left",
|
||||
label: "canOperate",
|
||||
sortable: false,
|
||||
field: "canOperate",
|
||||
headerStyle: "font-size: 14px",
|
||||
style: "font-size: 14px",
|
||||
},
|
||||
{
|
||||
name: "canSign",
|
||||
align: "left",
|
||||
label: "canSign",
|
||||
sortable: false,
|
||||
field: "canSign",
|
||||
headerStyle: "font-size: 14px",
|
||||
style: "font-size: 14px",
|
||||
},
|
||||
{
|
||||
name: "canUpdate",
|
||||
align: "left",
|
||||
label: "canUpdate",
|
||||
sortable: false,
|
||||
field: "canUpdate",
|
||||
headerStyle: "font-size: 14px",
|
||||
style: "font-size: 14px",
|
||||
},
|
||||
{
|
||||
name: "canView",
|
||||
align: "left",
|
||||
label: "canView",
|
||||
sortable: false,
|
||||
field: "canView",
|
||||
headerStyle: "font-size: 14px",
|
||||
style: "font-size: 14px",
|
||||
},
|
||||
]);
|
||||
|
||||
function fetchWorkflowList() {
|
||||
http
|
||||
.get(config.API.viewWorkflow + `/lists`)
|
||||
.then((res) => {
|
||||
const data = res.data.result;
|
||||
dataWorkflow.value = data;
|
||||
optionName.value = data;
|
||||
})
|
||||
.catch((err) => {
|
||||
messageError($q, err);
|
||||
});
|
||||
}
|
||||
|
||||
function fetchType() {
|
||||
http
|
||||
.get(config.API.orgPosType)
|
||||
.then((res) => {
|
||||
const data = res.data.result;
|
||||
dataType.value = data.map((e: PosType) => ({
|
||||
id: e.posTypeName,
|
||||
name: e.posTypeName,
|
||||
posLevels: e.posLevels,
|
||||
}));
|
||||
optionType.value = dataType.value;
|
||||
})
|
||||
.catch((err) => {
|
||||
messageError($q, err);
|
||||
});
|
||||
}
|
||||
|
||||
function onSelectPosType(id: string) {
|
||||
const data = dataType.value.find(
|
||||
(e: OptionsType) => e.id === id && e.posLevels
|
||||
)?.posLevels;
|
||||
|
||||
dataLevel.value =
|
||||
data?.map((e: PosLevel) => ({
|
||||
id: e.posLevelName,
|
||||
name: e.posLevelName,
|
||||
})) || [];
|
||||
|
||||
formFilter.level = "";
|
||||
}
|
||||
|
||||
async function searchWorkflow() {
|
||||
if (
|
||||
formFilter.name !== "" &&
|
||||
formFilter.type !== "" &&
|
||||
formFilter.level !== ""
|
||||
) {
|
||||
showLoader();
|
||||
rows.value = [];
|
||||
await http
|
||||
.get(
|
||||
config.API.viewWorkflow +
|
||||
`?sysName=${formFilter.name}&posTypeName=${formFilter.type}&posLevelName=${formFilter.level}`
|
||||
)
|
||||
.then(async (res) => {
|
||||
const data = await res.data.result;
|
||||
if (data && data[0]?.metaStates) {
|
||||
rows.value = data[0].metaStates;
|
||||
expanded.value = rows.value.map((e: WorkflowLists) => e.name);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
messageError($q, err);
|
||||
})
|
||||
.finally(() => {
|
||||
hideLoader();
|
||||
isSearch.value = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function filterSelector(val: string, update: Function, refData: string) {
|
||||
switch (refData) {
|
||||
case "name":
|
||||
update(() => {
|
||||
optionName.value = dataWorkflow.value.filter(
|
||||
(v: DataWorkflow) => v.name.indexOf(val) > -1
|
||||
);
|
||||
});
|
||||
break;
|
||||
|
||||
case "type":
|
||||
update(() => {
|
||||
optionType.value = dataType.value.filter(
|
||||
(v: OptionsType) => v.name.indexOf(val) > -1
|
||||
);
|
||||
});
|
||||
break;
|
||||
|
||||
case "level":
|
||||
update(() => {
|
||||
optionLevel.value = dataLevel.value.filter(
|
||||
(v: OptionsLevel) => v.name.indexOf(val) > -1
|
||||
);
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
showLoader();
|
||||
await Promise.all([fetchType(), fetchWorkflowList()]).finally(() => {
|
||||
hideLoader();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="toptitle text-dark col-12 row items-center">Check Workflow</div>
|
||||
|
||||
<div class="q-pa-sm">
|
||||
<q-card>
|
||||
<div class="row col-12 q-mb-sm">
|
||||
<q-form
|
||||
class="col-12"
|
||||
q-form
|
||||
greedy
|
||||
@submit.prevent
|
||||
@validation-success="searchWorkflow"
|
||||
>
|
||||
<div class="row justify-between q-gutter-y-sm q-pa-lg">
|
||||
<div class="col-6 col-md-4">
|
||||
<q-select
|
||||
dense
|
||||
outlined
|
||||
use-input
|
||||
lazy-rules
|
||||
emit-value
|
||||
map-options
|
||||
hide-bottom-space
|
||||
option-label="name"
|
||||
option-value="sysName"
|
||||
v-model="formFilter.name"
|
||||
:options="optionName"
|
||||
label="Workflow"
|
||||
:rules="[(val: string) => !!val || `${'กรุณาเลือก Workflow'}`]"
|
||||
@filter="(inputValue: string,
|
||||
doneFn: Function) => filterSelector(inputValue, doneFn, 'name'
|
||||
)"
|
||||
>
|
||||
<template v-slot:no-option>
|
||||
<q-item>
|
||||
<q-item-section class="text-italic text-grey">
|
||||
ไม่มีข้อมูล
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
</q-select>
|
||||
</div>
|
||||
<div class="col-5 col-md-3">
|
||||
<q-select
|
||||
dense
|
||||
outlined
|
||||
use-input
|
||||
lazy-rules
|
||||
emit-value
|
||||
map-options
|
||||
hide-bottom-space
|
||||
option-label="name"
|
||||
option-value="id"
|
||||
v-model="formFilter.type"
|
||||
:options="optionType"
|
||||
@update:model-value="onSelectPosType"
|
||||
label="ประเภทตำแหน่ง"
|
||||
:rules="[(val: string) => !!val || `${'กรุณาเลือก ประเภทตำแหน่ง'}`]"
|
||||
@filter="(inputValue: string,
|
||||
doneFn: Function) => filterSelector(inputValue, doneFn, 'type'
|
||||
)"
|
||||
>
|
||||
<template v-slot:no-option>
|
||||
<q-item>
|
||||
<q-item-section class="text-italic text-grey">
|
||||
ไม่มีข้อมูล
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
</q-select>
|
||||
</div>
|
||||
<div class="col-5 col-md-3">
|
||||
<q-select
|
||||
dense
|
||||
outlined
|
||||
use-input
|
||||
lazy-rules
|
||||
emit-value
|
||||
map-options
|
||||
hide-bottom-space
|
||||
option-label="name"
|
||||
option-value="id"
|
||||
v-model="formFilter.level"
|
||||
:options="optionLevel"
|
||||
label="ระดับตำแหน่ง"
|
||||
:rules="[(val: string) => !!val || `${'กรุณาเลือก ระดับตำแหน่ง'}`]"
|
||||
@filter="(inputValue: string,
|
||||
doneFn: Function) => filterSelector(inputValue, doneFn, 'level'
|
||||
)"
|
||||
>
|
||||
<template v-slot:no-option>
|
||||
<q-item>
|
||||
<q-item-section class="text-italic text-grey">
|
||||
ไม่มีข้อมูล
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
</q-select>
|
||||
</div>
|
||||
|
||||
<q-btn
|
||||
type="submit"
|
||||
dense
|
||||
unelevated
|
||||
color="primary"
|
||||
class="col-5 col-md-1"
|
||||
label="ค้นหา"
|
||||
/>
|
||||
</div>
|
||||
</q-form>
|
||||
</div>
|
||||
|
||||
<q-card v-if="isSearch">
|
||||
<d-table
|
||||
v-if="rows.length !== 0"
|
||||
flat
|
||||
bordered
|
||||
:rows="rows"
|
||||
:columns="columns"
|
||||
row-key="name"
|
||||
v-model:expanded="expanded"
|
||||
:hide-bottom="true"
|
||||
>
|
||||
<template v-slot:header="props">
|
||||
<q-tr :props="props">
|
||||
<q-th v-for="col in props.cols" :key="col.name" :props="props">
|
||||
{{ col.label }}
|
||||
</q-th>
|
||||
</q-tr>
|
||||
</template>
|
||||
|
||||
<template v-slot:body="props">
|
||||
<q-tr :props="props">
|
||||
<q-td v-for="col in props.cols" :key="col.name" :props="props">
|
||||
{{ col.value }}
|
||||
</q-td>
|
||||
</q-tr>
|
||||
<q-tr v-show="props.expand" :props="props">
|
||||
<q-td colspan="100%">
|
||||
<div class="q-pa-md">
|
||||
<q-card bordered>
|
||||
<q-card-section style="padding: 0px">
|
||||
<d-table
|
||||
flat
|
||||
bordered
|
||||
:rows="props.row.metaStateOperators"
|
||||
:columns="columnsExpanded"
|
||||
row-key="name"
|
||||
:hide-bottom="true"
|
||||
>
|
||||
<template v-slot:header="props">
|
||||
<q-tr :props="props">
|
||||
<q-th
|
||||
v-for="col in props.cols"
|
||||
:key="col.name"
|
||||
:props="props"
|
||||
>
|
||||
{{ col.label }}
|
||||
</q-th>
|
||||
</q-tr>
|
||||
</template>
|
||||
|
||||
<template v-slot:body="props">
|
||||
<q-tr :props="props">
|
||||
<q-td
|
||||
v-for="col in props.cols"
|
||||
:key="col.name"
|
||||
:props="props"
|
||||
>
|
||||
<div v-if="col.name !== 'operator'">
|
||||
<q-icon
|
||||
v-if="col.value"
|
||||
name="check"
|
||||
color="primary"
|
||||
size="sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
{{ col.value }}
|
||||
</div>
|
||||
</q-td>
|
||||
</q-tr>
|
||||
</template>
|
||||
</d-table>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</div>
|
||||
</q-td>
|
||||
</q-tr>
|
||||
</template>
|
||||
</d-table>
|
||||
|
||||
<q-banner inline-actions rounded class="bg-grey-1 text-center" v-else>
|
||||
ไม่มีข้อมูล
|
||||
</q-banner>
|
||||
</q-card>
|
||||
</q-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
Loading…
Add table
Add a link
Reference in a new issue