fix : 계약관리 등록폼 수정

- 체크박스 여부에 따른 input창 disable
This commit is contained in:
Kasi
2025-05-27 15:04:00 +09:00
parent f586d520bc
commit 244a3d9f9c
3 changed files with 476 additions and 36 deletions

View File

@@ -3,10 +3,12 @@
import axios from 'axios' import axios from 'axios'
import {saveContract} from "/@src/service/contract.ts"; import {saveContract} from "/@src/service/contract.ts";
import type {iPbAtt} from "/@src/utils/types.ts"; import type {iPbAtt} from "/@src/utils/types.ts";
import {useRouter} from "vue-router";
const registerFormOpen = ref(false) const registerFormOpen = ref(false)
const loading = ref(false) const loading = ref(false)
const notyf = useNotyf() const notyf = useNotyf()
const router = useRouter()
const params = reactive({ const params = reactive({
cateCd: '', cateCd: '',
contNo: '', contNo: '',
@@ -46,7 +48,7 @@ const completedPriceDataParams = reactive({
svyDt:'', svyDt:'',
reason:'', reason:'',
estimates: [], estimates: [],
exeYn: false, excYn: false,
page: 1, page: 1,
row: 5, row: 5,
}) })
@@ -158,7 +160,6 @@ function handlePriceRowClick(row) {
} }
registerFormOpen.value = false registerFormOpen.value = false
priceSearchCheckBoxStatus.value = !!row
console.log(row) console.log(row)
console.log(completedPriceDataParams.contAmt) console.log(completedPriceDataParams.contAmt)
} }
@@ -184,31 +185,23 @@ const saveContOne = async () => {
const paramsCont ={ const paramsCont ={
prcsNo: completedPriceDataParams.prcsNo, prcsNo: completedPriceDataParams.prcsNo,
bizNo: completedPriceDataParams.bizNo, bizNo: completedPriceDataParams.bizNo,
cateCd: priceSearchCheckBoxStatus.value ? selectedCode.value : completedPriceDataParams.cateCd,
compNm: completedPriceDataParams.compNm, compNm: completedPriceDataParams.compNm,
title: completedPriceDataParams.title, title: completedPriceDataParams.title,
regSdat: formatMonthDate(completedPriceDataParams.regSdat), regSdat: formatMonthDate(completedPriceDataParams.regSdat),
regEdat: formatMonthDate(completedPriceDataParams.regEdat), regEdat: formatMonthDate(completedPriceDataParams.regEdat),
contAmt: completedPriceDataParams.contAmt, contAmt: completedPriceDataParams.contAmt,
signDt: formatMonthDate(completedPriceDataParams.svyDt), signDt: formatMonthDate(completedPriceDataParams.regSdat),
reason: completedPriceDataParams.reason, reason: completedPriceDataParams.reason,
exeYn: true, // 가격조사 예외여부 확인필요 excYn: priceSearchCheckBoxStatus.value, // 가격조사 예외여부 확인필요
// contAtts: pbAtts.value., contAtts: params.contAtts,
// cateCd: completedPriceDataParams.cateCd,
// cateNm: completedPriceDataParams.cateNm,
// content: completedPriceDataParams.content,
// regSabun: completedPriceDataParams.regSabun,
// regNm: completedPriceDataParams.regNm,
// regDt: formatMonthDate(completedPriceDataParams.regDt),
// stCd: completedPriceDataParams.stCd,
// stNm: completedPriceDataParams.stNm,
} }
console.log(pbAtts) console.log(pbAtts)
res = await saveContract(paramsCont) res = await saveContract(paramsCont)
if(res.request.status == '200'){ if(res.request.status == '200'){
notyf.primary('등록 되었습니다.') notyf.primary('등록 되었습니다.')
router.push({path: '/app/contractManagement'}) // router.push({path: '/app/contractManagement'})
} }
}catch(e){ }catch(e){
notyf.error(e.message) notyf.error(e.message)
@@ -217,7 +210,7 @@ const saveContOne = async () => {
} }
} }
const pbAtts = ref<iPbAtt[]>([params.contAtts]) const pbAtts = ref<iPbAtt[]>(params.contAtts)
const onFileChange = (e, idx) => { const onFileChange = (e, idx) => {
const file = e.target.files[0] const file = e.target.files[0]
@@ -239,6 +232,28 @@ const onFileChange = (e, idx) => {
reader.readAsDataURL(file) reader.readAsDataURL(file)
} }
function resetForm() {
completedPriceDataParams.prcsNo = ''
completedPriceDataParams.bizNo = ''
completedPriceDataParams.compNm = ''
completedPriceDataParams.title = ''
completedPriceDataParams.regSdat = ''
completedPriceDataParams.regEdat = ''
completedPriceDataParams.contAmt = ''
completedPriceDataParams.reason = ''
selectedCode.value = ''
pbAtts.value = []
// 기타 입력값도 여기에 추가
}
watch(
() => priceSearchCheckBoxStatus.value,
() => {resetForm()}
)
function routerMove() {
router.push({path: '/app/contractManagement'})
}
</script> </script>
<template> <template>
@@ -264,6 +279,7 @@ const onFileChange = (e, idx) => {
<VCodeSelect <VCodeSelect
v-model="selectedCode" v-model="selectedCode"
cd_grp="5" cd_grp="5"
:disabled="!priceSearchCheckBoxStatus"
/></VField> /></VField>
</span> </span>
</td> </td>
@@ -299,7 +315,7 @@ const onFileChange = (e, idx) => {
<VField class="is-flex"> <VField class="is-flex">
<VControl raw subcontrol> <VControl raw subcontrol>
<VCheckbox <VCheckbox
label="가격조사여부" label="예외사유"
color="info" color="info"
v-model="priceSearchCheckBoxStatus" v-model="priceSearchCheckBoxStatus"
/> />
@@ -329,6 +345,7 @@ const onFileChange = (e, idx) => {
v-model="completedPriceDataParams.title" v-model="completedPriceDataParams.title"
class="input custom-text-filter" class="input custom-text-filter"
placeholder="계약명" placeholder="계약명"
:disabled="!priceSearchCheckBoxStatus"
> >
</VControl> </VControl>
</VField> </VField>
@@ -343,6 +360,7 @@ const onFileChange = (e, idx) => {
v-model="completedPriceDataParams.bizNo" v-model="completedPriceDataParams.bizNo"
class="input custom-text-filter" class="input custom-text-filter"
placeholder="사업자번호" placeholder="사업자번호"
:disabled="!priceSearchCheckBoxStatus"
> >
</VControl> </VControl>
</VField> </VField>
@@ -354,6 +372,7 @@ const onFileChange = (e, idx) => {
v-model="completedPriceDataParams.compNm" v-model="completedPriceDataParams.compNm"
class="input custom-text-filter" class="input custom-text-filter"
placeholder="업체명" placeholder="업체명"
:disabled="!priceSearchCheckBoxStatus"
> >
</VControl> </VControl>
</VField> </VField>
@@ -388,6 +407,7 @@ const onFileChange = (e, idx) => {
:value="formatMonthDate(completedPriceDataParams.regSdat)" :value="formatMonthDate(completedPriceDataParams.regSdat)"
class="input custom-text-filter" class="input custom-text-filter"
placeholder="계약체결일" placeholder="계약체결일"
:disabled="!priceSearchCheckBoxStatus"
> >
</VControl> </VControl>
</VField> </VField>
@@ -398,23 +418,7 @@ const onFileChange = (e, idx) => {
> >
</VButton> </VButton>
<VModal </td>
actions="center"
title="계약금액"
>
<template #content>
<VPlaceholderSection
title="Go Premium"
subtitle="Unlock more features and business tools by going premium"
/>
</template>
<template #action>
<VButton color="primary" raised>
등록
</VButton>
</template>
</VModal>
</td>
<td colspan="2"> <td colspan="2">
<VField> <VField>
<VControl> <VControl>
@@ -422,6 +426,7 @@ const onFileChange = (e, idx) => {
v-model="completedPriceDataParams.contAmt" v-model="completedPriceDataParams.contAmt"
class="input custom-text-filter" class="input custom-text-filter"
placeholder="금액" placeholder="금액"
:disabled="!priceSearchCheckBoxStatus"
> >
</VControl> </VControl>
</VField> </VField>
@@ -533,7 +538,7 @@ const onFileChange = (e, idx) => {
</table> </table>
<div class="bottom-button"> <div class="bottom-button">
<VButton @click="saveContOne"> </VButton> <VButton @click="saveContOne"> </VButton>
<VButton> </VButton> <VButton @click="routerMove"> </VButton>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -0,0 +1,435 @@
<script setup lang="ts">
import {getDetailPrcs, updatePrcsNo, putSurveyPrcsNo} from '/src/service/priceApi'
import { type Person } from '/@src/utils/types'
import {formatDatefromString} from "/@src/utils/common/comfunc.ts";
const notyf = useNotyf()
const loading = ref(false)
const router = useRouter()
const props = defineProps<{
prcsNo: iPrcs
}>()
onBeforeMount(async ()=>{
let result;
if(history.state.key === undefined) {
result = await getDetailPrcs(props.prcsNo)
} else {
result = await getDetailPrcs(history.state.key)
}
getDetailList(result)
})
const detailActionsOpen = ref(false)
const apprLine = defineModel<Person[]>()
const generalParams = reactive({
title: "",
content: "",
regSdat: "",
regEdat: "",
prvYn: true,
prvRsn : "",
prvPwd : "",
aiYn: true,
})
const params = reactive({
cateSelect: '',
prcsNo: '', // 키값
stCd:'',//결재상태 코드{ 등록중:0100[회수버튼],
// 회수: 0300, 반려: 0400, 등록 완료: 0200 }
prcsAttsColumn:[ //첨부파일 입력
{ key: 'logiFnm', label: '구분'},
{ key: 'data', label: '데이터'}
],
prcsAtts: [], //첨부파일 데이터
felxColumn: [
{ key: 'gubunNm', label: '구분'},
{ key: 'deptNm', label: '부서' },
{ key: 'sabun', label: '사번' },
{ key: 'name', label: '이름' },
{ key: 'attendNm', label: '비고' },
{ key: 'apprStat', label: '결재상태'},
{ key: 'date', label: '승인일자'},
],
priceData:[],
prcsBizsColumn: [ //견적사 입력
{ key: 'num', label: '구분', width: '10%' },
{ key: 'email', label: '이메일', editable: true, width: '50px' },
{ key: 'bizNo', label: '사업자번호', editable: true, width: '50px'},
],
prcsBizs: [], //견적사 입력 데이터
dtlSpecsColumn: [
{ key: 'num', label: '번호', editable: false },
{ key: 'itemNm', label: '품명', editable: true },
{ key: 'spec', label: '규격', editable: true },
{ key: 'unit', label: '단위', editable: true },
{ key: 'qty', label: '수량', editable: true },
{ key: '', label: '단가(VAT별도)', editable: false },
{ key: '', label: '금액(VAT별도)', editable: false },
],
dtlSpecs: [], //상세 규격 입력 데이터
})
function getDetailList(arg){
params.prcsNo = arg.prcsNo
params.stCd = arg.stCd
params.cateSelect = arg.cateNm
generalParams.title = arg.title
generalParams.content = arg.content
params.prcsBizs = arg.prcsBizs.map(req => ({
bizNo: req.bizNo,
email: req.email,
}))
params.dtlSpecs = arg.dtlSpecs
generalParams.regSdat = formatDatefromString(arg.regSdat)
generalParams.regEdat = formatDatefromString(arg.regEdat)
apprLine.value = arg.apprMst.apprReqs.map(req => ({
gubunNm: req.gubunNm,
deptCd: req.deptCd,
deptNm: req.deptNm,
sabun: req.sabun,
name: req.name,
apprNo: req.apprNo,
apprOrd: req.apprOrd,
apprStat: req.apprStat,
attendNm: req.attendNm
})) //비고 데이터 없음, 승인일자 없음 todo
console.log(" apprLine.value", apprLine.value)
}
const updateState = async () => {
let res = null
try {
loading.value = true
const paramsPrice = {
prcsNo : params.prcsNo
}
res = await updatePrcsNo(paramsPrice.prcsNo)
notyf.dismissAll()
if (res.request.status === 200) {
notyf.primary('회수 되었습니다.')
router.push({path: '/app/priceManagement'})
}
} catch (e) {
notyf.error(e.message)
} finally {
loading.value = false
}
}
const onChangeFinal = async () => {
let res = null
try {
loading.value = true
res = await putSurveyPrcsNo(params.prcsNo)
notyf.dismissAll()
if (res.request.status === 200) {
notyf.primary('가격조사 완료 되었습니다.')
router.push({path: '/app/contractManagement'})
}
} catch (e) {
notyf.error(e.message)
} finally {
loading.value = false
}
}
</script>
<template>
<div class="page-content is-navbar-lg">
<div class="datatable-wrapper">
<div class="table-container">
<table class="table datatable-table is-fullwidth">
<colgroup>
<col style="width: 10%;">
<col style="width: 10%;">
<col style="width: 10%;">
<col style="width: 10%;">
<col style="width: 10%;">
<col style="width: 10%;">
<col style="width: 10%;">
</colgroup>
<tbody>
<tr>
<td>분야</td>
<td colspan="2">
<span class="column is-7">
<input
:readonly=true
v-model="params.cateSelect"
class="input custom-text-filter"
placeholder="제목"
>
</span>
</td>
<td>제목</td>
<td colspan="3">
<div class="column is-fullhd">
<VField class="pr-2">
<VControl>
<input
:readonly=true
v-model="generalParams.title"
class="input custom-text-filter"
placeholder="제목"
>
</VControl>
</VField>
</div>
</td>
</tr>
<tr>
<td>내용</td>
<td colspan="6">
<div class="column is-fullhd">
<VField class="pr-2">
<VControl>
<input
:readonly=true
v-model="generalParams.content"
class="input custom-text-filter"
placeholder="내용"
/>
</VControl>
</VField>
</div>
</td>
</tr>
<tr>
<td>규격입력</td>
<td colspan="2">
<VButton
color='success'
icon="fas"
elevated
@click="detailActionsOpen = true"
>
<span> 상세 규격 등록 완료</span>
</VButton>
<VModal
:open="detailActionsOpen"
actions="center"
title="상세 규격 입력"
size="contract-big"
cancelLabel="닫기"
@close="detailActionsOpen = false"
>
<template #content>
<ComVFlexTable
:key="params.dtlSpecs.length"
:data="params.dtlSpecs"
:columns="params.dtlSpecsColumn"
:separators="true"
:clickable="true"
>
<template #body-cell="{ row, column, index, value }">
<!-- : 특정 컬럼이면 input, 아니면 그냥 출력 -->
<div>
<input
:readonly=true
v-if="column.editable"
v-model="row[column.key]"
class="editable-input"
/>
<span v-else-if="column.key=='num'">{{index+1}}</span>
<span v-else>{{ value }}</span>
</div>
</template>
</ComVFlexTable>
</template>
<template #cancel>
</template>
</VModal>
</td>
<td>등록기간</td>
<td colspan="5">
<div class="columns">
<div class="column is-5">
<!-- <VDatePicker-->
<!-- v-model="generalParams.regSdat"-->
<!-- color="green"-->
<!-- disabled-->
<!-- trim-weeks-->
<!-- style="pointer-events: none;"-->
<!-- >-->
<!-- <template #default="{ inputValue, inputEvents }">-->
<!-- <VField>-->
<!-- <VControl icon="lucide:calendar">-->
<!-- <input-->
<!-- :readonly=true-->
<!-- class="input v-input"-->
<!-- type="text"-->
<!-- :value="inputValue"-->
<!-- v-on="inputEvents"-->
<!-- placeholder="시작일"-->
<!-- >-->
<!-- </VControl>-->
<!-- </VField>-->
<!-- </template>-->
<!-- </VDatePicker>-->
<input
:readonly=true
v-model="generalParams.regSdat"
class="input custom-text-filter"
placeholder="제목"
>
</div>
<div style="transform: translateY(15px)">~</div>
<div class="column is-5">
<!-- <VDatePicker-->
<!-- v-model="generalParams.regEdat"-->
<!-- color="green"-->
<!-- trim-weeks-->
<!-- disabledDates=""-->
<!-- >-->
<!-- <template #default="{ inputValue, inputEvents }">-->
<!-- <VField>-->
<!-- <VControl icon="lucide:calendar">-->
<!-- <input-->
<!-- :readonly=true-->
<!-- class="input v-input"-->
<!-- type="text"-->
<!-- :value="inputValue"-->
<!-- v-on="inputEvents"-->
<!-- placeholder="종료일"-->
<!-- >-->
<!-- </VControl>-->
<!-- </VField>-->
<!-- </template>-->
<!-- </VDatePicker>-->
<input
:readonly=true
v-model="generalParams.regEdat"
class="input custom-text-filter"
placeholder="제목"
>
</div>
</div>
</td>
</tr>
<tr>
<td>첨부파일</td>
<td colspan="3">
<VField class="file has-name is-right">
<div class="file-label">
<input
class="file-input"
type="file"
name="resume">
<span class="file-cta">
<span class="file-icon">
<i class="fas fa-cloud-upload-alt"/>
</span>
<span class="file-label">첨부파일</span>
</span>
<span class="file-name light-text">2022.xls</span>
</div>
</VField>
</td>
</tr>
<tr>
<td>견적요청</td>
<td colspan="6">
<div style="display: flex; justify-content: flex-end; gap: 8px;">
<!-- <VButton-->
<!-- color="primary"-->
<!-- icon="fas"-->
<!-- elevated-->
<!-- @click="showTable = !showTable"-->
<!-- >-->
<!-- 견적사 확인-->
<!-- </VButton>-->
<VButton
color="primary"
icon="fas fa-circle"
elevated
@click="onChangeFinal"
>
가격조사 완료
</VButton>
</div>
<div class="mt-2">
<ComVFlexTable
:key="params.prcsBizs.length"
:data="params.prcsBizs"
:columns="params.prcsBizsColumn"
:compact="true"
:separators="true"
:clickable="true"
>
<template #body-cell="{ column, index, value }">
<div>
<span v-if="column.key=='num'">{{index + 1}}</span>
<!-- readonly 출력 -->
<span v-else>{{ value }}</span>
</div>
</template>
</ComVFlexTable>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="column is-12">
<VField class="pr-2">
<VLabel class="has-fullwidth">
결재선
</VLabel>
</VField>
<ComVFlexTable
:data="apprLine"
:columns="params.felxColumn"
:separators="true"
:clickable="true"
:compact="true">
<template #body-cell="{ row, column, index, value }">
<!-- : 특정 컬럼이면 input, 아니면 그냥 출력 -->
<div>
<span v-if="column.key=='attendNm' && !value">{{'재중'}}</span>
<span v-else>{{value}}</span>
</div>
</template>
</ComVFlexTable>
</div>
<div>
<VButton
v-if="params.stCd === '0100'"
color="warning"
@click.stop="updateState"
>
회수
</VButton>
<VButton
to="/app/priceManagement"
v-if="params.stCd === '0100' || '0200' || '0300' || '0400'"
color="info"
>
닫기
</VButton>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
.table tbody td {
color: var(--smoke-white);
}
.datatable-table {
padding: 12px 12px;
td:nth-child(1) {
background-color: var(--primary);
}
td:nth-child(3) {
background-color: var(--primary);
}
}
</style>

View File

@@ -43,7 +43,7 @@ const params = reactive({
}) })
function formatRegDt(value) { function formatRegDt(value) {
return value ? value.toString().replace(/[^0-9]/g, '').replace(/\B(?=(\d{3})+(?!\d))/g, ',') : '' return value ? value.substring(0, 16) : ''
} }
async function getIntegratedPaymentList() { async function getIntegratedPaymentList() {