Compare commits

...

3 Commits

Author SHA1 Message Date
Yu Sung
97b832fd2e feat(calculate): 라이브 환불 기능 API 연동 및 UI 수정
- refundLive API 요청 파라미터를 canUsage에서 canUsageStr로 변경
- CalculateLive 화면의 환불 함수에서 canUsageStr을 전달하도록 수정
- API URL(/admin/calculate/live/refund) 및 필드 요구사항 반영
2026-03-16 15:49:28 +09:00
Yu Sung
b21d0f455f feat(chat): 시스템 프롬프트 글자수 표시 및 2000자 제한 추가 2026-03-16 11:12:38 +09:00
Yu Sung
0e4b38ce3e feat(charge-refund): 캔 환불 프로세스 추가 2026-03-05 18:13:41 +09:00
5 changed files with 108 additions and 23 deletions

View File

@@ -138,6 +138,15 @@ async function deleteCreatorSettlementRatio(memberId) {
return Vue.axios.post('/admin/calculate/ratio/delete/' + memberId);
}
async function refundLive(roomId, canUsageStr) {
const request = {
roomId: roomId,
canUsageStr: canUsageStr
};
return Vue.axios.post('/admin/calculate/live/refund', request);
}
export {
getCalculateLive,
getCalculateContent,
@@ -148,6 +157,7 @@ export {
createCreatorSettlementRatio,
updateCreatorSettlementRatio,
deleteCreatorSettlementRatio,
refundLive,
getCalculateLiveByCreator,
getCalculateContentByCreator,
getCalculateCommunityByCreator,

View File

@@ -11,4 +11,8 @@ async function getChargeStatusDetail(startDate, paymentGateway, currency) {
);
}
export { getChargeStatus, getChargeStatusDetail }
async function refundCharge(chargeId) {
return Vue.axios.post('/admin/charge/refund', { chargeId });
}
export { getChargeStatus, getChargeStatusDetail, refundCharge }

View File

@@ -69,10 +69,6 @@
class="elevation-1"
hide-default-footer
>
<template v-slot:item.email="{ item }">
{{ item.email }}
</template>
<template v-slot:item.nickname="{ item }">
{{ item.nickname }}
</template>
@@ -116,6 +112,16 @@
<template v-slot:item.depositAmount="{ item }">
{{ item.depositAmount.toLocaleString() }}
</template>
<template v-slot:item.actions="{ item }">
<v-btn
small
color="error"
@click="refund(item)"
>
환불
</v-btn>
</template>
</v-data-table>
</v-col>
</v-row>
@@ -151,12 +157,6 @@ export default {
total_page: 0,
items: [],
headers: [
{
text: '이메일',
align: 'center',
sortable: false,
value: 'email',
},
{
text: '크리에이터',
align: 'center',
@@ -227,6 +227,12 @@ export default {
align: 'center',
sortable: false,
value: 'depositAmount',
},
{
text: '관리',
align: 'center',
sortable: false,
value: 'actions',
}
],
}
@@ -286,6 +292,22 @@ export default {
this.getCalculateLive()
},
async refund(item) {
if (confirm('정말로 환불하시겠습니까?')) {
try {
const res = await api.refundLive(item.roomId, item.canUsageStr)
if (res.status === 200 && res.data.success === true) {
this.notifySuccess('환불 처리가 완료되었습니다.')
await this.getCalculateLive()
} else {
this.notifyError(res.data.message || '환불 처리 중 오류가 발생했습니다.')
}
} catch (e) {
this.notifyError('환불 처리 중 오류가 발생했습니다.')
}
}
},
async downloadExcel() {
try {
const res = await api.downloadCalculateLiveExcel(this.start_date, this.end_date)

View File

@@ -94,10 +94,6 @@
class="elevation-1"
hide-default-footer
>
<template v-slot:item.accountId="{ item }">
{{ item.accountId }}
</template>
<template v-slot:item.nickname="{ item }">
{{ item.nickname }}
</template>
@@ -113,6 +109,16 @@
<template v-slot:item.datetime="{ item }">
{{ item.datetime }}
</template>
<template v-slot:item.refund="{ item }">
<v-btn
color="error"
small
@click="confirmRefund(item)"
>
환불
</v-btn>
</template>
</v-data-table>
<v-card-actions v-show="!is_loading">
<v-spacer />
@@ -146,14 +152,9 @@ export default {
end_date: null,
items: [],
detail_items: null,
selected_date_item: null,
show_popup_dialog: false,
detail_headers: [
{
text: 'no',
align: 'center',
sortable: false,
value: 'accountId',
},
{
text: '닉네임',
align: 'center',
@@ -184,6 +185,12 @@ export default {
sortable: false,
value: 'datetime',
},
{
text: '환불',
align: 'center',
sortable: false,
value: 'refund',
},
],
headers: [
{
@@ -284,6 +291,7 @@ export default {
async getChargeStatusDetail(value) {
if (value.date !== '합계') {
this.is_loading = true
this.selected_date_item = value
try {
const res = await api.getChargeStatusDetail(value.date, value.pg, value.currency)
@@ -300,6 +308,45 @@ export default {
this.is_loading = false
}
}
},
async confirmRefund(item) {
let canText = `${item.chargeCan}`
if (item.rewardCan > 0) {
canText += ` + ${item.rewardCan}`
}
const confirm = await this.$dialog.confirm({
title: '환불 확인',
text: `${item.nickname}님의 ${canText}을 환불하시겠습니까?`,
actions: {
false: '취소',
true: '환불'
}
})
if (confirm) {
await this.refundCharge(item.chargeId)
}
},
async refundCharge(chargeId) {
this.is_loading = true
try {
const res = await api.refundCharge(chargeId)
if (res.status === 200 && res.data.success === true) {
this.notifySuccess('환불이 완료되었습니다.')
await this.getChargeStatusDetail(this.selected_date_item)
await this.getChargeStatus()
} else {
this.notifyError(res.data.message || '환불 처리 중 오류가 발생했습니다.')
}
} catch (e) {
this.notifyError('환불 처리 중 오류가 발생했습니다.')
} finally {
this.is_loading = false
}
}
}
}

View File

@@ -353,10 +353,11 @@
<v-col cols="12">
<v-textarea
v-model="character.systemPrompt"
label="시스템 프롬프트"
label="시스템 프롬프트 (최대 2000자)"
outlined
auto-grow
rows="4"
counter="2000"
:class="{ 'required-asterisk': !isEdit }"
:rules="systemPromptRules"
/>
@@ -1182,7 +1183,8 @@ export default {
],
typeOptions: ['Clone', 'Character'],
systemPromptRules: [
v => (this.isEdit ? true : (!!v && v.trim().length > 0) || '시스템 프롬프트를 입력하세요')
v => (this.isEdit ? true : (!!v && v.trim().length > 0) || '시스템 프롬프트를 입력하세요'),
v => (!!v && v.length <= 2000) || '최대 2000자까지 입력 가능합니다'
],
// 인물 관계 옵션 및 검증 규칙
relationshipTypeOptions: ['가족', '친구', '동료', '연인', '기타'],