mirror of
https://git.hmsn.ink/kospo/svcm/oa.git
synced 2026-03-20 07:23:50 +09:00
fix : 파일 이름수정
This commit is contained in:
442
src/pages/app/ApprovalManagement.vue
Normal file
442
src/pages/app/ApprovalManagement.vue
Normal file
@@ -0,0 +1,442 @@
|
||||
<script setup lang="ts">
|
||||
import { getIntegratedApproval } from '/src/service/integratedApproval'
|
||||
import type { VFlexTableWrapperSortFunction, VFlexTableWrapperFilterFunction } from '/src/components/app-vuero/ComVFlexTableWrapper.vue'
|
||||
import { users } from '/src/data/layouts/card-grid-v1'
|
||||
import PriceDetail from "/@src/pages/app/priceDetail.vue";
|
||||
import {conveterNo, updateApprovalStatus} from "/@src/service/approvalApi.ts";
|
||||
|
||||
|
||||
onBeforeMount(async () => {
|
||||
await getIntegratedPaymentList()
|
||||
})
|
||||
const isModalOpen = ref(false)
|
||||
const selectedRow = ref<any>(null)
|
||||
const prcsNo = ref<string>('')
|
||||
const router = useRouter()
|
||||
|
||||
const masks = ref({
|
||||
modelValue: 'YYYY-MM-DD',
|
||||
})
|
||||
const notyf = useNotyf()
|
||||
|
||||
const params = reactive({
|
||||
title: '',
|
||||
priceData: [],
|
||||
flexColumn: [
|
||||
{ key: 'apprNo', label: '결재번호', cellClass: 'paymentColumn1' },
|
||||
{ key: 'title', label: '제목', cellClass: 'paymentColumn2' },
|
||||
{ key: 'name', label: '작성자', cellClass: 'paymentColumn3' },
|
||||
{
|
||||
key: 'regDt',
|
||||
label: '등록일',
|
||||
cellClass: 'paymentColumn4',
|
||||
format: formatRegDt,
|
||||
},
|
||||
{ key: 'process', label: '구분', cellClass: 'paymentColumn5' },
|
||||
],
|
||||
flexWrapperColumn: {
|
||||
apprNo: { label: '결재번호', cellClass: 'paymentColumn1', searchable: true, sortable: true },
|
||||
title: { label: '제목', cellClass: 'paymentColumn2', searchable: true, sortable: true },
|
||||
name: { label: '작성자', cellClass: 'paymentColumn3', searchable: true, sortable: true },
|
||||
regDt: { label: '등록일', cellClass: 'paymentColumn4', searchable: true, sortable: true },
|
||||
process: { label: '구분', cellClass: 'paymentColumn5', searchable: true, sortable: true },
|
||||
},
|
||||
paymentParams: [],
|
||||
rowData: [],
|
||||
})
|
||||
|
||||
function formatRegDt(value) {
|
||||
return value ? value.substring(0, 16) : ''
|
||||
}
|
||||
|
||||
async function getIntegratedPaymentList() {
|
||||
const paymentParams = {
|
||||
title: '',
|
||||
page: '1',
|
||||
row: '10',
|
||||
sabun: '17131303', // 김진형 17131303, 손원창 17131304
|
||||
}
|
||||
const result = await getIntegratedApproval(paymentParams)
|
||||
params.paymentParams = result.content.map(item => ({
|
||||
...item,
|
||||
process: gubunMap[item.gubun] || '',
|
||||
}))
|
||||
}
|
||||
|
||||
async function updateIntegratedPaymentApprovalFunc() {
|
||||
const paymentUpdateParams = {
|
||||
apprNo: params.rowData.apprNo,
|
||||
apprOrd: params.rowData.apprOrd,
|
||||
sabun: params.rowData.sabun,
|
||||
apprStatCd: '0200', // 결재 상태변경 (결재승인 0200 결재회수 0300 결재반려 0400)
|
||||
reason: '',
|
||||
}
|
||||
const result = await updateApprovalStatus(paymentUpdateParams)
|
||||
notyf.primary("결재승인완료")
|
||||
window.location.reload()
|
||||
}
|
||||
|
||||
async function updateIntegratedPaymentRejectionFunc() {
|
||||
const paymentUpdateParams = {
|
||||
apprNo: params.rowData.apprNo,
|
||||
apprOrd: params.rowData.apprOrd,
|
||||
sabun: params.rowData.sabun,
|
||||
apprStatCd: '0400', // 결재 상태변경 (결재승인 0200 결재회수 0300 결재반려 0400)
|
||||
reason: '',
|
||||
}
|
||||
const result = await updateApprovalStatus(paymentUpdateParams)
|
||||
notyf.primary("결재반려완료")
|
||||
window.location.reload()
|
||||
}
|
||||
|
||||
const gubunMap = {
|
||||
SAP: '전표생성',
|
||||
SVCM: '가격조사',
|
||||
}
|
||||
|
||||
const searchApproval = async () => {
|
||||
const paymentParams = {
|
||||
params: {
|
||||
title: params.title,
|
||||
page: '1',
|
||||
row: '10',
|
||||
},
|
||||
}
|
||||
const result = await getIntegratedApproval(paymentParams)
|
||||
params.paymentParams = result.content
|
||||
console.log(params.paymentParams)
|
||||
}
|
||||
|
||||
type User = (typeof users)[0]
|
||||
|
||||
// duplicate user data to grow the array
|
||||
const data: User[] = []
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
data.push(...users)
|
||||
}
|
||||
|
||||
// this is a sample for custom sort function
|
||||
const locationSorter: VFlexTableWrapperSortFunction<User> = ({ order, a, b }) => {
|
||||
if (order === 'asc') {
|
||||
return a.location.localeCompare(b.location)
|
||||
}
|
||||
else if (order === 'desc') {
|
||||
return b.location.localeCompare(a.location)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// this is a sample for custom filter function
|
||||
const userFilter: VFlexTableWrapperFilterFunction<User> = ({ searchTerm, row }) => {
|
||||
if (!searchTerm) {
|
||||
return true
|
||||
}
|
||||
|
||||
// search either in the name or the bio
|
||||
return (
|
||||
row.name.toLocaleLowerCase().includes(searchTerm.toLocaleLowerCase())
|
||||
|| row.bio.toLocaleLowerCase().includes(searchTerm.toLocaleLowerCase())
|
||||
)
|
||||
}
|
||||
|
||||
const onRowClick = async (row) => {
|
||||
params.rowData = row
|
||||
try {
|
||||
const params = {
|
||||
apprNo: row.apprNo,
|
||||
sabun: row.sabun
|
||||
}
|
||||
console.log(params)
|
||||
// API 호출
|
||||
const result = await conveterNo(params)
|
||||
|
||||
// 모달 무조건 열기
|
||||
isModalOpen.value = true
|
||||
|
||||
// prcsNo 설정 (응답 구조에 맞게 수정)
|
||||
if (result?.prcsNo) {
|
||||
prcsNo.value = result.prcsNo
|
||||
} else {
|
||||
notyf.error('가격조사번호를 찾을 수 없습니다.')
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
isModalOpen.value = true // 에러 시에도 모달 열기
|
||||
notyf.error(e.message)
|
||||
}
|
||||
}
|
||||
|
||||
const onRowClick2 = (row: any) => {
|
||||
selectedRow.value = row
|
||||
isModalOpen.value = true
|
||||
prcsNo.value = row.prcsNo
|
||||
// prcsNo.value = 'PRCS-20250527049'
|
||||
console.log(row.apprNo)
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="page-content is-navbar-lg">
|
||||
<div>
|
||||
<div class="datatable-toolbar">
|
||||
<div class="column is-2">
|
||||
<VField class="pr-2">
|
||||
<VLabel class="has-fullwidth">
|
||||
결재제목
|
||||
</VLabel>
|
||||
<VControl>
|
||||
<input
|
||||
v-model="params.title"
|
||||
class="input custom-text-filter"
|
||||
placeholder="결재제목"
|
||||
>
|
||||
</VControl>
|
||||
</VField>
|
||||
</div>
|
||||
<div class="column is-5">
|
||||
<VField class="pr-2">
|
||||
<VLabel class="has-fullwidth">
|
||||
등록기간
|
||||
</VLabel>
|
||||
<VControl>
|
||||
<div class="columns">
|
||||
<div class="column is-6">
|
||||
<VDatePicker
|
||||
v-model.string="params.regSdt"
|
||||
color="green"
|
||||
:masks="masks"
|
||||
trim-weeks
|
||||
>
|
||||
<template #default="{ inputValue, inputEvents }">
|
||||
<VField>
|
||||
<VControl icon="lucide:calendar">
|
||||
<input
|
||||
class="input v-input"
|
||||
type="text"
|
||||
:value="inputValue"
|
||||
placeholder="시작일"
|
||||
v-on="inputEvents"
|
||||
>
|
||||
</VControl>
|
||||
</VField>
|
||||
</template>
|
||||
</VDatePicker>
|
||||
</div>
|
||||
<div style="transform: translateY(15px)">
|
||||
~
|
||||
</div>
|
||||
<div class="column is-6">
|
||||
<VDatePicker
|
||||
v-model.string="params.regEdt"
|
||||
color="green"
|
||||
:masks="masks"
|
||||
trim-weeks
|
||||
>
|
||||
<template #default="{ inputValue, inputEvents }">
|
||||
<VField>
|
||||
<VControl icon="lucide:calendar">
|
||||
<input
|
||||
class="input v-input"
|
||||
type="text"
|
||||
:value="inputValue"
|
||||
placeholder="종료일"
|
||||
v-on="inputEvents"
|
||||
>
|
||||
</VControl>
|
||||
</VField>
|
||||
</template>
|
||||
</VDatePicker>
|
||||
</div>
|
||||
</div>
|
||||
</VControl>
|
||||
</VField>
|
||||
</div>
|
||||
<div class="column is-1">
|
||||
<div style="padding-top:20px;float:right;">
|
||||
<VButtons>
|
||||
<VButton
|
||||
color="primary"
|
||||
elevated
|
||||
icon="fas fa-search"
|
||||
@click.stop="searchApproval"
|
||||
>
|
||||
검색
|
||||
</VButton>
|
||||
</VButtons>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="datatable-wrapper">
|
||||
<ComVFlexTable
|
||||
:data="params.paymentParams"
|
||||
:columns="params.flexColumn"
|
||||
:separators="true"
|
||||
:clickable="true"
|
||||
:compact="true"
|
||||
:use-payment-header="true"
|
||||
@row-click="onRowClick"
|
||||
>
|
||||
<template #payment-header>
|
||||
<div class="flex-table-header">
|
||||
<span class="flex-table-item paymentColumn1">결재번호</span>
|
||||
<span class="flex-table-item paymentColumn2">제목</span>
|
||||
<span class="flex-table-item paymentColumn3">작성자</span>
|
||||
<span class="flex-table-item paymentColumn4">등록일</span>
|
||||
<span class="flex-table-item paymentColumn5">구분</span>
|
||||
</div>
|
||||
</template>
|
||||
</ComVFlexTable>
|
||||
|
||||
<!-- 모달 컴포넌트 추가 -->
|
||||
<VModal
|
||||
is="form"
|
||||
v-model:open="isModalOpen"
|
||||
title="결재함"
|
||||
size="contract-big"
|
||||
actions="center"
|
||||
@submit.prevent="isModalOpen = false"
|
||||
@close="isModalOpen = false"
|
||||
>
|
||||
<template #content>
|
||||
<PriceDetail :prcsNo="prcsNo" />
|
||||
</template>
|
||||
<template #action>
|
||||
<VButton type="submit" color="info" raised @click="updateIntegratedPaymentRejectionFunc">반려</VButton>
|
||||
<VButton type="submit" color="primary" raised @click="updateIntegratedPaymentApprovalFunc">승인</VButton>
|
||||
</template>
|
||||
</VModal>
|
||||
<!-- <VFlexTableWrapper :columns="params.flexWrapperColumn" :data="params.paymentParams">-->
|
||||
<!--<!–-->
|
||||
<!-- Here we retrieve the internal wrapperState.-->
|
||||
<!-- Note that we can not destructure it-->
|
||||
<!-- –>-->
|
||||
<!-- <template #default="wrapperState">-->
|
||||
<!-- <pre>data: {{ data }}</pre>-->
|
||||
<!-- <!– We can place any content inside the default slot–>-->
|
||||
<!-- <VFlexTableToolbar>-->
|
||||
<!-- <template #left>-->
|
||||
<!-- <!– We can bind wrapperState.searchInput to any input –>-->
|
||||
<!-- <VField>-->
|
||||
<!-- <VControl icon="lucide:search">-->
|
||||
<!-- <input-->
|
||||
<!-- v-model="wrapperState.searchInput"-->
|
||||
<!-- type="text"-->
|
||||
<!-- class="input is-rounded"-->
|
||||
<!-- placeholder="Filter..."-->
|
||||
<!-- >-->
|
||||
<!-- </VControl>-->
|
||||
<!-- </VField>-->
|
||||
<!-- </template>-->
|
||||
|
||||
<!-- <template #right>-->
|
||||
<!-- <!– We can also bind wrapperState.limit –>-->
|
||||
<!-- <VField>-->
|
||||
<!-- <VControl>-->
|
||||
<!-- <div class="select is-rounded">-->
|
||||
<!-- <select v-model="wrapperState.limit">-->
|
||||
<!-- <option :value="1">-->
|
||||
<!-- 1 results per page-->
|
||||
<!-- </option>-->
|
||||
<!-- <option :value="10">-->
|
||||
<!-- 10 results per page-->
|
||||
<!-- </option>-->
|
||||
<!-- <option :value="15">-->
|
||||
<!-- 15 results per page-->
|
||||
<!-- </option>-->
|
||||
<!-- <option :value="25">-->
|
||||
<!-- 25 results per page-->
|
||||
<!-- </option>-->
|
||||
<!-- <option :value="50">-->
|
||||
<!-- 50 results per page-->
|
||||
<!-- </option>-->
|
||||
<!-- </select>-->
|
||||
<!-- </div>-->
|
||||
<!-- </VControl>-->
|
||||
<!-- </VField>-->
|
||||
<!-- </template>-->
|
||||
<!-- </VFlexTableToolbar>-->
|
||||
|
||||
<!-- <!–-->
|
||||
<!-- The VFlexTable "data" and "columns" props-->
|
||||
<!-- will be inherited from parent VFlexTableWrapper-->
|
||||
<!-- –>-->
|
||||
<!-- <VFlexTable rounded>-->
|
||||
<!-- <!– Custom "name" cell content –>-->
|
||||
<!-- <template #body-cell="{ row, column }">-->
|
||||
<!-- <template v-if="column.key === 'name'">-->
|
||||
<!-- <VAvatar-->
|
||||
<!-- size="medium"-->
|
||||
<!-- :picture="row.medias.avatar"-->
|
||||
<!-- :badge="row.medias.badge"-->
|
||||
<!-- :initials="row.initials"-->
|
||||
<!-- />-->
|
||||
<!-- <div>-->
|
||||
<!-- <span class="dark-text" :title="row.name">-->
|
||||
<!-- {{ row?.shortname }}-->
|
||||
<!-- </span>-->
|
||||
<!-- <VTextEllipsis-->
|
||||
<!-- width="280px"-->
|
||||
<!-- class="light-text"-->
|
||||
<!-- :title="row.bio"-->
|
||||
<!-- >-->
|
||||
<!-- <small>{{ row?.bio }}</small>-->
|
||||
<!-- </VTextEllipsis>-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
<!-- </template>-->
|
||||
<!-- </VFlexTable>-->
|
||||
|
||||
<!-- <!– Table Pagination with wrapperState.page binded–>-->
|
||||
<!-- <VFlexPagination-->
|
||||
<!-- v-model:current-page="wrapperState.page"-->
|
||||
<!-- class="mt-6"-->
|
||||
<!-- :item-per-page="wrapperState.limit"-->
|
||||
<!-- :total-items="wrapperState.total"-->
|
||||
<!-- :max-links-displayed="5"-->
|
||||
<!-- no-router-->
|
||||
<!-- />-->
|
||||
<!-- </template>-->
|
||||
<!-- </VFlexTableWrapper>-->
|
||||
</div>
|
||||
</div>
|
||||
<!-- <VButtons class="v-buttons-right-align">-->
|
||||
<!-- <VButton-->
|
||||
<!-- color="primary"-->
|
||||
<!-- icon="fas fa-plus"-->
|
||||
<!-- elevated-->
|
||||
<!-- to="/app/PriceInsert"-->
|
||||
<!-- >-->
|
||||
<!-- 등록-->
|
||||
<!-- </VButton>-->
|
||||
<!-- </VButtons>-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
input[readonly] {
|
||||
background-color: #f5f5f5; /* 살짝 회색 배경 */
|
||||
color: #888; /* 글자색 연하게 */
|
||||
cursor: not-allowed; /* 마우스 커서 변경 */
|
||||
border-color: #e0e0e0; /* 테두리 연하게 */
|
||||
}
|
||||
|
||||
.v-buttons-right-align {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 1rem; // 필요 시 간격 추가
|
||||
}
|
||||
|
||||
.flex-table .flex-table-item {
|
||||
background-color: var(--primary);
|
||||
border: 0px;
|
||||
}
|
||||
.flex-table .flex-table-header {
|
||||
padding: 0px;
|
||||
}
|
||||
.flex-table.is-table-clickable .flex-table-item:hover, .flex-table.is-table-clickable .flex-table-item:focus-within a:hover {
|
||||
background-color: var(--primary)!important;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user