- 상단 레이아웃을 6/6으로 분할하고 좌측에 현재 `<월> 정산 내역` 라벨 표시 - 총 에이전트 수 표시는 우측 정렬로 유지 - 금액/합계 열 정렬을 text-right → text-center로 통일하여 가독성 향상 - 전역 테이블 셀 가운데 정렬 CSS 추가(th/td) - 클릭 가능한 금액 셀의 UX 유지(cursor: pointer)
243 lines
7.0 KiB
Vue
243 lines
7.0 KiB
Vue
<template>
|
|
<div>
|
|
<v-toolbar dark>
|
|
<v-spacer />
|
|
<v-toolbar-title>에이전트 리스트</v-toolbar-title>
|
|
<v-spacer />
|
|
</v-toolbar>
|
|
|
|
<br>
|
|
|
|
<v-container>
|
|
<v-row>
|
|
<v-col
|
|
cols="6"
|
|
class="text-left"
|
|
>
|
|
<strong>{{ settlementMonthLabel }}</strong>
|
|
</v-col>
|
|
<v-col
|
|
cols="6"
|
|
class="text-right"
|
|
>
|
|
총 에이전트 수: <strong>{{ totalCount | numberFormat }}</strong>
|
|
</v-col>
|
|
</v-row>
|
|
|
|
<v-row>
|
|
<v-col>
|
|
<v-simple-table class="elevation-10">
|
|
<template>
|
|
<thead>
|
|
<tr>
|
|
<th class="text-center">
|
|
에이전트 닉네임
|
|
</th>
|
|
<th class="text-center">
|
|
소속 크리에이터 수
|
|
</th>
|
|
<th class="text-center">
|
|
라이브
|
|
</th>
|
|
<th class="text-center">
|
|
콘텐츠
|
|
</th>
|
|
<th class="text-center">
|
|
커뮤니티
|
|
</th>
|
|
<th class="text-center">
|
|
콘텐츠 후원
|
|
</th>
|
|
<th class="text-center">
|
|
채널 후원
|
|
</th>
|
|
<th class="text-center">
|
|
합계
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr
|
|
v-for="item in agentList"
|
|
:key="item.agentId"
|
|
>
|
|
<td
|
|
class="link"
|
|
@click="goAgentDetail(item)"
|
|
>
|
|
{{ item.agentNickname }}
|
|
</td>
|
|
<td class="text-center">
|
|
{{ item.assignedCreatorCount | numberFormat }}
|
|
</td>
|
|
<td
|
|
class="text-center clickable"
|
|
@click="goSettlement(item, 'live')"
|
|
>
|
|
{{ formatCurrency(item.liveAgentSettlementAmount) }}
|
|
</td>
|
|
<td
|
|
class="text-center clickable"
|
|
@click="goSettlement(item, 'content')"
|
|
>
|
|
{{ formatCurrency(item.contentAgentSettlementAmount) }}
|
|
</td>
|
|
<td
|
|
class="text-center clickable"
|
|
@click="goSettlement(item, 'community')"
|
|
>
|
|
{{ formatCurrency(item.communityAgentSettlementAmount) }}
|
|
</td>
|
|
<td
|
|
class="text-center clickable"
|
|
@click="goSettlement(item, 'content-donation')"
|
|
>
|
|
{{ formatCurrency(item.contentDonationAgentSettlementAmount) }}
|
|
</td>
|
|
<td
|
|
class="text-center clickable"
|
|
@click="goSettlement(item, 'channel-donation')"
|
|
>
|
|
{{ formatCurrency(item.channelDonationAgentSettlementAmount) }}
|
|
</td>
|
|
<td class="text-center">
|
|
{{ formatCurrency(totalAmount(item)) }}
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</template>
|
|
</v-simple-table>
|
|
</v-col>
|
|
</v-row>
|
|
|
|
<!-- 페이지네이션은 서버 지원 시 활성화
|
|
<v-row class="text-center">
|
|
<v-col>
|
|
<v-pagination
|
|
v-model="page"
|
|
:length="total_page"
|
|
circle
|
|
@input="fetchList"
|
|
/>
|
|
</v-col>
|
|
</v-row>
|
|
-->
|
|
</v-container>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { getAgentList } from '@/api/agent'
|
|
|
|
export default {
|
|
name: 'AgentList',
|
|
filters: {
|
|
numberFormat(v) {
|
|
if (v === null || v === undefined) return '-'
|
|
try {
|
|
return new Intl.NumberFormat('ko-KR').format(v)
|
|
} catch (e) {
|
|
return v
|
|
}
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
agentList: [],
|
|
totalCount: 0,
|
|
// 페이지네이션(필요 시)
|
|
page: 1,
|
|
total_page: 1,
|
|
page_size: 20,
|
|
is_loading: false,
|
|
}
|
|
},
|
|
computed: {
|
|
settlementMonthLabel() {
|
|
const now = new Date()
|
|
const month = now.getMonth() + 1 // 1~12
|
|
return `${month}월 정산 내역`
|
|
}
|
|
},
|
|
created() {
|
|
this.fetchList()
|
|
},
|
|
methods: {
|
|
async fetchList() {
|
|
if (this.is_loading) return
|
|
this.is_loading = true
|
|
try {
|
|
const res = await getAgentList(/* this.page, this.page_size */)
|
|
// 일부 API는 { data: { totalCount, items } } 형태로 한 번 더 래핑됨을 대비
|
|
let payload = (res && res.data) ? res.data : null
|
|
if (payload && payload.data && (!payload.items && !payload.totalCount)) {
|
|
payload = payload.data
|
|
}
|
|
const data = payload || { totalCount: 0, items: [] }
|
|
this.totalCount = data.totalCount || 0
|
|
this.agentList = Array.isArray(data.items) ? data.items : []
|
|
// 서버가 페이지네이션 정보를 주면 설정하도록 남김
|
|
this.total_page = Math.max(1, Math.ceil(this.totalCount / this.page_size))
|
|
} catch (e) {
|
|
this.totalCount = 0
|
|
this.agentList = []
|
|
} finally {
|
|
this.is_loading = false
|
|
}
|
|
},
|
|
formatCurrency(n) {
|
|
const num = Number(n || 0)
|
|
return new Intl.NumberFormat('ko-KR', { style: 'currency', currency: 'KRW', maximumFractionDigits: 0 }).format(num)
|
|
},
|
|
totalAmount(item) {
|
|
const {
|
|
liveAgentSettlementAmount = 0,
|
|
contentAgentSettlementAmount = 0,
|
|
communityAgentSettlementAmount = 0,
|
|
contentDonationAgentSettlementAmount = 0,
|
|
channelDonationAgentSettlementAmount = 0,
|
|
} = item || {}
|
|
return (
|
|
(liveAgentSettlementAmount || 0) +
|
|
(contentAgentSettlementAmount || 0) +
|
|
(communityAgentSettlementAmount || 0) +
|
|
(contentDonationAgentSettlementAmount || 0) +
|
|
(channelDonationAgentSettlementAmount || 0)
|
|
)
|
|
},
|
|
goAgentDetail(item) {
|
|
this.$router.push({ name: 'AgentDetail', params: { agentId: item.agentId }, query: { nickname: item.agentNickname } })
|
|
},
|
|
goSettlement(item, type) {
|
|
const id = item.agentId
|
|
const nameMap = {
|
|
'live': 'AgentSettlementLive',
|
|
'content': 'AgentSettlementContent',
|
|
'community': 'AgentSettlementCommunity',
|
|
'content-donation': 'AgentSettlementContentDonation',
|
|
'channel-donation': 'AgentSettlementChannelDonation',
|
|
}
|
|
const name = nameMap[type]
|
|
if (!name) return
|
|
this.$router.push({ name, params: { agentId: id }, query: { nickname: item.agentNickname } })
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.link {
|
|
color: #3f51b5;
|
|
cursor: pointer;
|
|
text-decoration: underline;
|
|
}
|
|
.clickable {
|
|
cursor: pointer;
|
|
}
|
|
/* 테이블 셀 가운데 정렬 */
|
|
table th,
|
|
table td {
|
|
text-align: center !important;
|
|
}
|
|
</style>
|