initial commit

This commit is contained in:
devwill1004-dotcom
2026-03-06 19:44:43 +08:00
commit 36dcd7d555
223 changed files with 69452 additions and 0 deletions

151
src/libs/auth-helper.js Normal file
View File

@@ -0,0 +1,151 @@
import Cookies from 'js-cookie'
import { AUTH_COOKIE, BOARD_COOKIE, LANG_COOKIE } from '@/libs/constants'
import store from '../store'
import { isMobile, parseJwt } from '@/libs/utils'
import { getToken } from '@/api/member'
import { subDays } from 'date-fns'
export function getAuthToken () {
const tokenStr = getAuthCookie()
if (tokenStr) {
return tokenStr
}
return null
}
export function setPopupCookie (item) {
const siteId = process.env.VUE_APP_SITE_ID || 'moka'
const name = siteId + '_popup_' + item.bannerIdx
const expires = subDays(new Date(), -1)
Cookies.set(name, 'Y', {
expires: expires,
path: '/'
})
}
export function getPopupCookie (name) {
return Cookies.get(name, {
path: '/'
})
}
export function setBoardCookie (value = 1) {
Cookies.set(BOARD_COOKIE.name, value, {
path: LANG_COOKIE.path,
domain: LANG_COOKIE.domain
})
}
export function getBoardCookie () {
return Cookies.get(BOARD_COOKIE.name, {
path: LANG_COOKIE.path,
domain: LANG_COOKIE.domain
})
}
export function setLangCookie (value = 1) {
document.body.classList = value
Cookies.set(LANG_COOKIE.name, value, {
path: LANG_COOKIE.path,
domain: LANG_COOKIE.domain
})
}
export function getLangCookie () {
return Cookies.get(LANG_COOKIE.name, {
path: LANG_COOKIE.path,
domain: LANG_COOKIE.domain
})
}
export function setAuthCookie (value = 1) {
Cookies.set(AUTH_COOKIE.name, value, {
expires: AUTH_COOKIE.expires,
path: AUTH_COOKIE.path,
domain: AUTH_COOKIE.domain
})
}
function removeAuthCookie () {
Cookies.remove(AUTH_COOKIE.name, {
path: AUTH_COOKIE.path,
domain: AUTH_COOKIE.domain
})
}
export function getAuthCookie () {
return Cookies.get(AUTH_COOKIE.name, {
path: AUTH_COOKIE.path,
domain: AUTH_COOKIE.domain
})
}
export function setAuthData (data) {
setAuthCookie(data.token)
}
export function removeAuthData () {
removeAuthCookie()
store.commit('setUserData', null)
store.commit('setPopupLogin', [])
}
export function getStoreData () {
return store.dispatch('storeUserData').then(userData => {
store.dispatch('storeCommonCode').then(commonCode => {
store.dispatch('storeCategoryCode').then(categoryCode => {
})
})
}).then(() => {
return true
}).catch(err => {
console.error(err)
return false
})
}
export function tokenCheck (force) {
const authToken = getAuthToken()
if (authToken) {
const parseToken = parseJwt(authToken)
const expireTime = Number(parseToken.exp + '000')
const currentTime = new Date().getTime()
const diffMinute = (expireTime - currentTime) / 1000 / 60
if (force || diffMinute <= 5) {
return getToken().then(response => {
const data = response.data
if (data.resultCode === '0') {
setAuthData(data.data)
return getStoreData()
} else {
removeAuthData()
if (isMobile()) {
this.goPageByName('mobileMain')
} else {
const prefix = location.pathname.split('/')[1]
const siteIdInfo = getSiteId(prefix)
if (!siteIdInfo || !siteIdInfo.siteId) {
location.href = '/' + prefix
}
}
}
})
} else {
return true
}
} else {
return false
}
}
export function getSiteId (prefix) {
const envKeyList = process.env[`VUE_APP_PREFIX_${prefix.toUpperCase()}`]
const siteId = envKeyList.split(',')[0]
const apiKey = envKeyList.split(',')[1]
const vendor = envKeyList.split(',')[2]
return { siteId: siteId, apiKey: apiKey, vendor: vendor }
}

181
src/libs/constants.js Normal file
View File

