|
@@ -37,6 +37,19 @@
|
|
|
<div class="left--sections">
|
|
<div class="left--sections">
|
|
|
</div>
|
|
</div>
|
|
|
<div class="right--sections">
|
|
<div class="right--sections">
|
|
|
|
|
+ <div class="caption--wrap">
|
|
|
|
|
+ <i class="ico">!</i>
|
|
|
|
|
+ <div class="caption--box">
|
|
|
|
|
+ - 주문일은 YYYY.MM.DD 혹은 YYYY-MM-DD 형태로 입력해 주세요.<br>
|
|
|
|
|
+ - 구매자 정보 입력 후 저장 버튼을 꼭 클릭해 주세요.
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <v-btn class="custom-btn btn-white mini" @click="addEmptyRow"
|
|
|
|
|
+ ><i class="ico"></i>항목 추가</v-btn
|
|
|
|
|
+ >
|
|
|
|
|
+ <v-btn class="custom-btn btn-white mini" @click="deleteSelectedRows"
|
|
|
|
|
+ ><i class="ico"></i>항목 삭제</v-btn
|
|
|
|
|
+ >
|
|
|
<input
|
|
<input
|
|
|
ref="excelFileInput"
|
|
ref="excelFileInput"
|
|
|
type="file"
|
|
type="file"
|
|
@@ -47,7 +60,7 @@
|
|
|
<v-btn class="custom-btn btn-excel" @click="$refs.excelFileInput.click()"
|
|
<v-btn class="custom-btn btn-excel" @click="$refs.excelFileInput.click()"
|
|
|
><i class="ico"></i>엑셀 업로드</v-btn
|
|
><i class="ico"></i>엑셀 업로드</v-btn
|
|
|
>
|
|
>
|
|
|
- <v-btn class="custom-btn btn-excel"
|
|
|
|
|
|
|
+ <v-btn class="custom-btn btn-excel" @click="downloadExcel"
|
|
|
><i class="ico"></i>엑셀 다운로드</v-btn
|
|
><i class="ico"></i>엑셀 다운로드</v-btn
|
|
|
>
|
|
>
|
|
|
</div>
|
|
</div>
|
|
@@ -59,12 +72,11 @@
|
|
|
style="width: 100%; height: calc(10 * 2.94rem)"
|
|
style="width: 100%; height: calc(10 * 2.94rem)"
|
|
|
class="ag-theme-quartz"
|
|
class="ag-theme-quartz"
|
|
|
:gridOptions="gridOptions"
|
|
:gridOptions="gridOptions"
|
|
|
- :rowData="tblItems"
|
|
|
|
|
rowSelection="multiple"
|
|
rowSelection="multiple"
|
|
|
|
|
+ :rowData="tblItems"
|
|
|
:paginationPageSize="pageObj.pageSize"
|
|
:paginationPageSize="pageObj.pageSize"
|
|
|
:suppressPaginationPanel="true"
|
|
:suppressPaginationPanel="true"
|
|
|
@grid-ready="onGridReady"
|
|
@grid-ready="onGridReady"
|
|
|
- @rowClicked="detailLocated"
|
|
|
|
|
>
|
|
>
|
|
|
</ag-grid-vue>
|
|
</ag-grid-vue>
|
|
|
|
|
|
|
@@ -81,7 +93,7 @@
|
|
|
>
|
|
>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="btn-r">
|
|
<div class="btn-r">
|
|
|
- <v-btn v-if="pageType !== 'D'" class="custom-btn btn-blue2" @click="fnBtnEvt"
|
|
|
|
|
|
|
+ <v-btn class="custom-btn btn-blue2" @click="fnRegEvt"
|
|
|
><i class="ico"></i>저장</v-btn
|
|
><i class="ico"></i>저장</v-btn
|
|
|
>
|
|
>
|
|
|
</div>
|
|
</div>
|
|
@@ -162,7 +174,7 @@ import pagination from "../components/common/pagination.vue";
|
|
|
// gridOption
|
|
// gridOption
|
|
|
const gridOptions = {
|
|
const gridOptions = {
|
|
|
columnDefs: [
|
|
columnDefs: [
|
|
|
- //{ checkboxSelection: true, headerCheckboxSelection: true, width: 0 },
|
|
|
|
|
|
|
+ { checkboxSelection: true, headerCheckboxSelection: true, width: 50 },
|
|
|
{
|
|
{
|
|
|
headerName: "No",
|
|
headerName: "No",
|
|
|
valueGetter: (params) => params.api.getDisplayedRowCount() - params.node.rowIndex,
|
|
valueGetter: (params) => params.api.getDisplayedRowCount() - params.node.rowIndex,
|
|
@@ -204,13 +216,13 @@ import pagination from "../components/common/pagination.vue";
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
headerName: "배송업체",
|
|
headerName: "배송업체",
|
|
|
- field: "DELIVERY_COMPANY",
|
|
|
|
|
|
|
+ field: "DELI_COMP",
|
|
|
width: 100,
|
|
width: 100,
|
|
|
editable: true,
|
|
editable: true,
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
headerName: "송장번호",
|
|
headerName: "송장번호",
|
|
|
- field: "TRACKING_NUMBER",
|
|
|
|
|
|
|
+ field: "DELI_NUMB",
|
|
|
editable: true,
|
|
editable: true,
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
@@ -228,12 +240,13 @@ import pagination from "../components/common/pagination.vue";
|
|
|
rowHeight: rowHeightPx,
|
|
rowHeight: rowHeightPx,
|
|
|
pagination: true,
|
|
pagination: true,
|
|
|
suppressPaginationPanel: true, // 하단 default 페이징 컨트롤 숨김
|
|
suppressPaginationPanel: true, // 하단 default 페이징 컨트롤 숨김
|
|
|
- //rowSelection: {
|
|
|
|
|
- // checkboxes: true,
|
|
|
|
|
- // headerCheckbox: true,
|
|
|
|
|
- // enableClickSelection: false,
|
|
|
|
|
- // mode: "multiRow",
|
|
|
|
|
- //},
|
|
|
|
|
|
|
+ rowMultiSelectWithClick: true,
|
|
|
|
|
+ rowSelection: {
|
|
|
|
|
+ checkboxes: true,
|
|
|
|
|
+ headerCheckbox: true,
|
|
|
|
|
+ enableClickSelection: false,
|
|
|
|
|
+ mode: "multiRow",
|
|
|
|
|
+ },
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
/************************************************************************
|
|
/************************************************************************
|
|
@@ -253,25 +266,6 @@ import pagination from "../components/common/pagination.vue";
|
|
|
gridApi.value.paginationGoToPage(__PAGE - 1);
|
|
gridApi.value.paginationGoToPage(__PAGE - 1);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-
|
|
|
|
|
-const fnBtnEvt = () => {
|
|
|
|
|
- if (!tblItems.value || tblItems.value.length === 0) {
|
|
|
|
|
- let param = {
|
|
|
|
|
- id: pageId,
|
|
|
|
|
- title: pageId,
|
|
|
|
|
- content: "저장할 배송 데이터가 없습니다.",
|
|
|
|
|
- yes: {
|
|
|
|
|
- text: "확인",
|
|
|
|
|
- isProc: false,
|
|
|
|
|
- }
|
|
|
|
|
- };
|
|
|
|
|
- $eventBus.emit("OPEN_CONFIRM_POP_UP", param);
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- fnRegEvt();
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
const fnRegEvt = () => {
|
|
const fnRegEvt = () => {
|
|
|
let param = {
|
|
let param = {
|
|
|
id: pageId,
|
|
id: pageId,
|
|
@@ -298,11 +292,87 @@ const fnBtnEvt = () => {
|
|
|
'이메일': 'EMAIL',
|
|
'이메일': 'EMAIL',
|
|
|
'구매수량': 'QTY',
|
|
'구매수량': 'QTY',
|
|
|
'총구매금액': 'TOTAL',
|
|
'총구매금액': 'TOTAL',
|
|
|
- '배송업체': 'DELIVERY_COMPANY',
|
|
|
|
|
- '송장번호': 'TRACKING_NUMBER',
|
|
|
|
|
|
|
+ '배송업체': 'DELI_COMP',
|
|
|
|
|
+ '송장번호': 'DELI_NUMB',
|
|
|
'주문일': 'ORDER_DATE'
|
|
'주문일': 'ORDER_DATE'
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ const addEmptyRow = () => {
|
|
|
|
|
+ const newRow = {
|
|
|
|
|
+ BUYER_NAME: "",
|
|
|
|
|
+ ADDRESS: "",
|
|
|
|
|
+ PHONE: "",
|
|
|
|
|
+ EMAIL: "",
|
|
|
|
|
+ QTY: "",
|
|
|
|
|
+ TOTAL: "",
|
|
|
|
|
+ DELI_COMP: "",
|
|
|
|
|
+ DELI_NUMB: "",
|
|
|
|
|
+ ORDER_DATE: ""
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 맨 앞에 추가 (unshift 사용)
|
|
|
|
|
+ tblItems.value.unshift(newRow);
|
|
|
|
|
+ pageObj.value.totalCnt = tblItems.value.length;
|
|
|
|
|
+
|
|
|
|
|
+ // ag-grid 데이터 갱신
|
|
|
|
|
+ if (gridApi.value) {
|
|
|
|
|
+ gridApi.value.setGridOption('rowData', tblItems.value);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $toast.success('새 항목이 추가되었습니다.');
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const deleteSelectedRows = () => {
|
|
|
|
|
+ if (!gridApi.value) return;
|
|
|
|
|
+
|
|
|
|
|
+ const selectedRows = gridApi.value.getSelectedRows();
|
|
|
|
|
+ if (selectedRows.length === 0) {
|
|
|
|
|
+ $toast.warning('삭제할 항목을 선택해주세요.');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let param = {
|
|
|
|
|
+ id: pageId,
|
|
|
|
|
+ title: pageId,
|
|
|
|
|
+ content: `선택된 ${selectedRows.length}개 항목을 삭제하시겠습니까?`,
|
|
|
|
|
+ yes: {
|
|
|
|
|
+ text: "삭제",
|
|
|
|
|
+ isProc: true,
|
|
|
|
|
+ event: "FN_DELETE_SELECTED",
|
|
|
|
|
+ param: selectedRows,
|
|
|
|
|
+ },
|
|
|
|
|
+ no: {
|
|
|
|
|
+ text: "취소",
|
|
|
|
|
+ isProc: false,
|
|
|
|
|
+ },
|
|
|
|
|
+ };
|
|
|
|
|
+ $eventBus.emit("OPEN_CONFIRM_POP_UP", param);
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const fnDeleteSelected = (selectedRows) => {
|
|
|
|
|
+ // 선택된 행들을 tblItems에서 제거
|
|
|
|
|
+ selectedRows.forEach(selectedRow => {
|
|
|
|
|
+ const index = tblItems.value.findIndex(item =>
|
|
|
|
|
+ item.BUYER_NAME === selectedRow.BUYER_NAME &&
|
|
|
|
|
+ item.ADDRESS === selectedRow.ADDRESS &&
|
|
|
|
|
+ item.PHONE === selectedRow.PHONE &&
|
|
|
|
|
+ item.EMAIL === selectedRow.EMAIL
|
|
|
|
|
+ );
|
|
|
|
|
+ if (index > -1) {
|
|
|
|
|
+ tblItems.value.splice(index, 1);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ pageObj.value.totalCnt = tblItems.value.length;
|
|
|
|
|
+
|
|
|
|
|
+ // ag-grid 데이터 갱신
|
|
|
|
|
+ if (gridApi.value) {
|
|
|
|
|
+ gridApi.value.setGridOption('rowData', tblItems.value);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $toast.success(`${selectedRows.length}개 항목이 삭제되었습니다.`);
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
const handleExcelUpload = (event) => {
|
|
const handleExcelUpload = (event) => {
|
|
|
const file = event.target.files[0];
|
|
const file = event.target.files[0];
|
|
|
if (!file) return;
|
|
if (!file) return;
|
|
@@ -343,10 +413,14 @@ const fnBtnEvt = () => {
|
|
|
|
|
|
|
|
// ag-grid에 데이터 추가
|
|
// ag-grid에 데이터 추가
|
|
|
// 기존 데이터는 지우고 추가
|
|
// 기존 데이터는 지우고 추가
|
|
|
- tblItems.value = [];
|
|
|
|
|
- tblItems.value = [...tblItems.value, ...mappedData];
|
|
|
|
|
|
|
+ tblItems.value = [...mappedData];
|
|
|
pageObj.value.totalCnt = tblItems.value.length;
|
|
pageObj.value.totalCnt = tblItems.value.length;
|
|
|
|
|
|
|
|
|
|
+ // ag-grid 데이터 갱신
|
|
|
|
|
+ if (gridApi.value) {
|
|
|
|
|
+ gridApi.value.setGridOption('rowData', tblItems.value);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
$toast.success(`${mappedData.length}건의 데이터가 추가되었습니다.`);
|
|
$toast.success(`${mappedData.length}건의 데이터가 추가되었습니다.`);
|
|
|
|
|
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
@@ -360,10 +434,63 @@ const fnBtnEvt = () => {
|
|
|
event.target.value = '';
|
|
event.target.value = '';
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ const downloadExcel = () => {
|
|
|
|
|
+ if (!tblItems.value || tblItems.value.length === 0) {
|
|
|
|
|
+ $toast.warning('다운로드할 데이터가 없습니다.');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 한글 헤더명 배열
|
|
|
|
|
+ const headers = [
|
|
|
|
|
+ '구매자명', '주소', '연락처', '이메일', '구매수량',
|
|
|
|
|
+ '총구매금액', '배송업체', '송장번호', '주문일'
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ // 데이터를 엑셀 형식으로 변환
|
|
|
|
|
+ const excelData = tblItems.value.map(item => [
|
|
|
|
|
+ item.BUYER_NAME || '',
|
|
|
|
|
+ item.ADDRESS || '',
|
|
|
|
|
+ item.PHONE || '',
|
|
|
|
|
+ item.EMAIL || '',
|
|
|
|
|
+ item.QTY || '',
|
|
|
|
|
+ item.TOTAL || '',
|
|
|
|
|
+ item.DELI_COMP || '',
|
|
|
|
|
+ item.DELI_NUMB || '',
|
|
|
|
|
+ item.ORDER_DATE || ''
|
|
|
|
|
+ ]);
|
|
|
|
|
+
|
|
|
|
|
+ // 헤더를 첫 번째 행에 추가
|
|
|
|
|
+ const worksheetData = [headers, ...excelData];
|
|
|
|
|
+
|
|
|
|
|
+ // 워크시트 생성
|
|
|
|
|
+ const worksheet = XLSX.utils.aoa_to_sheet(worksheetData);
|
|
|
|
|
+
|
|
|
|
|
+ // 워크북 생성
|
|
|
|
|
+ const workbook = XLSX.utils.book_new();
|
|
|
|
|
+ XLSX.utils.book_append_sheet(workbook, worksheet, '배송관리');
|
|
|
|
|
+
|
|
|
|
|
+ // 파일명 생성 (현재 날짜 포함)
|
|
|
|
|
+ const today = new Date();
|
|
|
|
|
+ const dateString = today.getFullYear() +
|
|
|
|
|
+ String(today.getMonth() + 1).padStart(2, '0') +
|
|
|
|
|
+ String(today.getDate()).padStart(2, '0');
|
|
|
|
|
+ const fileName = `배송관리_${dateString}.xlsx`;
|
|
|
|
|
+
|
|
|
|
|
+ // 엑셀 파일 다운로드
|
|
|
|
|
+ XLSX.writeFile(workbook, fileName);
|
|
|
|
|
+
|
|
|
|
|
+ $toast.success('엑셀 파일이 다운로드되었습니다.');
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
const fnDetail = () => {
|
|
const fnDetail = () => {
|
|
|
let req = {
|
|
let req = {
|
|
|
seq: useDtStore.boardInfo.seq,
|
|
seq: useDtStore.boardInfo.seq,
|
|
|
};
|
|
};
|
|
|
|
|
+ let req2 = {
|
|
|
|
|
+ item_seq: useDtStore.boardInfo.seq,
|
|
|
|
|
+ //인플루언서일 경우 본인의 inf_seq값 보내줘야함
|
|
|
|
|
+ //inf_seq: 8,
|
|
|
|
|
+ }
|
|
|
useAxios()
|
|
useAxios()
|
|
|
.get(`/item/detail/${req.seq}`)
|
|
.get(`/item/detail/${req.seq}`)
|
|
|
.then((res) => {
|
|
.then((res) => {
|
|
@@ -382,7 +509,19 @@ const fnBtnEvt = () => {
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
.catch((error) => {
|
|
.catch((error) => {
|
|
|
- console.error('제품 상세 조회 오류:', error);
|
|
|
|
|
|
|
+ $toast.error('제품 정보를 불러오는 중 오류가 발생했습니다.');
|
|
|
|
|
+ })
|
|
|
|
|
+ .finally(() => {
|
|
|
|
|
+ });
|
|
|
|
|
+ // 기 저장된 구매자명 리스트
|
|
|
|
|
+ // 제품 seq, 인플루언서 seq가 일치하는 리스트만
|
|
|
|
|
+ useAxios()
|
|
|
|
|
+ .post(`/deli/list`, req2)
|
|
|
|
|
+ .then((res) => {
|
|
|
|
|
+ tblItems.value = res.data;
|
|
|
|
|
+ pageObj.value.totalCnt = tblItems.value.length;
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch((error) => {
|
|
|
$toast.error('제품 정보를 불러오는 중 오류가 발생했습니다.');
|
|
$toast.error('제품 정보를 불러오는 중 오류가 발생했습니다.');
|
|
|
})
|
|
})
|
|
|
.finally(() => {
|
|
.finally(() => {
|
|
@@ -390,13 +529,10 @@ const fnBtnEvt = () => {
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const fnInsert = () => {
|
|
const fnInsert = () => {
|
|
|
- if (!tblItems.value || tblItems.value.length === 0) {
|
|
|
|
|
- $toast.error('저장할 배송 데이터가 없습니다.');
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
const deliveryData = {
|
|
const deliveryData = {
|
|
|
- itemSeq: useDtStore.boardInfo.seq,
|
|
|
|
|
|
|
+ item_seq: useDtStore.boardInfo.seq,
|
|
|
|
|
+ // 임시 인플루언서 시퀀스
|
|
|
|
|
+ inf_seq: 8,
|
|
|
deliveryList: tblItems.value.map(item => ({
|
|
deliveryList: tblItems.value.map(item => ({
|
|
|
buyerName: item.BUYER_NAME,
|
|
buyerName: item.BUYER_NAME,
|
|
|
address: item.ADDRESS,
|
|
address: item.ADDRESS,
|
|
@@ -404,27 +540,23 @@ const fnBtnEvt = () => {
|
|
|
email: item.EMAIL,
|
|
email: item.EMAIL,
|
|
|
qty: item.QTY,
|
|
qty: item.QTY,
|
|
|
total: item.TOTAL,
|
|
total: item.TOTAL,
|
|
|
- deliveryCompany: item.DELIVERY_COMPANY,
|
|
|
|
|
- trackingNumber: item.TRACKING_NUMBER,
|
|
|
|
|
- orderDate: item.ORDER_DATE
|
|
|
|
|
|
|
+ deliComp: item.DELI_COMP,
|
|
|
|
|
+ deliNumb: item.DELI_NUMB,
|
|
|
|
|
+ orderDate: item.ORDER_DATE.replaceAll(".", "-")
|
|
|
}))
|
|
}))
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
useAxios()
|
|
useAxios()
|
|
|
- .post('/delivery/save', deliveryData)
|
|
|
|
|
|
|
+ .post('/deli/reg', deliveryData)
|
|
|
.then((res) => {
|
|
.then((res) => {
|
|
|
$toast.success('배송 데이터가 성공적으로 저장되었습니다.');
|
|
$toast.success('배송 데이터가 성공적으로 저장되었습니다.');
|
|
|
- // 저장 후 목록으로 이동하거나 데이터 새로고침
|
|
|
|
|
- listLocated();
|
|
|
|
|
|
|
+ location.reload();
|
|
|
})
|
|
})
|
|
|
.catch((error) => {
|
|
.catch((error) => {
|
|
|
- console.error('배송 데이터 저장 오류:', error);
|
|
|
|
|
let errorMessage = '배송 데이터 저장 중 오류가 발생했습니다.';
|
|
let errorMessage = '배송 데이터 저장 중 오류가 발생했습니다.';
|
|
|
-
|
|
|
|
|
if (error.response && error.response.data && error.response.data.message) {
|
|
if (error.response && error.response.data && error.response.data.message) {
|
|
|
errorMessage = error.response.data.message;
|
|
errorMessage = error.response.data.message;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
$toast.error(errorMessage);
|
|
$toast.error(errorMessage);
|
|
|
})
|
|
})
|
|
|
.finally(() => {
|
|
.finally(() => {
|
|
@@ -437,6 +569,11 @@ $eventBus.off("FN_INSERT");
|
|
|
$eventBus.on("FN_INSERT", () => {
|
|
$eventBus.on("FN_INSERT", () => {
|
|
|
fnInsert();
|
|
fnInsert();
|
|
|
});
|
|
});
|
|
|
|
|
+
|
|
|
|
|
+$eventBus.off("FN_DELETE_SELECTED");
|
|
|
|
|
+$eventBus.on("FN_DELETE_SELECTED", (selectedRows) => {
|
|
|
|
|
+ fnDeleteSelected(selectedRows);
|
|
|
|
|
+});
|
|
|
/************************************************************************
|
|
/************************************************************************
|
|
|
| WATCH
|
|
| WATCH
|
|
|
************************************************************************/
|
|
************************************************************************/
|