|
|
@@ -156,38 +156,27 @@
|
|
|
</v-btn>
|
|
|
</div>
|
|
|
<div class="table--content">
|
|
|
- <v-data-table
|
|
|
- :headers="tableHeaders"
|
|
|
- :items="recentOrders"
|
|
|
- :loading="loading"
|
|
|
- class="elevation-1"
|
|
|
- items-per-page="10"
|
|
|
- >
|
|
|
- <template v-slot:item.amount="{ item }">
|
|
|
- {{ formatCurrency(item.amount) }}
|
|
|
- </template>
|
|
|
- <template v-slot:item.deliveryCompany="{ item }">
|
|
|
- {{ item.deliveryInfo?.company || '-' }}
|
|
|
- </template>
|
|
|
- <template v-slot:item.trackingNumber="{ item }">
|
|
|
- {{ item.deliveryInfo?.number || '-' }}
|
|
|
- </template>
|
|
|
- <template v-slot:item.status="{ item }">
|
|
|
- <v-chip
|
|
|
- :color="getStatusColor(item.status)"
|
|
|
- size="small"
|
|
|
+ <div class="tbl-wrapper">
|
|
|
+ <div class="tbl-wrap">
|
|
|
+ <!-- ag grid -->
|
|
|
+ <ag-grid-vue
|
|
|
+ style="width: 100%; height: calc(10 * 2.94rem)"
|
|
|
+ class="ag-theme-quartz"
|
|
|
+ :gridOptions="gridOptions"
|
|
|
+ :rowData="recentOrders"
|
|
|
+ :rowSelection="'single'"
|
|
|
+ :paginationPageSize="10"
|
|
|
+ :suppressPaginationPanel="true"
|
|
|
+ @grid-ready="onGridReady"
|
|
|
+ @selection-changed="onSelectionChanged"
|
|
|
>
|
|
|
- {{ getStatusText(item.status) }}
|
|
|
- </v-chip>
|
|
|
- </template>
|
|
|
- <template v-slot:item.actions="{ item }">
|
|
|
- <v-btn
|
|
|
- icon="mdi-eye"
|
|
|
- size="small"
|
|
|
- @click="viewOrder(item)"
|
|
|
- ></v-btn>
|
|
|
- </template>
|
|
|
- </v-data-table>
|
|
|
+ </ag-grid-vue>
|
|
|
+ <!-- 페이징 -->
|
|
|
+ <div class="ag-grid-custom-pagenations">
|
|
|
+ <pagination @chg_page="chgPage" :pageObj="pageObj"></pagination>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -196,6 +185,8 @@
|
|
|
<script setup>
|
|
|
import VueDatePicker from "@vuepic/vue-datepicker";
|
|
|
import "@vuepic/vue-datepicker/dist/main.css";
|
|
|
+ import { AgGridVue } from "ag-grid-vue3";
|
|
|
+ import pagination from "../../../components/common/pagination.vue";
|
|
|
import {
|
|
|
Chart as ChartJS,
|
|
|
CategoryScale,
|
|
|
@@ -291,18 +282,119 @@
|
|
|
avgOrderValue: 0
|
|
|
});
|
|
|
|
|
|
- // 테이블 관련
|
|
|
- const tableHeaders = ref([
|
|
|
- { title: '주문번호', key: 'orderNo', sortable: true },
|
|
|
- { title: '인플루언서', key: 'influencer', sortable: true },
|
|
|
- { title: '상품명', key: 'productName', sortable: false },
|
|
|
- { title: '주문금액', key: 'amount', sortable: true },
|
|
|
- { title: '배송업체', key: 'deliveryCompany', sortable: false },
|
|
|
- { title: '송장번호', key: 'trackingNumber', sortable: false },
|
|
|
- { title: '주문일', key: 'orderDate', sortable: true },
|
|
|
- { title: '상태', key: 'status', sortable: true },
|
|
|
- { title: '액션', key: 'actions', sortable: false }
|
|
|
- ]);
|
|
|
+ // ag-grid 관련
|
|
|
+ const gridApi = ref(null);
|
|
|
+ const gridOptions = ref({
|
|
|
+ columnDefs: [
|
|
|
+ {
|
|
|
+ headerName: '주문번호',
|
|
|
+ field: 'orderNo',
|
|
|
+ flex: 1,
|
|
|
+ minWidth: 140,
|
|
|
+ sortable: true,
|
|
|
+ filter: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ headerName: '인플루언서',
|
|
|
+ field: 'influencer',
|
|
|
+ flex: 1,
|
|
|
+ minWidth: 120,
|
|
|
+ sortable: true,
|
|
|
+ filter: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ headerName: '상품명',
|
|
|
+ field: 'productName',
|
|
|
+ flex: 2,
|
|
|
+ minWidth: 200,
|
|
|
+ sortable: false,
|
|
|
+ filter: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ headerName: '주문금액',
|
|
|
+ field: 'amount',
|
|
|
+ flex: 1,
|
|
|
+ minWidth: 120,
|
|
|
+ sortable: true,
|
|
|
+ filter: true,
|
|
|
+ valueFormatter: (params) => {
|
|
|
+ return new Intl.NumberFormat('ko-KR', {
|
|
|
+ style: 'currency',
|
|
|
+ currency: 'KRW'
|
|
|
+ }).format(params.value || 0);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ headerName: '배송업체',
|
|
|
+ field: 'deliveryCompany',
|
|
|
+ flex: 1,
|
|
|
+ minWidth: 120,
|
|
|
+ sortable: false,
|
|
|
+ filter: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ headerName: '송장번호',
|
|
|
+ field: 'trackingNumber',
|
|
|
+ flex: 1,
|
|
|
+ minWidth: 140,
|
|
|
+ sortable: false,
|
|
|
+ filter: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ headerName: '주문일',
|
|
|
+ field: 'orderDate',
|
|
|
+ flex: 1,
|
|
|
+ minWidth: 120,
|
|
|
+ sortable: true,
|
|
|
+ filter: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ headerName: '상태',
|
|
|
+ field: 'status',
|
|
|
+ flex: 0.8,
|
|
|
+ minWidth: 100,
|
|
|
+ sortable: true,
|
|
|
+ filter: true,
|
|
|
+ cellRenderer: (params) => {
|
|
|
+ const status = params.value;
|
|
|
+ const color = getStatusColor(status);
|
|
|
+ const text = getStatusText(status);
|
|
|
+ return `<span class="status-chip status-${color}">${text}</span>`;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ headerName: '액션',
|
|
|
+ field: 'actions',
|
|
|
+ flex: 0.6,
|
|
|
+ minWidth: 80,
|
|
|
+ sortable: false,
|
|
|
+ filter: false,
|
|
|
+ cellRenderer: () => {
|
|
|
+ return '<button class="action-btn">보기</button>';
|
|
|
+ },
|
|
|
+ onCellClicked: (params) => {
|
|
|
+ viewOrder(params.data);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ defaultColDef: {
|
|
|
+ sortable: true,
|
|
|
+ filter: true,
|
|
|
+ resizable: true,
|
|
|
+ },
|
|
|
+ pagination: false,
|
|
|
+ animateRows: true,
|
|
|
+ rowHeight: 40,
|
|
|
+ suppressHorizontalScroll: false,
|
|
|
+ });
|
|
|
+
|
|
|
+ // 페이징 관련
|
|
|
+ const pageObj = ref({
|
|
|
+ currentPage: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ totalCnt: 0,
|
|
|
+ totalPage: 0
|
|
|
+ });
|
|
|
|
|
|
const recentOrders = ref([]);
|
|
|
|
|
|
@@ -406,6 +498,29 @@
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+ // ag-grid 이벤트 핸들러
|
|
|
+ const onGridReady = (params) => {
|
|
|
+ gridApi.value = params.api;
|
|
|
+ };
|
|
|
+
|
|
|
+ const onSelectionChanged = () => {
|
|
|
+ const selectedRows = gridApi.value.getSelectedRows();
|
|
|
+ console.log('선택된 행:', selectedRows);
|
|
|
+ };
|
|
|
+
|
|
|
+ // 페이지 변경
|
|
|
+ const chgPage = (page) => {
|
|
|
+ pageObj.value.currentPage = page;
|
|
|
+ // 페이징 처리 로직 (현재는 클라이언트 사이드)
|
|
|
+ const startIndex = (page - 1) * pageObj.value.pageSize;
|
|
|
+ const endIndex = startIndex + pageObj.value.pageSize;
|
|
|
+ const paginatedData = recentOrders.value.slice(startIndex, endIndex);
|
|
|
+
|
|
|
+ if (gridApi.value) {
|
|
|
+ gridApi.value.setGridOption('rowData', paginatedData);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
// 주문 상세 보기
|
|
|
const viewOrder = (order) => {
|
|
|
router.push({
|
|
|
@@ -705,8 +820,8 @@
|
|
|
return dateB - dateA;
|
|
|
});
|
|
|
|
|
|
- // 테이블 형식으로 변환 (최근 20개만)
|
|
|
- recentOrders.value = allOrders.slice(0, 20).map((order, index) => ({
|
|
|
+ // 테이블 형식으로 변환
|
|
|
+ const formattedOrders = allOrders.map((order, index) => ({
|
|
|
orderNo: `ORD-${order.SEQ || (Date.now() + index)}`,
|
|
|
influencer: order.NICK_NAME || '알 수 없음',
|
|
|
productName: order.ITEM_NAME || '상품명 없음',
|
|
|
@@ -722,6 +837,18 @@
|
|
|
originalData: order
|
|
|
}));
|
|
|
|
|
|
+ recentOrders.value = formattedOrders;
|
|
|
+
|
|
|
+ // 페이징 정보 업데이트
|
|
|
+ pageObj.value.totalCnt = formattedOrders.length;
|
|
|
+ pageObj.value.totalPage = Math.ceil(formattedOrders.length / pageObj.value.pageSize);
|
|
|
+
|
|
|
+ // ag-grid 데이터 갱신 (첫 페이지만)
|
|
|
+ const firstPageData = formattedOrders.slice(0, pageObj.value.pageSize);
|
|
|
+ if (gridApi.value) {
|
|
|
+ gridApi.value.setGridOption('rowData', firstPageData);
|
|
|
+ }
|
|
|
+
|
|
|
} catch (error) {
|
|
|
console.error('최근 주문 데이터 조회 실패:', error);
|
|
|
$toast.error('최근 주문 데이터를 불러오는데 실패했습니다.');
|
|
|
@@ -966,6 +1093,53 @@
|
|
|
margin: 0;
|
|
|
}
|
|
|
|
|
|
+/* ag-grid 스타일 */
|
|
|
+.status-chip {
|
|
|
+ padding: 4px 8px;
|
|
|
+ border-radius: 4px;
|
|
|
+ font-size: 12px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: white;
|
|
|
+}
|
|
|
+
|
|
|
+.status-success {
|
|
|
+ background-color: #4caf50;
|
|
|
+}
|
|
|
+
|
|
|
+.status-primary {
|
|
|
+ background-color: #2196f3;
|
|
|
+}
|
|
|
+
|
|
|
+.status-info {
|
|
|
+ background-color: #00bcd4;
|
|
|
+}
|
|
|
+
|
|
|
+.status-warning {
|
|
|
+ background-color: #ff9800;
|
|
|
+}
|
|
|
+
|
|
|
+.status-error {
|
|
|
+ background-color: #f44336;
|
|
|
+}
|
|
|
+
|
|
|
+.status-grey {
|
|
|
+ background-color: #9e9e9e;
|
|
|
+}
|
|
|
+
|
|
|
+.action-btn {
|
|
|
+ background: #3f51b5;
|
|
|
+ color: white;
|
|
|
+ border: none;
|
|
|
+ padding: 4px 8px;
|
|
|
+ border-radius: 4px;
|
|
|
+ cursor: pointer;
|
|
|
+ font-size: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.action-btn:hover {
|
|
|
+ background: #303f9f;
|
|
|
+}
|
|
|
+
|
|
|
/* 반응형 */
|
|
|
@media (max-width: 768px) {
|
|
|
.filter--wrap {
|