@@ -0,0 +1,181 @@
export const IS_PRODUCTION = process.env.NODE_ENV === 'production'
export const HTTP_HEADER_SKIP_ERROR = 'Winner-Skip-Error'
export const HTTP_STATUS = {
badRequest: 400,
unauthrized: 401,
unprocessableEntity: 422
}
export const STORAGE_ITEM = {
authToken: 'winner_auth_token'
}
export const AUTH_COOKIE = {
name: 'winner_auth_token',
expires: (1 / 1440 * process.env.VUE_APP_LOGIN_TIME) || (1 / 12),
path: '/'
}
export const LANG_COOKIE = {
name: 'winner_lang',
path: '/'
}
export const BOARD_COOKIE = {
name: 'winner_boardList',
path: '/'
}
// if (IS_PRODUCTION) {
// AUTH_COOKIE.domain = '.naver.com'
// }
export const GAME_CATEGORY = [
// { name: '전체', icon: require('@/assets/img/all.png'), value: 'all', use: true },
{ name: 'front.gnb.livecasino', icon: require('@/assets/img/live_casino.png'), value: 'casino', use: true },
{ name: 'front.gnb.slot', icon: require('@/assets/img/slot.png'), value: 'slot', use: true },
{ name: 'front.gnb.sport', icon: require('@/assets/img/sports.png'), value: 'sport', use: true },
{ name: 'front.gnb.minigame', icon: require('@/assets/img/minigame.png'), value: 'minigame', use: true }
// { name: 'e-스포츠', icon: require('@/assets/img/e_sports.png'), value: 'esport', use: true },
// { name: '가상게임', icon: require('@/assets/img/virtualgame.png'), value: 'kiron', use: true }
// { name: '피싱게임', icon: require('@/assets/img/fishinggame.png'), value: 'fishing', use: true }
// ,{ name: '로터리게임', icon: require('@/assets/img/rotary.png'), value: 'rotary', use: true }
]
export const GAME_DETAIL_INFO = {
evolution: 1,
biggaming: 2,
asiagaming: 5,
dreamgaming: 6,
sexygaming: 9,
pragmaticplay: 10,
playtech: 12,
hotelcasino: 14,
slot: 0,
pragmaticslot: 200,
hananero: 201,
elysium: 202,
fishing: 1000
}
export const SPORT_GAME_CATEGORY = [
{ value: 'all', name: '전체', use: true, default: true, img: require('@/assets/img/all.png') },
{ value: 'soccer', name: '축구', use: true, img: require('@/assets/img/sports.png') },
{ value: 'basketball', name: '농구', use: true, img: require('@/assets/img/basket.png') },
{ value: 'baseball', name: '야구', use: true, img: require('@/assets/img/base.png') },
{ value: 'volleyball', name: '배구', use: true, img: require('@/assets/img/volley.png') },
{ value: 'badminton', name: '배드민턴', use: true, img: require('@/assets/img/tennis.png') },
{ value: 'hockey', name: '하키', use: true, img: require('@/assets/img/hockey2.png') },
{ value: 'combat', name: '격투기', use: true, img: require('@/assets/img/betting.png') }
]
export const SPORT_GAME_CATEGORY2 = [
{ value: 'soccer', name: '축구', use: true, img: require('@/assets/img/sports.png'), imgs: true },
{ value: 'basketball', name: '농구', use: true, img: require('@/assets/img/basket.png'), imgs: true },
{ value: 'baseball', name: '야구', use: true, img: require('@/assets/img/base.png'), imgs: true },
{ value: 'volleyball', name: '배구', use: true, img: require('@/assets/img/volley.png'), imgs: true },
{ value: 'tennis', name: '테니스', use: true, img: require('@/assets/img/tennis.png'), imgs: true },
{ value: 'hockey', name: '하키', use: true, img: require('@/assets/img/hockey2.png'), imgs: true },
{ value: 'handball', name: '핸드볼', use: true, img: require('@/assets/img/handball.png'), imgs: true },
{ value: 'football', name: '미식축구', use: true, img: require('@/assets/img/rugby.png'), imgs: true },
{ value: 'esport', name: 'e-스포츠', use: true, img: require('@/assets/img/e_sports.png'), imgs: true }
]
export const DOCUMENT_TITLE_PREFIX = process.env.VUE_APP_TITLE || ''
export const CASH_STATUS = {
0: {
class: 'poss',
text: '신청'
},
1: {
class: 'blc',
text: '완료'
},
2: {
class: '',
text: '대기'
},
'-1': {
class: '',
text: '취소'
}
}
export const CASH_STATUS_MOBILE = {
0: {
class: 'poss',
text: '신청'
},
1: {
class: 'done',
text: '완료'
},
2: {
class: '',
text: '대기'
},
'-1': {
class: 'cancel',
text: '취소'
}
}
export const PARTNER_LEVEL_NAME = {
PTN_1: '대본',
PTN_2: '본사',
PTN_3: '부본',
PTN_4: '총판',
PTN_5: '매장',
NORMAL: '회원'
}
export const SOCKET_SERVER_URL = process.env.VUE_APP_WEB_SOCKET_URL || 'http://54.168.76.109/websocket'
export const SOCKET_SUBSCRIBE_DESTINATION = '/topic/'
export const SOCKET_POWERBALL_SUBSCRIBE_DESTINATION = '/topic/powerball/'
export const TRIPLE_GAME_LIST = {
}
export const NonIframeGameCode = [
'1',
'13' // bota
]
export const PARTNER_MOBILE_TABLE_SITE = [
'brown789'
]
export const SPORT_BRANCH_LIST = {
1: '축구',
2: '농구',
3: '미식축구',
6: '테니스',
7: '야구',
8: '아이스하키',
9: '스페셜',
10: '핸드볼',
14: 'Motor Racing',
17: 'Poker',
23: 'Hockey',
19: '배구',
34: '배드민턴',
43: 'MMA',
45: '수영',
64: 'E-스포츠',
218: '가상축구',
219: '가상농구',
220: '롤',
221: 'DOTA2',
222: 'CSGO',
0: '기타'
}
export const STATUS_LIST = {
Opened: '경기시작 전',
Draw: '무승부',
Won: '승리',
Lost: '패배'
}

