에이전트 기능 #97
12
src/api/agent.js
Normal file
12
src/api/agent.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import Vue from 'vue'
|
||||
|
||||
// 에이전트 리스트 조회
|
||||
// 서버 스펙에 페이지네이션이 없다면 단순 GET으로 사용
|
||||
// 추후 필요 시 params(page,size) 확장 가능
|
||||
async function getAgentList() {
|
||||
return Vue.axios.get('/admin/partner/agent/list')
|
||||
}
|
||||
|
||||
export {
|
||||
getAgentList
|
||||
}
|
||||
@@ -56,6 +56,42 @@ const routes = [
|
||||
name: 'AgentList',
|
||||
component: () => import(/* webpackChunkName: "agent" */ '../views/Agent/AgentList.vue')
|
||||
},
|
||||
{
|
||||
path: '/agent/:agentId',
|
||||
name: 'AgentDetail',
|
||||
props: true,
|
||||
component: () => import(/* webpackChunkName: "agent" */ '../views/Agent/AgentDetail.vue')
|
||||
},
|
||||
{
|
||||
path: '/agent/:agentId/settlement/live',
|
||||
name: 'AgentSettlementLive',
|
||||
props: true,
|
||||
component: () => import(/* webpackChunkName: "agent" */ '../views/Agent/AgentLiveSettlement.vue')
|
||||
},
|
||||
{
|
||||
path: '/agent/:agentId/settlement/content',
|
||||
name: 'AgentSettlementContent',
|
||||
props: true,
|
||||
component: () => import(/* webpackChunkName: "agent" */ '../views/Agent/AgentContentSettlement.vue')
|
||||
},
|
||||
{
|
||||
path: '/agent/:agentId/settlement/community',
|
||||
name: 'AgentSettlementCommunity',
|
||||
props: true,
|
||||
component: () => import(/* webpackChunkName: "agent" */ '../views/Agent/AgentCommunitySettlement.vue')
|
||||
},
|
||||
{
|
||||
path: '/agent/:agentId/settlement/content-donation',
|
||||
name: 'AgentSettlementContentDonation',
|
||||
props: true,
|
||||
component: () => import(/* webpackChunkName: "agent" */ '../views/Agent/AgentContentDonationSettlement.vue')
|
||||
},
|
||||
{
|
||||
path: '/agent/:agentId/settlement/channel-donation',
|
||||
name: 'AgentSettlementChannelDonation',
|
||||
props: true,
|
||||
component: () => import(/* webpackChunkName: "agent" */ '../views/Agent/AgentChannelDonationSettlement.vue')
|
||||
},
|
||||
{
|
||||
path: '/agent/settlement-ratio',
|
||||
name: 'AgentSettlementRatio',
|
||||
|
||||
37
src/views/Agent/AgentChannelDonationSettlement.vue
Normal file
37
src/views/Agent/AgentChannelDonationSettlement.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-toolbar dark>
|
||||
<v-btn
|
||||
icon
|
||||
@click="$router.back()"
|
||||
>
|
||||
<v-icon>mdi-arrow-left</v-icon>
|
||||
</v-btn>
|
||||
<v-toolbar-title>에이전트 정산 상세 - 채널 후원</v-toolbar-title>
|
||||
<v-spacer />
|
||||
</v-toolbar>
|
||||
<v-container>
|
||||
<v-row>
|
||||
<v-col>
|
||||
<h3>채널 후원 정산 상세 페이지 (준비중)</h3>
|
||||
<p>Agent ID: {{ agentId }}</p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'AgentChannelDonationSettlement',
|
||||
props: {
|
||||
agentId: {
|
||||
type: [String, Number],
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
37
src/views/Agent/AgentCommunitySettlement.vue
Normal file
37
src/views/Agent/AgentCommunitySettlement.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-toolbar dark>
|
||||
<v-btn
|
||||
icon
|
||||
@click="$router.back()"
|
||||
>
|
||||
<v-icon>mdi-arrow-left</v-icon>
|
||||
</v-btn>
|
||||
<v-toolbar-title>에이전트 정산 상세 - 커뮤니티</v-toolbar-title>
|
||||
<v-spacer />
|
||||
</v-toolbar>
|
||||
<v-container>
|
||||
<v-row>
|
||||
<v-col>
|
||||
<h3>커뮤니티 정산 상세 페이지 (준비중)</h3>
|
||||
<p>Agent ID: {{ agentId }}</p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'AgentCommunitySettlement',
|
||||
props: {
|
||||
agentId: {
|
||||
type: [String, Number],
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
37
src/views/Agent/AgentContentDonationSettlement.vue
Normal file
37
src/views/Agent/AgentContentDonationSettlement.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-toolbar dark>
|
||||
<v-btn
|
||||
icon
|
||||
@click="$router.back()"
|
||||
>
|
||||
<v-icon>mdi-arrow-left</v-icon>
|
||||
</v-btn>
|
||||
<v-toolbar-title>에이전트 정산 상세 - 콘텐츠 후원</v-toolbar-title>
|
||||
<v-spacer />
|
||||
</v-toolbar>
|
||||
<v-container>
|
||||
<v-row>
|
||||
<v-col>
|
||||
<h3>콘텐츠 후원 정산 상세 페이지 (준비중)</h3>
|
||||
<p>Agent ID: {{ agentId }}</p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'AgentContentDonationSettlement',
|
||||
props: {
|
||||
agentId: {
|
||||
type: [String, Number],
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
37
src/views/Agent/AgentContentSettlement.vue
Normal file
37
src/views/Agent/AgentContentSettlement.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-toolbar dark>
|
||||
<v-btn
|
||||
icon
|
||||
@click="$router.back()"
|
||||
>
|
||||
<v-icon>mdi-arrow-left</v-icon>
|
||||
</v-btn>
|
||||
<v-toolbar-title>에이전트 정산 상세 - 콘텐츠</v-toolbar-title>
|
||||
<v-spacer />
|
||||
</v-toolbar>
|
||||
<v-container>
|
||||
<v-row>
|
||||
<v-col>
|
||||
<h3>콘텐츠 정산 상세 페이지 (준비중)</h3>
|
||||
<p>Agent ID: {{ agentId }}</p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'AgentContentSettlement',
|
||||
props: {
|
||||
agentId: {
|
||||
type: [String, Number],
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
37
src/views/Agent/AgentDetail.vue
Normal file
37
src/views/Agent/AgentDetail.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-toolbar dark>
|
||||
<v-btn
|
||||
icon
|
||||
@click="$router.back()"
|
||||
>
|
||||
<v-icon>mdi-arrow-left</v-icon>
|
||||
</v-btn>
|
||||
<v-toolbar-title>에이전트 상세</v-toolbar-title>
|
||||
<v-spacer />
|
||||
</v-toolbar>
|
||||
<v-container>
|
||||
<v-row>
|
||||
<v-col>
|
||||
<h3>에이전트 상세 페이지 (준비중)</h3>
|
||||
<p>Agent ID: {{ agentId }}</p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'AgentDetail',
|
||||
props: {
|
||||
agentId: {
|
||||
type: [String, Number],
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
@@ -1,19 +1,224 @@
|
||||
<template>
|
||||
<v-container fluid>
|
||||
<div>
|
||||
<v-toolbar dark>
|
||||
<v-spacer />
|
||||
<v-toolbar-title>에이전트 리스트</v-toolbar-title>
|
||||
<v-spacer />
|
||||
</v-toolbar>
|
||||
|
||||
<br>
|
||||
|
||||
<v-container>
|
||||
<v-row>
|
||||
<v-col cols="12">
|
||||
<h2>에이전트 리스트</h2>
|
||||
<p>에이전트 목록을 관리합니다. (구현 예정)</p>
|
||||
<v-col
|
||||
cols="12"
|
||||
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-right clickable"
|
||||
@click="goSettlement(item, 'live')"
|
||||
>
|
||||
{{ formatCurrency(item.liveAgentSettlementAmount) }}
|
||||
</td>
|
||||
<td
|
||||
class="text-right clickable"
|
||||
@click="goSettlement(item, 'content')"
|
||||
>
|
||||
{{ formatCurrency(item.contentAgentSettlementAmount) }}
|
||||
</td>
|
||||
<td
|
||||
class="text-right clickable"
|
||||
@click="goSettlement(item, 'community')"
|
||||
>
|
||||
{{ formatCurrency(item.communityAgentSettlementAmount) }}
|
||||
</td>
|
||||
<td
|
||||
class="text-right clickable"
|
||||
@click="goSettlement(item, 'content-donation')"
|
||||
>
|
||||
{{ formatCurrency(item.contentDonationAgentSettlementAmount) }}
|
||||
</td>
|
||||
<td
|
||||
class="text-right clickable"
|
||||
@click="goSettlement(item, 'channel-donation')"
|
||||
>
|
||||
{{ formatCurrency(item.channelDonationAgentSettlementAmount) }}
|
||||
</td>
|
||||
<td class="text-right">
|
||||
{{ 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,
|
||||
}
|
||||
},
|
||||
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 } })
|
||||
},
|
||||
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 } })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.link {
|
||||
color: #3f51b5;
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
37
src/views/Agent/AgentLiveSettlement.vue
Normal file
37
src/views/Agent/AgentLiveSettlement.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-toolbar dark>
|
||||
<v-btn
|
||||
icon
|
||||
@click="$router.back()"
|
||||
>
|
||||
<v-icon>mdi-arrow-left</v-icon>
|
||||
</v-btn>
|
||||
<v-toolbar-title>에이전트 정산 상세 - 라이브</v-toolbar-title>
|
||||
<v-spacer />
|
||||
</v-toolbar>
|
||||
<v-container>
|
||||
<v-row>
|
||||
<v-col>
|
||||
<h3>라이브 정산 상세 페이지 (준비중)</h3>
|
||||
<p>Agent ID: {{ agentId }}</p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'AgentLiveSettlement',
|
||||
props: {
|
||||
agentId: {
|
||||
type: [String, Number],
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
Reference in New Issue
Block a user