Compare commits

...

110 Commits

Author SHA1 Message Date
17ff1b817d Merge pull request 'test' (#101) from test into main
Reviewed-on: #101
2026-05-07 06:49:41 +00:00
Yu Sung
90377bdb3c feat(content-list): 검색 버튼 색상 수정
- 검색 버튼 색상: #3bb9f1로 변경
2026-05-07 15:29:34 +09:00
Yu Sung
a58a5cc0d1 feat(member): 계정 상세 팝업에 콘텐츠 관리자 권한 추가 및 라벨/검색 버튼 색상 수정
- 신규 권한: CONTENT_MANAGER 라디오 옵션 및 매핑 추가
- 라벨 변경: '사용 여부' → '권한'
- 검색 버튼 색상: #3bb9f1로 변경

왜: 콘텐츠 관리자 권한 지원 및 UI 용어/가시성 개선
무엇: MemberList.vue 수정으로 옵션/매핑/라벨/컬러 반영
2026-05-07 15:29:02 +09:00
Yu Sung
e7c95ab91b fix(content): ADMIN 권한에서만 테마 조회 API 호출하도록 수정
ContentList.vue의 created 훅에서 isAdmin 검사 후 getAudioContentThemeList 조건부 호출.

불필요한 API 호출 방지 및 권한 준수.
2026-05-07 15:23:49 +09:00
Yu Sung
ad4d498eeb feat(menu): 역할 기반 사이드 메뉴 추가/노출 로직 개선
- ADMIN 권한에만 추가 메뉴(시리즈 배너, 캐릭터 챗봇, 에이전트 관리, 정산 확장) 노출

- API 메뉴가 비어있고 CONTENT_MANAGER이면 '콘텐츠 리스트(/content/list)' 기본 메뉴 추가

- 기존 예외 처리 유지
2026-05-07 15:21:39 +09:00
Yu Sung
c72e1c18df fix(content): 관리 컬럼과 버튼을 ADMIN 권한에만 표시
배경: 비ADMIN 계정에서도 관리 열과 수정/삭제/공유 버튼이 노출되어 접근 혼란을 유발.

변경: computed isAdmin(Vuex accountStore.role 우선, localStorage 폴백) 추가 후, 테이블 헤더와 각 행의 관리 영역에 v-if="isAdmin" 적용.

영향: ADMIN 외 권한에서는 UI 요소가 렌더링되지 않음. 기능 동작 변경 없음.
2026-05-07 14:28:47 +09:00
Yu Sung
9435334734 fix(api): 관리자 로그인 API 엔드포인트 변경
- /member/login -> /admin/member/login
- 프론트엔드 관리자 로그인 경로와 백엔드 변경사항 동기화
2026-05-07 14:21:59 +09:00
Yu Sung
f01f002614 refactor(account): 로그인 상태 필드 정리 및 role 저장
왜: userId/nickname/profileImage는 사용처가 없어 유지보수 단순화. 대신 권한 판별을 위해 role 필요.\n무엇: accountStore에서 세 필드 삭제, role 추가. isAuthenticated 동기화 수정. LOGIN/LOGOUT 로직 role 반영. Axios Authorization 유지.
2026-05-07 14:19:21 +09:00
6769d8d485 Merge pull request 'feat(can): 캔 등록 화면에 일본 엔(JPY) 화폐 단위를 추가' (#100) from test into main
Reviewed-on: #100
2026-05-01 06:35:22 +00:00
Yu Sung
a833f0b6b8 feat(can): 캔 등록 화면에 일본 엔(JPY) 화폐 단위를 추가 2026-05-01 14:27:41 +09:00
860b3c7bab Merge pull request 'fix(calculate): 오리지널 시리즈 정산 - pageSize 20으로 수정' (#99) from test into main
Reviewed-on: #99
2026-04-22 02:14:44 +00:00
Yu Sung
9b756cbaf1 fix(calculate): 오리지널 시리즈 정산 - pageSize 20으로 수정 2026-04-22 11:12:53 +09:00
7d694a4c36 Merge pull request 'feat(calculate): 오리지널 시리즈 정산 기능 추가' (#98) from test into main
Reviewed-on: #98
2026-04-22 01:34:25 +00:00
Yu Sung
de18086699 feat(calculate): 오리지널 시리즈 정산 기능 추가
Co-authored-by: Junie <junie@jetbrains.com>
2026-04-22 10:20:19 +09:00
cae9e9a430 Merge pull request '에이전트 기능' (#97) from test into main
Reviewed-on: #97
2026-04-14 10:00:04 +00:00
f90f8f6250 Merge pull request 'test' (#96) from test into main
Reviewed-on: #96
2026-04-08 02:17:32 +00:00
abb15cb2c7 Merge pull request 'feat(calculate): 라이브 환불 기능 API 연동 및 UI 수정' (#95) from test into main
Reviewed-on: #95
2026-03-16 07:27:32 +00:00
b26837f258 Merge pull request 'feat(chat): 시스템 프롬프트 글자수 표시 및 2000자 제한 추가' (#94) from test into main
Reviewed-on: #94
2026-03-16 02:16:13 +00:00
f42602886e Merge pull request 'test' (#93) from test into main
Reviewed-on: #93
2026-03-05 09:26:14 +00:00
b8373829f0 Merge pull request 'feat(calculate): 크리에이터별 채널 후원 정산 페이지 개발 및 관련 API 수정' (#92) from test into main
Reviewed-on: #92
2026-03-03 05:57:30 +00:00
2769c3c9f0 Merge pull request '채널 후원 정산 페이지 추가' (#91) from test into main
Reviewed-on: #91
2026-02-26 11:28:32 +00:00
648d4d3a97 Merge pull request 'fix(content): 오디오 콘텐츠 삭제 시 FormData 형식으로 요청하도록 수정' (#90) from test into main
Reviewed-on: #90
2026-02-13 09:42:24 +00:00
4baf253b7e Merge pull request '회원 통계 페이지에 애플 가입 수 추가' (#89) from test into main
Reviewed-on: #89
2026-02-08 07:52:06 +00:00
e0c63df2a6 Merge pull request '콘텐츠 수정 - 커버 이미지 수정 기능 추가' (#88) from test into main
Reviewed-on: #88
2026-02-06 05:13:01 +00:00
892923becc Merge pull request 'test' (#87) from test into main
Reviewed-on: #87
2026-02-04 14:00:37 +00:00
d3ea703204 Merge pull request '캔 환율관리 - 페이징 없이 모든 데이터 표시되도록 수정' (#86) from test into main
Reviewed-on: #86
2026-01-13 05:11:30 +00:00
70298b8f8f Merge pull request 'feat(admin-series): 시리즈 리스트에 연재요일 표시' (#85) from test into main
Reviewed-on: #85
2025-11-14 08:21:07 +00:00
9fa9f3e699 Merge pull request 'test' (#84) from test into main
Reviewed-on: #84
2025-11-13 20:18:27 +00:00
d82531583c Merge pull request 'fix(admin-series): 시리즈 수정 기능 추가' (#83) from test into main
Reviewed-on: #83
2025-11-13 19:51:42 +00:00
6240a285c2 Merge pull request 'fix(admin-can): 닉네임 검색 시 선택 칩이 사라지는 문제 수정' (#82) from test into main
Reviewed-on: #82
2025-11-10 08:05:25 +00:00
f577ab575e Merge pull request 'feat(admin-can): 캔 지급 화면에 닉네임 검색·다중 회원번호 입력 및 다중 지급 지원' (#81) from test into main
Reviewed-on: #81
2025-11-10 07:08:25 +00:00
0c3e3fc3fd Merge pull request 'feat(admin-can-status): 화폐단위 추가, 충전금액에 NumberFormat style: currency 적용하여 화폐단위 표시' (#80) from test into main
Reviewed-on: #80
2025-10-10 21:00:42 +00:00
6886c372aa Merge pull request 'feat(can): 소수점이 잘못 표기되던 버그 수정' (#79) from test into main
Reviewed-on: #79
2025-10-10 08:58:35 +00:00
8dd3dcb770 Merge pull request 'test' (#78) from test into main
Reviewed-on: #78
2025-10-10 08:25:15 +00:00
1a435b6074 Merge pull request 'test' (#77) from test into main
Reviewed-on: #77
2025-09-18 19:42:41 +00:00
492859dae3 Merge pull request 'test' (#76) from test into main
Reviewed-on: #76
2025-09-16 06:16:32 +00:00
18b59b5598 Merge pull request 'test' (#75) from test into main
Reviewed-on: #75
2025-09-14 09:04:57 +00:00
5fcdd7f06d Merge pull request '캐릭터 챗봇' (#74) from test into main
Reviewed-on: #74
2025-09-10 06:26:02 +00:00
1e149f7e41 Merge pull request '쿠폰생성 - 쿠폰타입(포인트, 캔) 선택 추가' (#73) from test into main
Reviewed-on: #73
2025-06-10 11:01:52 +00:00
aca3767a24 Merge pull request 'test' (#72) from test into main
Reviewed-on: #72
2025-05-20 07:21:28 +00:00
d51655f15e Merge pull request '포인트 정책 등록/수정 페이지 추가' (#71) from test into main
Reviewed-on: #71
2025-04-24 03:28:52 +00:00
47dd32939f Merge pull request '일별 전체 회원 수 - 이메일, 구글, 카카오 회원 수 추가' (#70) from test into main
Reviewed-on: #70
2025-04-10 02:35:33 +00:00
2e1891ab08 Merge pull request '회원리스트 - 로그인 타입 필드 추가' (#69) from test into main
Reviewed-on: #69
2025-04-09 10:44:30 +00:00
99d70cc8f7 Merge pull request '이벤트 배너 수정 - 링크 지우기 추가' (#68) from test into main
Reviewed-on: #68
2025-04-07 14:48:10 +00:00
9f1675e82d Merge pull request '광고통계 - 로그인 수를 가장 오른쪽으로 이동' (#67) from test into main
Reviewed-on: #67
2025-04-02 02:11:35 +00:00
c2838be2ed Merge pull request '일별 전체 회원 수 통계' (#66) from test into main
Reviewed-on: #66
2025-03-31 03:54:56 +00:00
b5c2941c0d Merge pull request '앱 실행 수 추가' (#65) from test into main
Reviewed-on: #65
2025-03-28 05:58:43 +00:00
d5c01d8d23 Merge pull request '광고통계 - 빠른검색 (날짜 지정) 추가' (#64) from test into main
Reviewed-on: #64
2025-03-17 04:58:02 +00:00
7118b0649a Merge pull request '비밀번호 재설정 기능 추가' (#63) from test into main
Reviewed-on: #63
2025-03-17 03:09:41 +00:00
8f5346581e Merge pull request '일별 전체 회원 수 페이지 추가' (#62) from test into main
Reviewed-on: #62
2025-03-14 16:08:06 +00:00
e43f2e30be Merge pull request '충전 이벤트, 이벤트 배너 - 기간 설정에 시간 추가' (#61) from test into main
Reviewed-on: #61
2025-03-14 03:34:42 +00:00
397fd267e0 Merge pull request 'test' (#60) from test into main
Reviewed-on: #60
2025-03-11 08:07:48 +00:00
fe4b88350b Merge pull request '광고 통계 페이지' (#59) from test into main
Reviewed-on: #59
2025-03-05 13:53:32 +00:00
537474e162 Merge pull request '마케팅 - 매체 파트너 코드 페이지 추가' (#58) from test into main
Reviewed-on: #58
2025-03-05 09:54:31 +00:00
b5abdf3cf5 Merge pull request 'test' (#57) from test into main
Reviewed-on: #57
2025-02-18 15:12:52 +00:00
a2e457b5e8 Merge pull request 'test' (#56) from test into main
Reviewed-on: #56
2025-02-09 13:25:35 +00:00
05ddd417cd Merge pull request '콘텐츠 배너 등록/수정' (#54) from test into main
Reviewed-on: #54
2025-01-17 16:46:45 +00:00
e70426af68 Merge pull request 'test' (#53) from test into main
Reviewed-on: #53
2025-01-17 06:00:59 +00:00
81b33e1322 Merge pull request '오디션 지원 취소기능 적용' (#52) from test into main
Reviewed-on: #52
2025-01-08 06:34:54 +00:00
588fcfbe90 Merge pull request '오디션 지원자 연락처 표시' (#51) from test into main
Reviewed-on: #51
2025-01-07 20:10:23 +00:00
ff2c126382 Merge pull request '오디션 메뉴 추가' (#50) from test into main
Reviewed-on: #50
2025-01-07 17:20:32 +00:00
702daca29f Merge pull request '소다라이브 -> 보이스온' (#49) from test into main
Reviewed-on: #49
2024-11-21 12:59:05 +00:00
8e9008a3c1 Merge pull request '이벤트 기간 추가' (#48) from test into main
Reviewed-on: #48
2024-10-31 03:17:44 +00:00
5c0c00aad4 Merge pull request '크리에이터 리스트 - 프로필 이미지 다운로드 버튼 추가' (#47) from test into main
Reviewed-on: #47
2024-10-24 03:07:00 +00:00
e0949c6d73 Merge pull request 'test' (#46) from test into main
Reviewed-on: #46
2024-10-16 04:18:55 +00:00
0449bac8d5 Merge pull request '전체 개수 추가' (#45) from test into main
Reviewed-on: #45
2024-10-15 04:18:01 +00:00
d412c15c9d Merge pull request '시리즈 리스트 - 작품 개수 추가' (#44) from test into main
Reviewed-on: #44
2024-10-14 15:43:15 +00:00
ed16a6ddad Merge pull request '시리즈 리스트 페이지 추가' (#43) from test into main
Reviewed-on: #43
2024-10-14 10:14:19 +00:00
f06e2d41e0 Merge pull request '전체 크리에이터 수 추가' (#42) from test into main
Reviewed-on: #42
2024-09-26 11:38:53 +00:00
7505269db3 Merge pull request '크리에이터별 정산 - 페이징 추가' (#41) from test into main
Reviewed-on: #41
2024-08-01 05:16:04 +00:00
15eeb6943d Merge pull request '크리에이터 기준 라이브, 콘텐츠, 커뮤니티 합계 정산 페이지 추가' (#40) from test into main
Reviewed-on: #40
2024-07-08 14:41:28 +00:00
7e7ed46cea Merge pull request '크리에이터 기준 라이브, 콘텐츠, 커뮤니티 합계 정산 페이지 추가' (#39) from test into main
Reviewed-on: #39
2024-07-08 14:37:08 +00:00
fd01786649 Merge pull request 'test' (#38) from test into main
Reviewed-on: #38
2024-07-08 14:22:01 +00:00
c48c1c2f09 Merge pull request '크리에이터 정산비율 등록페이지 추가' (#37) from test into main
Reviewed-on: #37
2024-06-11 08:11:57 +00:00
9bcf3a3cdb Merge pull request '커뮤니티 정산' (#36) from test into main
Reviewed-on: #36
2024-06-06 14:59:58 +00:00
4c5b987d98 Merge pull request 'test' (#35) from test into main
Reviewed-on: #35
2024-06-03 22:24:23 +00:00
f168403048 Merge pull request '라이브 리스트 - 현재참여인원 추가' (#34) from test into main
Reviewed-on: #34
2024-05-28 18:16:18 +00:00
82ee1584e7 Merge pull request '커뮤니티 정산 페이지 추가' (#33) from test into main
Reviewed-on: #33
2024-05-28 16:13:16 +00:00
65cb918389 Merge pull request '시그니처 관리 - 재생 시간 등록/수정 기능 추가' (#32) from test into main
Reviewed-on: #32
2024-05-02 07:17:34 +00:00
784baf9a2f Merge pull request '시리즈 장르 - 등록/삭제 페이지 추가' (#31) from test into main
Reviewed-on: #31
2024-04-26 19:06:32 +00:00
7a85ac41cc Merge pull request '관리자 - 캔 충전현황' (#30) from test into main
Reviewed-on: #30
2024-04-01 11:34:15 +00:00
9d4c9437cf Merge pull request '관리자 - 캔 충전현황' (#29) from test into main
Reviewed-on: #29
2024-04-01 11:27:14 +00:00
68845aeae1 Merge pull request '콘텐츠 리스트 한정판 표시' (#28) from test into main
Reviewed-on: #28
2024-03-29 05:00:01 +00:00
bbdca29337 Merge pull request '콘텐츠 리스트' (#27) from test into main
Reviewed-on: #27
2024-03-28 06:43:25 +00:00
c14c041daa Merge pull request 'test' (#26) from test into main
Reviewed-on: #26
2024-03-19 07:50:16 +00:00
a515a144eb Merge pull request 'test' (#25) from test into main
Reviewed-on: #25
2024-03-13 11:42:23 +00:00
54a6773905 Merge pull request 'test' (#24) from test into main
Reviewed-on: #24
2024-03-12 07:54:10 +00:00
d97087b4e9 Merge pull request '시그니처 캔 등록 페이지 추가' (#23) from test into main
Reviewed-on: #23
2024-03-08 13:59:51 +00:00
ddb2449053 Merge pull request '파비콘 변경' (#22) from test into main
Reviewed-on: #22
2024-02-17 14:56:25 +00:00
8aca07cdf7 Merge pull request '콘텐츠 수정' (#21) from test into main
Reviewed-on: #21
2024-02-08 18:25:50 +00:00
0ba845d95a Merge pull request '콘텐츠 리스트 - 오픈예정일 추가' (#20) from test into main
Reviewed-on: #20
2024-01-11 09:27:25 +00:00
64b1fd5395 Merge pull request '수정 기능 추가' (#19) from test into main
Reviewed-on: #19
2024-01-03 15:25:28 +00:00
639bea70fa Merge pull request '쿠폰 관리 페이지 추가' (#18) from test into main
Reviewed-on: #18
2024-01-03 10:33:23 +00:00
6a89ba059b Merge pull request '푸시 발송 대상 지정 UI 추가' (#17) from test into main
Reviewed-on: #17
2023-11-24 07:01:10 +00:00
ff83041585 Merge pull request '연령제한 표시 추가' (#16) from test into main
Reviewed-on: #16
2023-11-21 16:25:21 +00:00
e660be0bf4 Merge pull request '일자별 콘텐츠 후원 페이지 - 유/무료 구분 추가' (#15) from test into main
Reviewed-on: #15
2023-11-14 13:36:49 +00:00
62cdd57069 Merge pull request '일자별 콘텐츠 후원 페이지 - 유/무료 구분 추가' (#14) from test into main
Reviewed-on: #14
2023-11-14 13:34:37 +00:00
f8346ed5ef Merge pull request '일자별 콘텐츠 후원 페이지 - 유/무료 구분 추가' (#13) from test into main
Reviewed-on: #13
2023-11-14 13:19:50 +00:00
9656b9a9d1 Merge pull request '일자별 콘텐츠 후원 페이지 추가' (#12) from test into main
Reviewed-on: #12
2023-11-14 08:57:15 +00:00
97a58266bb Merge pull request 'orderType 추가, 판매수 -> 누적 판매수 로 변경' (#11) from test into main
Reviewed-on: #11
2023-11-13 14:52:38 +00:00
8fc0cfa345 Merge pull request '콘텐츠별 누적 현황 페이지 - 총 콘텐츠 개수 표시' (#10) from test into main
Reviewed-on: #10
2023-11-13 14:08:26 +00:00
22f9c2287d Merge pull request '콘텐츠별 누적 현황 페이지 추가' (#9) from test into main
Reviewed-on: #9
2023-11-13 13:46:19 +00:00
9284f7d5c3 Merge pull request '콘텐츠 정산 - 엑셀 다운로드 추가' (#8) from test into main
Reviewed-on: #8
2023-11-13 08:46:43 +00:00
e6f27a4529 Merge pull request '콘텐츠 정산 - 헤더 순서 변경' (#7) from test into main
Reviewed-on: #7
2023-11-10 13:56:50 +00:00
6a33d1c024 Merge pull request '콘텐츠 정산 페이지 추가' (#6) from test into main
Reviewed-on: #6
2023-11-10 10:51:32 +00:00
3b83789c15 Merge pull request 'test' (#5) from test into main
Reviewed-on: #5
2023-10-06 15:09:02 +00:00
55f0ab9af3 Merge pull request '크리에이터 라이브 정산 - 인원 추가, 코인 -> 캔' (#4) from test into main
Reviewed-on: #4
2023-10-03 12:15:25 +00:00
9b168a6112 Merge pull request '크리에이터 라이브 정산 페이지 추가' (#3) from test into main
Reviewed-on: #3
2023-10-03 09:25:39 +00:00
c47937933e Merge pull request 'test' (#2) from test into main
Reviewed-on: #2
2023-08-25 07:50:32 +00:00
4744fe7d9a Merge pull request '채널공유 - 파이어베이스 링크, 도메인, 프로젝트명 변경' (#1) from test into main
Reviewed-on: #1
2023-08-22 03:39:44 +00:00
9 changed files with 537 additions and 113 deletions

View File

@@ -1,7 +1,7 @@
import Vue from 'vue'; import Vue from 'vue';
async function login(email, password) { async function login(email, password) {
return Vue.axios.post('/member/login', { return Vue.axios.post('/admin/member/login', {
email, email,
password, password,
isAdmin: true, isAdmin: true,

View File

@@ -0,0 +1,37 @@
import Vue from 'vue';
// 소지 유저 조회
async function getOwners() {
return Vue.axios.get('/admin/calculate/original-series/owners');
}
// 정산 내역 조회 (page는 1부터 시작하는 UI 기준, 서버에는 0부터 전달)
async function getSettlementDetails({ startDate, endDate, creatorId, page = 1, size = 10 }) {
const params = new URLSearchParams();
// 서버 파라미터 스펙 변경: start_date, end_date, creator_id
if (startDate) params.append('start_date', startDate);
if (endDate) params.append('end_date', endDate);
if (creatorId != null) params.append("creator_id", creatorId);
params.append('page', Math.max(0, (page || 1) - 1));
params.append('size', size || 10);
return Vue.axios.get(`/admin/calculate/original-series/settlement-details?${params.toString()}`);
}
// 엑셀 다운로드 (xlsx 바이너리)
async function downloadSettlementExcel({ startDate, endDate }) {
const params = new URLSearchParams();
// 서버 파라미터 스펙 변경: start_date, end_date
if (startDate) params.append('start_date', startDate);
if (endDate) params.append('end_date', endDate);
return Vue.axios.get(`/admin/calculate/original-series/settlement-details/excel?${params.toString()}` , {
responseType: 'blob'
});
}
export {
getOwners,
getSettlementDetails,
downloadSettlementExcel,
};

View File

@@ -94,103 +94,135 @@ export default {
this.isLoading = true this.isLoading = true
try { try {
let res = await api.getMenus(); let res = await api.getMenus();
if (res.status === 200 && res.data.success === true && res.data.data.length > 0) { if (res.status === 200 && res.data.success === true) {
this.items = res.data.data // 기본 메뉴 설정 (API 결과가 비어있을 수 있음)
this.items = Array.isArray(res.data.data) ? res.data.data : []
// '시리즈 관리' 메뉴에 '배너 등록' 하위 메뉴 추가 // 현재 사용자 역할 확인
try { const role = (this.$store && this.$store.state && this.$store.state.accountStore && this.$store.state.accountStore.role)
const seriesMenu = this.items.find(m => m && m.title === '시리즈 관리') || localStorage.role
if (seriesMenu) {
if (!Array.isArray(seriesMenu.items)) { // ADMIN 권한 전용 추가 메뉴들
seriesMenu.items = seriesMenu.items ? [].concat(seriesMenu.items) : [] if (role === 'ADMIN') {
} // '시리즈 관리' 메뉴에 '배너 등록' 하위 메뉴 추가
const exists = seriesMenu.items.some(ci => ci && ci.route === '/content/series/banner') try {
if (!exists) { const seriesMenu = this.items.find(m => m && m.title === '시리즈 관리')
seriesMenu.items.push({ if (seriesMenu) {
title: '배너 등록', if (!Array.isArray(seriesMenu.items)) {
route: '/content/series/banner', seriesMenu.items = seriesMenu.items ? [].concat(seriesMenu.items) : []
items: null }
}) const exists = seriesMenu.items.some(ci => ci && ci.route === '/content/series/banner')
if (!exists) {
seriesMenu.items.push({
title: '배너 등록',
route: '/content/series/banner',
items: null
})
}
} }
} catch (e) {
// ignore
} }
} catch (e) {
// ignore
}
// 캐릭터 챗봇 메뉴 추가 // 캐릭터 챗봇 메뉴 추가
this.items.push({ this.items.push({
title: '캐릭터 챗봇', title: '캐릭터 챗봇',
route: null,
items: [
{
title: '배너 등록',
route: '/character/banner',
items: null
},
{
title: '캐릭터 리스트',
route: '/character',
items: null
},
{
title: '큐레이션',
route: '/character/curation',
items: null
},
{
title: '정산',
route: '/character/calculate',
items: null
},
{
title: '원작',
route: '/original-work',
items: null
},
]
})
// 에이전트 관리 메뉴를 '크리에이터 관리' 바로 아래에 추가
try {
const insertAfterTitle = '크리에이터 관리'
const agentMenu = {
title: '에이전트 관리',
route: null, route: null,
items: [ items: [
{ title: '에이전트 리스트', route: '/agent/list', items: null }, {
{ title: '에이전트 정산 비율', route: '/agent/settlement-ratio', items: null }, title: '배너 등록',
route: '/character/banner',
items: null
},
{
title: '캐릭터 리스트',
route: '/character',
items: null
},
{
title: '큐레이션',
route: '/character/curation',
items: null
},
{
title: '정산',
route: '/character/calculate',
items: null
},
{
title: '원작',
route: '/original-work',
items: null
},
] ]
})
// 에이전트 관리 메뉴를 '크리에이터 관리' 바로 아래에 추가
try {
const insertAfterTitle = '크리에이터 관리'
const agentMenu = {
title: '에이전트 관리',
route: null,
items: [
{ title: '에이전트 리스트', route: '/agent/list', items: null },
{ title: '에이전트 정산 비율', route: '/agent/settlement-ratio', items: null },
]
}
const idx = this.items.findIndex(m => m && m.title === insertAfterTitle)
if (idx >= 0) {
this.items.splice(idx + 1, 0, agentMenu)
} else {
// 기준 메뉴가 없으면 하단에 추가
this.items.push(agentMenu)
}
} catch (e) {
// ignore
} }
const idx = this.items.findIndex(m => m && m.title === insertAfterTitle) // 정산현황 메뉴에 '채널 후원 정산' 및 '오리지널 시리즈 정산' 추가
if (idx >= 0) { try {
this.items.splice(idx + 1, 0, agentMenu) const calculateMenu = this.items.find(m => m && m.title === '정산현황')
} else { if (calculateMenu) {
// 기준 메뉴가 없으면 하단에 추가 if (!Array.isArray(calculateMenu.items)) {
this.items.push(agentMenu) calculateMenu.items = calculateMenu.items ? [].concat(calculateMenu.items) : []
}
const exists = calculateMenu.items.some(ci => ci && ci.route === '/calculate/channel-donation')
if (!exists) {
calculateMenu.items.push({
title: '채널 후원 정산',
route: '/calculate/channel-donation',
items: null
})
}
const existsOriginal = calculateMenu.items.some(ci => ci && ci.route === '/calculate/original-series')
if (!existsOriginal) {
calculateMenu.items.push({
title: '오리지널 시리즈 정산',
route: '/calculate/original-series',
items: null
})
}
}
} catch (e) {
// ignore
} }
} catch (e) {
// ignore
} }
// 정산 관리 메뉴에 '채널 후원 정산' 추가 // 조회한 메뉴가 비어 있고, 콘텐츠 매니저라면 기본 메뉴 추가
try { if (this.items.length === 0 && role === 'CONTENT_MANAGER') {
const calculateMenu = this.items.find(m => m && m.title === '정산 관리') this.items.push({
if (calculateMenu) { title: '콘텐츠 리스트',
if (!Array.isArray(calculateMenu.items)) { route: '/content/list',
calculateMenu.items = calculateMenu.items ? [].concat(calculateMenu.items) : [] items: null
} })
const exists = calculateMenu.items.some(ci => ci && ci.route === '/calculate/channel-donation') }
if (!exists) {
calculateMenu.items.push({ // 그래도 비어있다면 이전 동작과 동일하게 처리
title: '채널 후원 정산', if (this.items.length === 0) {
route: '/calculate/channel-donation', this.notifyError("알 수 없는 오류가 발생했습니다. 다시 로그인 해주세요!")
items: null this.logout();
})
}
}
} catch (e) {
// ignore
} }
} else { } else {
this.notifyError("알 수 없는 오류가 발생했습니다. 다시 로그인 해주세요!") this.notifyError("알 수 없는 오류가 발생했습니다. 다시 로그인 해주세요!")

View File

@@ -51,6 +51,11 @@ const routes = [
component: () => import(/* webpackChunkName: "counselor" */ '../views/Creator/CreatorSettlementRatio.vue') component: () => import(/* webpackChunkName: "counselor" */ '../views/Creator/CreatorSettlementRatio.vue')
}, },
// Agent Management // Agent Management
{
path: '/calculate/original-series',
name: 'OriginalSeriesSettlement',
component: () => import(/* webpackChunkName: "calculate" */ '../views/Calculate/OriginalSeriesSettlement.vue')
},
{ {
path: '/agent/list', path: '/agent/list',
name: 'AgentList', name: 'AgentList',

View File

@@ -12,17 +12,13 @@ enhanceAccessToken();
const accountStore = { const accountStore = {
namespaced: true, namespaced: true,
state: { state: {
userId: '',
nickname: '',
accessToken: '', accessToken: '',
profileImage: '', role: '',
}, },
getters: { getters: {
isAuthenticated(state) { isAuthenticated(state) {
state.userId = state.userId || localStorage.userId
state.nickname = state.nickname || localStorage.nickname
state.profileImage = state.profileImage || localStorage.profileImage
state.accessToken = state.accessToken || localStorage.accessToken state.accessToken = state.accessToken || localStorage.accessToken
state.role = state.role || localStorage.role
return state.accessToken !== undefined && return state.accessToken !== undefined &&
state.accessToken !== null && state.accessToken !== null &&
@@ -31,27 +27,19 @@ const accountStore = {
} }
}, },
mutations: { mutations: {
LOGIN(state, {userId, nickname, token, profileImage}) { LOGIN(state, {token, role}) {
state.userId = userId
localStorage.userId = userId
state.nickname = nickname
localStorage.nickname = nickname
state.profileImage = profileImage
localStorage.profileImage = profileImage
state.accessToken = token state.accessToken = token
localStorage.accessToken = token localStorage.accessToken = token
state.role = role
localStorage.role = role
Vue.axios.defaults.headers.common['Authorization'] = `Bearer ${token}`; Vue.axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
}, },
LOGOUT(state) { LOGOUT(state) {
state.userId = ''
state.nickname = ''
state.profileImage = ''
state.accessToken = '' state.accessToken = ''
state.role = ''
localStorage.clear() localStorage.clear()
if (location.pathname === '/') { if (location.pathname === '/') {

View File

@@ -0,0 +1,340 @@
<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-btn
color="primary"
:loading="excelLoading"
@click="onDownloadExcel"
>
엑셀 다운로드
</v-btn>
</v-toolbar>
<v-container>
<!-- 필터 영역 -->
<v-row
class="mt-2 mb-2"
align="center"
justify="end"
>
<v-col
cols="12"
md="3"
>
<v-autocomplete
v-model="selectedCreatorId"
:items="ownerOptions"
:loading="ownersLoading"
item-text="nickname"
item-value="creatorId"
label="멤버 선택"
dense
clearable
hide-details
/>
</v-col>
<v-col
cols="12"
md="3"
>
<v-menu
v-model="menuStart"
:close-on-content-click="false"
transition="scale-transition"
offset-y
min-width="auto"
>
<template v-slot:activator="{ on, attrs }">
<v-text-field
v-bind="attrs"
label="시작일"
readonly
dense
:value="startDateStr"
v-on="on"
/>
</template>
<v-date-picker
v-model="startDateStr"
scrollable
@input="menuStart = false"
/>
</v-menu>
</v-col>
<v-col
cols="12"
md="3"
>
<v-menu
v-model="menuEnd"
:close-on-content-click="false"
transition="scale-transition"
offset-y
min-width="auto"
>
<template v-slot:activator="{ on, attrs }">
<v-text-field
v-bind="attrs"
label="종료일"
readonly
dense
:value="endDateStr"
v-on="on"
/>
</template>
<v-date-picker
v-model="endDateStr"
scrollable
@input="menuEnd = false"
/>
</v-menu>
</v-col>
<v-col
cols="12"
md="2"
>
<v-btn
color="primary"
:loading="isLoading"
@click="onSearch"
>
조회
</v-btn>
</v-col>
</v-row>
<!-- 테이블 영역 -->
<v-data-table
:headers="headers"
:items="items"
:loading="isLoading"
:items-per-page="pageSize"
class="elevation-1"
disable-pagination
hide-default-footer
>
<template v-slot:no-data>
<div class="text-center grey--text pa-6">
데이터가 없습니다.
</div>
</template>
<template v-slot:item.price="{ item }">
<span>{{ numberFormat(item.price) }}</span>
</template>
<template v-slot:item.totalCan="{ item }">
<span>{{ numberFormat(item.totalCan) }}</span>
</template>
<template v-slot:item.totalPoint="{ item }">
<span>{{ numberFormat(item.totalPoint) }}</span>
</template>
</v-data-table>
<v-row
class="mt-4"
justify="center"
>
<v-pagination
v-model="page"
:length="totalPages"
:total-visible="7"
@input="fetchList"
/>
</v-row>
</v-container>
</div>
</template>
<script>
import {
getOwners,
getSettlementDetails,
downloadSettlementExcel,
} from "@/api/original_series_settlement";
export default {
name: "OriginalSeriesSettlement",
data() {
return {
// 필터 상태
ownersLoading: false,
ownerOptions: [],
selectedCreatorId: null,
startDateStr: "",
endDateStr: "",
menuStart: false,
menuEnd: false,
// 목록 상태
isLoading: false,
items: [],
totalCount: 0,
page: 1,
pageSize: 20,
excelLoading: false,
headers: [
{ text: "시리즈 제목", value: "seriesTitle", align: "center" },
{ text: "콘텐츠 제목", value: "contentTitle", align: "center" },
{ text: "가격", value: "price", align: "center" },
{ text: "구분", value: "orderType", align: "center" },
{ text: "판매 수", value: "salesCount", align: "center" },
{ text: "합계(캔)", value: "totalCan", align: "center" },
{ text: "합계(포인트)", value: "totalPoint", align: "center" },
],
};
},
computed: {
totalPages() {
return Math.max(1, Math.ceil(this.totalCount / this.pageSize));
},
},
created() {
this.initDefaultDates();
this.loadOwners();
},
methods: {
numberFormat(v) {
if (v === null || v === undefined) return "-";
try {
return Number(v).toLocaleString();
} catch (e) {
return String(v);
}
},
notifyError(message) {
this.$dialog.notify.error(message);
},
notifySuccess(message) {
this.$dialog.notify.success(message);
},
// 이번 달 1일 ~ 오늘
initDefaultDates() {
const now = new Date();
const y = now.getFullYear();
const m = now.getMonth();
const first = new Date(y, m, 1);
const pad = (n) => (n < 10 ? "0" + n : "" + n);
this.startDateStr = `${first.getFullYear()}-${pad(
first.getMonth() + 1
)}-${pad(first.getDate())}`;
this.endDateStr = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(
now.getDate()
)}`;
},
async loadOwners() {
this.ownersLoading = true;
try {
const res = await getOwners();
if (res.status === 200 && res.data && res.data.success) {
const list = Array.isArray(res.data.data) ? res.data.data : [];
this.ownerOptions = list;
// 가장 조회된 값 순서로 온다고 가정, 첫 번째를 기본 선택
if (list.length > 0) {
this.selectedCreatorId = list[0].creatorId;
}
// 초기 조회 (이번 달 범위, 기본 멤버)
this.page = 1;
await this.fetchList();
} else {
this.notifyError(
res.data && res.data.message
? res.data.message
: "소지 유저 조회 실패"
);
}
} catch (e) {
this.notifyError("소지 유저 조회 중 오류가 발생했습니다.");
} finally {
this.ownersLoading = false;
}
},
async onSearch() {
this.page = 1;
await this.fetchList();
},
async fetchList() {
if (!this.selectedCreatorId) {
this.items = [];
this.totalCount = 0;
return;
}
this.isLoading = true;
try {
const res = await getSettlementDetails({
startDate: this.startDateStr,
endDate: this.endDateStr,
creatorId: this.selectedCreatorId,
page: this.page,
size: this.pageSize,
});
if (res.status === 200 && res.data) {
if (res.data.success) {
const data = res.data.data || { totalCount: 0, items: [] };
this.totalCount = data.totalCount || 0;
this.items = Array.isArray(data.items) ? data.items : [];
} else {
this.notifyError(res.data.message || "정산 내역 조회 실패");
}
} else {
this.notifyError("정산 내역 조회 실패");
}
} catch (e) {
this.notifyError("정산 내역 조회 중 오류가 발생했습니다.");
} finally {
this.isLoading = false;
}
},
async onDownloadExcel() {
this.excelLoading = true;
try {
const res = await downloadSettlementExcel({
startDate: this.startDateStr,
endDate: this.endDateStr,
});
const blob = new Blob([res.data], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
});
const url = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.setAttribute("download", "오리지널_시리즈_정산.xlsx");
document.body.appendChild(link);
link.click();
link.parentNode.removeChild(link);
window.URL.revokeObjectURL(url);
this.notifySuccess("엑셀 다운로드가 시작되었습니다.");
} catch (e) {
this.notifyError("엑셀 다운로드 중 오류가 발생했습니다.");
} finally {
this.excelLoading = false;
}
},
},
};
</script>
<style scoped>
/* 테이블 헤더/바디 모두 가운데 정렬 */
.v-data-table table thead th,
.v-data-table table tbody td {
text-align: center !important;
}
</style>

View File

@@ -135,7 +135,8 @@ export default {
currency: 'KRW', currency: 'KRW',
currencies: [ currencies: [
{ text: 'KRW (한국 원)', value: 'KRW' }, { text: 'KRW (한국 원)', value: 'KRW' },
{ text: 'USD (미국 달러)', value: 'USD' } { text: 'USD (미국 달러)', value: 'USD' },
{ text: 'JPY (일본 엔)', value: 'JPY' }
], ],
headers: [ headers: [
{ {

View File

@@ -36,7 +36,7 @@
> >
<v-btn <v-btn
slot="append" slot="append"
color="#9970ff" color="#3bb9f1"
dark dark
@click="search" @click="search"
> >
@@ -96,7 +96,10 @@
<th class="text-center"> <th class="text-center">
오픈 예정일 오픈 예정일
</th> </th>
<th class="text-center"> <th
v-if="isAdmin"
class="text-center"
>
관리 관리
</th> </th>
</tr> </tr>
@@ -214,7 +217,7 @@
</td> </td>
<td>{{ item.date }}</td> <td>{{ item.date }}</td>
<td>{{ item.releaseDate }}</td> <td>{{ item.releaseDate }}</td>
<td> <td v-if="isAdmin">
<v-row> <v-row>
<v-col> <v-col>
<v-btn <v-btn
@@ -527,6 +530,14 @@ export default {
}; };
}, },
computed: {
isAdmin() {
const role = (this.$store && this.$store.state && this.$store.state.accountStore && this.$store.state.accountStore.role)
|| (typeof localStorage !== 'undefined' ? localStorage.role : '');
return role === 'ADMIN';
},
},
async created() { async created() {
this.audio_content = { this.audio_content = {
id: null, id: null,
@@ -539,7 +550,10 @@ export default {
is_settlement_ratio_deleted: false, is_settlement_ratio_deleted: false,
settlement_ratio: "", settlement_ratio: "",
}; };
await this.getAudioContentThemeList(); // ADMIN 권한일 때만 테마 리스트 조회
if (this.isAdmin) {
await this.getAudioContentThemeList();
}
await this.getAudioContent(); await this.getAudioContent();
}, },

View File

@@ -19,7 +19,7 @@
> >
<v-btn <v-btn
slot="append" slot="append"
color="#9970ff" color="#3bb9f1"
dark dark
@click="search" @click="search"
> >
@@ -171,7 +171,7 @@
<v-card-text> <v-card-text>
<v-row align="center"> <v-row align="center">
<v-col cols="4"> <v-col cols="4">
사용 여부 권한
</v-col> </v-col>
<v-col cols="8"> <v-col cols="8">
<v-radio-group <v-radio-group
@@ -191,6 +191,10 @@
value="USER" value="USER"
label="일반회원" label="일반회원"
/> />
<v-radio
value="CONTENT_MANAGER"
label="콘텐츠 관리자"
/>
<v-spacer /> <v-spacer />
</v-radio-group> </v-radio-group>
</v-col> </v-col>
@@ -451,6 +455,8 @@ export default {
this.user_type = 'CREATOR' this.user_type = 'CREATOR'
} else if (member.userType === '에이전트') { } else if (member.userType === '에이전트') {
this.user_type = 'AGENT' this.user_type = 'AGENT'
} else if (member.userType === '콘텐츠 관리자') {
this.user_type = 'CONTENT_MANAGER'
} }
this.email = member.email this.email = member.email
@@ -519,7 +525,8 @@ export default {
if ( if (
(this.user_type === 'CREATOR' && this.member.userType === '크리에이터') || (this.user_type === 'CREATOR' && this.member.userType === '크리에이터') ||
(this.user_type === 'USER' && this.member.userType === '일반회원') || (this.user_type === 'USER' && this.member.userType === '일반회원') ||
(this.user_type === 'AGENT' && this.member.userType === '에이전트') (this.user_type === 'AGENT' && this.member.userType === '에이전트') ||
(this.user_type === 'CONTENT_MANAGER' && this.member.userType === '콘텐츠 관리자')
) { ) {
this.notifyError("변경사항이 없습니다.") this.notifyError("변경사항이 없습니다.")
} else { } else {