30
src/libs/crypto.js Normal file
View File

@@ -0,0 +1,30 @@
import CryptoJS from 'crypto-js'
const key = process.env.VUE_APP_CRYPTO_KEY || '25354E6B712A2'
const sha = CryptoJS.SHA256(key)
export function encrypt (data) {
const iv = Math.random().toString(36).substring(2, 10) + Math.random().toString(36).substring(2, 10)
return iv + CryptoJS.AES.encrypt(JSON.stringify(data), sha, {
iv: CryptoJS.enc.Utf8.parse(iv),
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}).toString()
}
export function decrypt (data) {
const ivR = data.substring(0, 16)
const content = data.substring(16)
const result = CryptoJS.AES.decrypt(
content,
sha,
{
iv: CryptoJS.enc.Utf8.parse(ivR),
padding: CryptoJS.pad.Pkcs7
}
).toString(CryptoJS.enc.Utf8)
return JSON.parse(result)
}

114
src/libs/http-client.js Normal file
View File

@@ -0,0 +1,114 @@
import axios from 'axios'
import { getAuthToken } from '@/libs/auth-helper'
import { decrypt, encrypt } from '@/libs/crypto'
import store from '@/store'
let baseUrl = process.env.VUE_APP_API_BASE_URL
function isApiUrl (url) {
if (url.charAt(0) === '/') {
return true
}
return url.indexOf(baseUrl) === 0
}
const httpClient = axios.create({
baseURL: baseUrl
})
httpClient.interceptors.request.use(function (config) {
const siteIdInfo = store.getters.siteIdInfo
if (siteIdInfo && siteIdInfo.vendor) {
config.baseURL = process.env[`VUE_APP_API_BASE_URL_${siteIdInfo.vendor.toUpperCase()}`]
baseUrl = process.env[`VUE_APP_API_BASE_URL_${siteIdInfo.vendor.toUpperCase()}`]
}
if (isApiUrl(config.url)) {
if (config.method === 'get') {
if (!config.params) {
config.params = {}
}
config.params.t = new Date().getTime()
}
const siteId = siteIdInfo.siteId
config.data = { ...config.data, siteId: siteId }
// config.body = config.data
if (window.siteLogDataView) {
console.log(config.url + ' REQ : ', config.data)
}
config.data = encrypt(config.data)
config.headers = Object.assign(config.headers, {
// Authorization: 'ite1234567890abcdef'
Authorization: siteIdInfo.apiKey,
'Content-Type': 'application/json;charset=UTF-8',
Accept: '*/*'
})
const authToken = getAuthToken()
if (authToken) {
config.headers = Object.assign(config.headers, {
token: authToken
})
}
}
return config
}, function (error) {
return Promise.reject(error)
})
httpClient.interceptors.response.use(function (response) {
response.data = decrypt(response.data)
if (window.siteLogDataView) {
console.log(response.config.url + ' RES : ', response.data)
}
if (!isApiUrl(response.config.url) && !response.data.resultCode !== '0') {
const message = response.data.resultMessage || 'RESPONSE_FAILED'
const error = new Error(message)
error.isFailed = true
return Promise.reject(error)
} else {
response.headers['Content-Type'] = 'application/json'
return response
}
}, function (error) {
// let needAlert = true
if (window.__VUE_ROOT__) {
/// window.__VUE_ROOT__.$children[0].signOut()
} else {
// removeAuthData()
}
// router.push({ name: 'main' })
// if (error.config.headers[HTTP_HEADER_SKIP_ERROR]) {
// needAlert = false
// } else if (error.response && error.response.status) {
// const statusCode = error.response.status
//
// const authFailedStatusCodes = [
// HTTP_STATUS.unauthrized,
// HTTP_STATUS.unprocessableEntity
// ]
// if (authFailedStatusCodes.includes(statusCode)) {
// needAlert = false
// if (window.__VUE_ROOT__) {
// window.__VUE_ROOT__.$children[0].signOut()
// } else {
// removeAuthData()
// }
// router.push({ name: 'main' })
// } else if (statusCode === HTTP_STATUS.badRequest) {
// // to-do: what happened?
// }
// }
// if (needAlert) {
// error.isHandled = true
// store.commit('setErrorData', error)
// }
return Promise.reject(error)
})
export default httpClient

