mirror of
https://git.hmsn.ink/kospo/svcm/oa.git
synced 2026-03-20 07:13:44 +09:00
fix : 파일 업로드, 파일 다운로드 기능 추가 => 가격조사 등록, 가격조사 수정
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { savePrice } from '/src/service/priceApi'
|
import {deletePrcsFile, getPrcsFileDown, savePrice} from '/src/service/priceApi'
|
||||||
import { Person } from '/@src/utils/types'
|
import {type iPbAtt, Person} from '/@src/utils/types'
|
||||||
import {formatBizNum,formatDate} from "/@src/utils/common/comfunc.ts";
|
import {formatBizNum,formatDate} from "/@src/utils/common/comfunc.ts";
|
||||||
|
|
||||||
const notyf = useNotyf()
|
const notyf = useNotyf()
|
||||||
@@ -131,7 +131,7 @@ const savePriceOne = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const pbAtts = ref<iPbAtt[]>(params.prcsAtts)
|
||||||
|
|
||||||
const addNewEstimateRow = () => {
|
const addNewEstimateRow = () => {
|
||||||
const newRow = {}
|
const newRow = {}
|
||||||
@@ -173,8 +173,6 @@ const onDetailDelete = (index: number) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const onPayDelete = (index: number) => {
|
const onPayDelete = (index: number) => {
|
||||||
console.log("params.felxColumn.length",params.felxColumn.length)
|
|
||||||
console.log("params.felxColumn.length",apprLine.value.length)
|
|
||||||
if(apprLine.value.length-1 !== params.felxColumn.length
|
if(apprLine.value.length-1 !== params.felxColumn.length
|
||||||
|| (params.felxColumn.length == 6 && apprLine.value.length-1 == params.felxColumn.length))
|
|| (params.felxColumn.length == 6 && apprLine.value.length-1 == params.felxColumn.length))
|
||||||
{
|
{
|
||||||
@@ -183,19 +181,32 @@ const onPayDelete = (index: number) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const fileInput = ref<HTMLInputElement | null>(null)
|
const onFileClick = () => {
|
||||||
const fileName = ref('')
|
const input = <any> document.querySelector('.file-input')
|
||||||
|
input.click()
|
||||||
function openFileDialog() {
|
|
||||||
fileInput.value?.click()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onFileChange(event: Event) {
|
const onFileChange = (e: any) => {
|
||||||
const target = event.target as HTMLInputElement
|
Array.from(e.target.files).forEach((file: any) => {
|
||||||
if (target.files && target.files.length > 0) {
|
const reader = new FileReader()
|
||||||
fileName.value = target.files[0].name
|
reader.onload = () => {
|
||||||
// 여기서 파일 업로드 로직을 추가할 수 있습니다.
|
const result = <string>reader.result
|
||||||
// 예: emit('file-selected', target.files[0])
|
const pbAtt = <iPbAtt>{
|
||||||
|
logiFnm: file.name,
|
||||||
|
size: file.size,
|
||||||
|
data: result.split(',')[1],
|
||||||
|
}
|
||||||
|
pbAtts.value.push(pbAtt)
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.readAsDataURL(file)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const onFilDelete = async ( index: number, fileOrd: number) => {
|
||||||
|
notyf.dismissAll()
|
||||||
|
if (index) {
|
||||||
|
pbAtts.value.splice(index, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,20 +442,42 @@ function onInput(row, column){
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>첨부파일</td>
|
<td>첨부파일</td>
|
||||||
<td colspan="10">
|
<td colspan="3">
|
||||||
<VField class="file has-name is-left">
|
<VField>
|
||||||
<VButton @click="openFileDialog">
|
<div class="column is-6">
|
||||||
파일 첨부
|
<div class="file has-name is-fullwidth">
|
||||||
</VButton>
|
<input
|
||||||
<input
|
class="file-input hide"
|
||||||
ref="fileInput"
|
type="file"
|
||||||
type="file"
|
multiple
|
||||||
style="display: none"
|
@change="(e) => onFileChange(e)"
|
||||||
@change="onFileChange"
|
>
|
||||||
/>
|
<VLabel>
|
||||||
<span v-if="fileName" class="file-name">{{ fileName }}</span>
|
<VButton icon="fas fa-plus" color="info" class="file-trigger" @click="onFileClick" >
|
||||||
</VField>
|
<span>파일업로드</span>
|
||||||
|
</VButton>
|
||||||
|
</VLabel>
|
||||||
|
<VControl>
|
||||||
|
<div
|
||||||
|
v-for="(f, i) in pbAtts"
|
||||||
|
:key="f.logiFnm"
|
||||||
|
class="content estimate-file-wrapper"
|
||||||
|
>
|
||||||
|
<div class="estimate-file-name">
|
||||||
|
{{ f.logiFnm }}
|
||||||
|
</div>
|
||||||
|
<div class="estimate-file-size">
|
||||||
|
{{ Math.ceil(f.size / 1024) }}kb
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<i class="fa fa-trash estimate-file-delete" @click="onFilDelete( i, f.fileOrd)" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</VControl>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</VField>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {getDetailPrcs, updatePrice} from '/src/service/priceApi'
|
import {getDetailPrcs, updatePrice, getPrcsFileDown, deletePrcsFile} from '/src/service/priceApi'
|
||||||
import { type Person } from '/@src/utils/types'
|
import {type iPbAtt, type Person} from '/@src/utils/types'
|
||||||
import {formatBizNum, formatDate} from "/@src/utils/common/comfunc.ts";
|
import {formatBizNum, formatDate} from "/@src/utils/common/comfunc.ts";
|
||||||
|
|
||||||
const notyf = useNotyf()
|
const notyf = useNotyf()
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -73,7 +72,10 @@ const params = reactive({
|
|||||||
btnChangeFlag: false
|
btnChangeFlag: false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const pbAtts = ref<iPbAtt[]>(params.prcsAtts)
|
||||||
|
|
||||||
function getDetailList(arg){
|
function getDetailList(arg){
|
||||||
|
console.log("arg",arg)
|
||||||
params.prcsNo = arg.prcsNo
|
params.prcsNo = arg.prcsNo
|
||||||
params.stCd = arg.stCd
|
params.stCd = arg.stCd
|
||||||
params.cateSelect = arg.cateCd
|
params.cateSelect = arg.cateCd
|
||||||
@@ -98,6 +100,7 @@ function getDetailList(arg){
|
|||||||
apprDt: req.apprDt,
|
apprDt: req.apprDt,
|
||||||
attendCd: req.attendCd
|
attendCd: req.attendCd
|
||||||
})) //비고 데이터 없음, 승인일자 없음 todo
|
})) //비고 데이터 없음, 승인일자 없음 todo
|
||||||
|
params.prcsAtts = arg.prcsAtts
|
||||||
}
|
}
|
||||||
|
|
||||||
const changeButton = () => {
|
const changeButton = () => {
|
||||||
@@ -138,9 +141,12 @@ const updatePriceOne = async () => {
|
|||||||
prcsBizs: params.prcsBizs.map(({ num, ...rest }) => rest), //견적사 입력 데이터
|
prcsBizs: params.prcsBizs.map(({ num, ...rest }) => rest), //견적사 입력 데이터
|
||||||
dtlSpecs: [], //todo
|
dtlSpecs: [], //todo
|
||||||
// params.dtlSpecs.map(({ num, ...rest }) => rest), //상세 규격 입력 데이터
|
// params.dtlSpecs.map(({ num, ...rest }) => rest), //상세 규격 입력 데이터
|
||||||
prcsAtts: params.prcsAtts, //첨부파일 데이터
|
prcsAtts: pbAtts.value.map(req => ({
|
||||||
|
logiFnm: req.logiFnm,
|
||||||
|
data: req.data})),//첨부파일 데이터,
|
||||||
apprReqs: apprLine.value.map(({ deptNm, ...rest }) => rest), //결재선 데이터
|
apprReqs: apprLine.value.map(({ deptNm, ...rest }) => rest), //결재선 데이터
|
||||||
}
|
}
|
||||||
|
console.log("pbAtts.value",pbAtts.value)
|
||||||
console.log("paramsPrice",paramsPrice)
|
console.log("paramsPrice",paramsPrice)
|
||||||
res = await updatePrice(paramsPrice)
|
res = await updatePrice(paramsPrice)
|
||||||
notyf.dismissAll()
|
notyf.dismissAll()
|
||||||
@@ -193,29 +199,60 @@ const onDetailDelete = (index: number) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileInput = ref<HTMLInputElement | null>(null)
|
|
||||||
const fileName = ref('')
|
|
||||||
|
|
||||||
function openFileDialog() {
|
|
||||||
fileInput.value?.click()
|
|
||||||
}
|
|
||||||
|
|
||||||
function onFileChange(event: Event) {
|
|
||||||
const target = event.target as HTMLInputElement
|
|
||||||
if (target.files && target.files.length > 0) {
|
|
||||||
fileName.value = target.files[0].name
|
|
||||||
// 여기서 파일 업로드 로직을 추가할 수 있습니다.
|
|
||||||
// 예: emit('file-selected', target.files[0])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onInput(row, column){
|
function onInput(row, column){
|
||||||
if (column.key === 'bizNo') {
|
if (column.key === 'bizNo') {
|
||||||
const raw =row[column.key].replace(/\D/g, '')
|
const raw =row[column.key].replace(/\D/g, '')
|
||||||
row[column.key] = formatBizNum(raw) // 실시간 포맷 적용
|
row[column.key] = formatBizNum(raw)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onFileClick = () => {
|
||||||
|
const input = <any> document.querySelector('.file-input')
|
||||||
|
input.click()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onFileChange = (e: any) => {
|
||||||
|
Array.from(e.target.files).forEach((file: any) => {
|
||||||
|
const reader = new FileReader()
|
||||||
|
reader.onload = () => {
|
||||||
|
const result = <string>reader.result
|
||||||
|
const pbAtt = <iPbAtt>{
|
||||||
|
prcsNo: params.prcsNo,
|
||||||
|
logiFnm: file.name,
|
||||||
|
size: file.size,
|
||||||
|
data: result.split(',')[1],
|
||||||
|
}
|
||||||
|
pbAtts.value.push(pbAtt)
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.readAsDataURL(file)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const onFilDelete = async (prcsNo: string, index: number, fileOrd: number) => {
|
||||||
|
notyf.dismissAll()
|
||||||
|
console.log(prcsNo)
|
||||||
|
if (prcsNo === undefined || prcsNo === null) {
|
||||||
|
pbAtts.value.splice(index, 1)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
await deletePrcsFile(params.prcsNo, fileOrd).then((res: string) => {
|
||||||
|
notyf.success(res)
|
||||||
|
pbAtts.value.splice(index, 1)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onPrcsFileDownload = async (prcsNo: string, fileOrd: number, logiFnm: string) => {
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = `https://svcm.hmsn.ink/api/prcs/${prcsNo}/${fileOrd}` //todo
|
||||||
|
link.setAttribute('download', logiFnm)
|
||||||
|
link.setAttribute('target', '_blank')
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -439,20 +476,62 @@ function onInput(row, column){
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>첨부파일</td>
|
<td>첨부파일</td>
|
||||||
<td colspan="3">
|
<td colspan="4">
|
||||||
<VField class="file has-name is-left">
|
<VField>
|
||||||
<VButton @click="openFileDialog">
|
|
||||||
파일 첨부
|
|
||||||
</VButton>
|
|
||||||
<input
|
<input
|
||||||
ref="fileInput"
|
class="file-input hide"
|
||||||
type="file"
|
type="file"
|
||||||
style="display: none"
|
multiple
|
||||||
@change="onFileChange"
|
@change="(e) => onFileChange(e)"
|
||||||
/>
|
>
|
||||||
|
<VLabel>
|
||||||
<span v-if="fileName" class="file-name">{{ fileName }}</span>
|
<VButton icon="fas fa-plus" color="info" class="file-trigger" @click="onFileClick" >
|
||||||
|
<span>파일업로드</span>
|
||||||
|
</VButton>
|
||||||
|
</VLabel>
|
||||||
|
<VControl>
|
||||||
|
<div
|
||||||
|
v-for="(f, i) in pbAtts"
|
||||||
|
:key="f.logiFnm"
|
||||||
|
class="content estimate-file-wrapper"
|
||||||
|
>
|
||||||
|
<div class="estimate-file-name">
|
||||||
|
{{ f.logiFnm }}
|
||||||
|
</div>
|
||||||
|
<div class="estimate-file-size">
|
||||||
|
{{ Math.ceil(f.size / 1024) }}kb
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<i class="fa fa-trash estimate-file-delete" @click="onFilDelete(f.bizNo, i, f.fileOrd)" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</VControl>
|
||||||
</VField>
|
</VField>
|
||||||
|
<div class="column is-12">
|
||||||
|
<VField>
|
||||||
|
<VLabel>첨부파일</VLabel>
|
||||||
|
<VControl>
|
||||||
|
<div
|
||||||
|
v-for="f in params.prcsAtts"
|
||||||
|
:key="f.logiFnm"
|
||||||
|
class="content estimate-file-wrapper"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<i class="fa fa-file-pdf estimate-file-img" style="font-size:40px;" />
|
||||||
|
</div>
|
||||||
|
<div class="estimate-file-name">
|
||||||
|
{{ f.logiFnm }}
|
||||||
|
</div>
|
||||||
|
<div class="estimate-file-size">
|
||||||
|
{{ Math.ceil(f.size / 1024) }}kb
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<i class="fa fa-download estimate-file-download" @click="onPrcsFileDownload(f.prcsNo, f.fileOrd, f.logiFnm)" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</VControl>
|
||||||
|
</VField>
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
@@ -532,5 +611,4 @@ function onInput(row, column){
|
|||||||
background-color: var(--primary);
|
background-color: var(--primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
38
src/scss/vuero-css/_vuerofile.scss
Normal file
38
src/scss/vuero-css/_vuerofile.scss
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
.estimate-file-wrapper {
|
||||||
|
display:flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
border:1px solid #ccc;
|
||||||
|
border-radius:5px;
|
||||||
|
padding:10px 20px;
|
||||||
|
margin-bottom:10px;
|
||||||
|
.estimate-file-download, .estimate-file-delete {
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 40px;
|
||||||
|
padding-left: 30px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.estimate-file-img {
|
||||||
|
font-size: 40px;
|
||||||
|
padding-right: 50px;
|
||||||
|
}
|
||||||
|
.estimate-file-name {
|
||||||
|
width: 400px;
|
||||||
|
line-height: 40px;
|
||||||
|
}
|
||||||
|
.estimate-file-size {
|
||||||
|
width: 200px;
|
||||||
|
line-height: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.estimate-file-download, .estimate-file-delete, .fa-plus-circle {
|
||||||
|
&:hover {
|
||||||
|
color: var(--primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-trigger {
|
||||||
|
margin-left: 10px;
|
||||||
|
height:15px;
|
||||||
|
padding:10px 10px;
|
||||||
|
}
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
@import './vuerosearch';
|
@import './vuerosearch';
|
||||||
@import './vuerotable';
|
@import './vuerotable';
|
||||||
|
@import './vuerofile';
|
||||||
|
|||||||
@@ -70,15 +70,15 @@ export async function getDetailPrcs(params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 가격조사서 다운로드 Todo
|
* 가격조사서 다운로드
|
||||||
* @param {object} params
|
* @param {object} params
|
||||||
* @property {string} params.prcsNo - 가격조사번호
|
* @property {string} params.prcsNo - 가격조사번호
|
||||||
* @property {string} params.fileOrd - 파일순서
|
* @property {string} params.fileOrd - 파일순서
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export async function getPrcsFileDown(params) {
|
export async function getPrcsFileDown(prcsNo, fileOrd) {
|
||||||
try {
|
try {
|
||||||
const result = await axios.get(`/api/prcs/${params}`)
|
const result = await axios.get(`/api/prcs/${prcsNo}/${fileOrd}`)
|
||||||
return result.data
|
return result.data
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error(e)
|
throw new Error(e)
|
||||||
@@ -86,15 +86,15 @@ export async function getPrcsFileDown(params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 가격조사서 첨부파일 삭제 Todo
|
* 가격조사서 첨부파일 삭제
|
||||||
* @param {object} params
|
* @param {object} params
|
||||||
* @property {string} params.prcsNo - 가격조사번호
|
* @property {string} params.prcsNo - 가격조사번호
|
||||||
* @property {string} params.fileOrd - 파일순서
|
* @property {string} params.fileOrd - 파일순서
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export async function deletePrcsFile(params) {
|
export async function deletePrcsFile(prcsNo, fileOrd) {
|
||||||
try {
|
try {
|
||||||
const result = await axios.delete(`/api/prcs/${params}`)
|
const result = await axios.delete(`/api/prcs/${prcsNo}/${fileOrd}`)
|
||||||
return result.data
|
return result.data
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error(e)
|
throw new Error(e)
|
||||||
|
|||||||
Reference in New Issue
Block a user