152
src/libs/utils.js Normal file
View File

@@ -0,0 +1,152 @@
import { format, subDays } from 'date-fns'
import MobileDetect from 'mobile-detect'
export function isValidUserId (value) {
const regType = /^[A-Za-z0-9+]{5,20}$/
return regType.test(value)
}
export function isValidPassword (value) {
const regType = /^[a-zA-Z0-9!@#$%*]{6,20}$/
return regType.test(value)
}
export function isValidPasswordPartner (value) {
const regType = /^[a-zA-Z0-9!@#$%*]{5,20}$/
return regType.test(value)
}
export function isValidOnlyNumber (value) {
const regType = /^[0-9]+$/
return regType.test(value)
}
export function isValidOnlyPhoneNumber (value) {
const regType = /^01([0|1|6|7|8|9])-?([0-9]{3,4})-?([0-9]{4})$/
return regType.test(value)
}
export function isPlainObject (value) {
return Object.prototype.toString.call(value) === '[object Object]'
}
export function isInteger (value) {
return typeof value === 'number' && isFinite(value) && Math.floor(value) === value
}
export function upperFirst (value) {
value = String(value)
if (!value.length) {
return value
}
return value.charAt(0).toUpperCase() + value.slice(1)
}
export function cloneDeep (data) {
return JSON.parse(JSON.stringify(data))
}
export function getPercentage (value, total, digits) {
if (isNaN(value) || isNaN(total) || total === 0) {
return 0
}
let result = value / total * 100
if (digits !== undefined) {
result = Number(result.toFixed(digits))
}
return result
}
export function getTimeString (value) {
const hour = Math.floor(value / 3600)
const minute = Math.floor(value / 60) % 60
const second = Math.round(value % 60)
if (hour >= 1) {
return `${hour}h ${minute}m ${second}s`
}
if (minute >= 1) {
return `${minute}m ${second}s`
}
return `${second}s`
}
export function getNumberWithOrdinal (n) {
const s = ['th', 'st', 'nd', 'rd']
const v = n % 100
return n + (s[(v - 20) % 10] || s[v] || s[0])
}
export function thousand (value, fixed = 0) {
value = Number(value)
return value.toLocaleString('en-US', { minimumFractionDigits: fixed, maximumFractionDigits: fixed })
}
export function leadingZero (number) {
return number < 10 ? '0' + number : number
}
export function capitalize (string) {
return string.charAt(0).toUpperCase() + string.slice(1)
}
export function getDateStr (value, defaultStr, type) {
if (!defaultStr) {
defaultStr = 'yyyy-MM-dd'
}
return format(value, defaultStr)
}
export function getDateStrKorean (value, defaultStr, type) {
if (!defaultStr) {
defaultStr = 'MM월 dd일'
}
return format(value, defaultStr)
}
export function getSubDaysDate (value, days) {
return subDays(value, days)
}
export function isMobile () {
const md = new MobileDetect(window.navigator.userAgent)
return md.mobile()
}
function b64DecodeUnicode (str) {
return decodeURIComponent(
Array.prototype.map.call(atob(str), c =>
'%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
).join(''))
}
export function parseJwt (token) {
return JSON.parse(
b64DecodeUnicode(
token.split('.')[1].replace('-', '+').replace('_', '/')
)
)
}
export function displayDateTime (dateStr, isUTC = false) {
const _dateStr = isUTC ? dateStr + 'z' : dateStr.replace('T', ' ')
const dateObject = new Date(_dateStr)
const year = dateObject.getFullYear()
const month = String(dateObject.getMonth() + 1).padStart(2, '0')
const day = String(dateObject.getDate()).padStart(2, '0')
const hour = String(dateObject.getHours()).padStart(2, '0')
const minute = String(dateObject.getMinutes()).padStart(2, '0')
const dateTimeString = `${year}-${month}-${day} ${hour}:${minute}`
return dateTimeString
}
export function replaceDateT (dateStr) {
const _dateStr = dateStr.replace('T', ' ')
return _dateStr
}