提交 f8a92a1f 作者: 施汉文

Merge branch 'release' into shw-feat-style

...@@ -16,8 +16,7 @@ ...@@ -16,8 +16,7 @@
<title>企微侧边栏</title> <title>企微侧边栏</title>
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0,shrink-to-fit=no,user-scalable=no"> --> <!-- <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0,shrink-to-fit=no,user-scalable=no"> -->
<script src="https://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script> <script src="https://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script>
<!-- iconpark CDN链接 --> <script src="https://lf1-cdn-tos.bytegoofy.com/obj/iconpark/svg_27278_173.e64d61edfe0d4824e2eeb0b7f478e568.js"></script>
<script src="https://lf1-cdn-tos.bytegoofy.com/obj/iconpark/icons_27278_172.4236cc17b47ad2f8ea4b21bbf191bb50.es5.js"></script>
</head> </head>
<body> <body>
<noscript> <noscript>
......
...@@ -95,6 +95,14 @@ ...@@ -95,6 +95,14 @@
</el-menu-item> </el-menu-item>
</el-menu> </el-menu>
</div> </div>
<<<<<<< HEAD =======
<!-- 绑定的 w 账号 -->
<bindUserList />
</div>
<div class="mobile-content">
<router-view></router-view>
>>>>>>> release
</div> </div>
</div> </div>
</template> </template>
...@@ -175,6 +183,11 @@ export default { ...@@ -175,6 +183,11 @@ export default {
icon: "gongnengicon-renwuliebiao", icon: "gongnengicon-renwuliebiao",
}, },
{ {
label: "用户待办",
path: "/userToDo",
hasRedDot: false, // 红点状态
},
{
label: "微言助手", label: "微言助手",
path: "/aiChat", path: "/aiChat",
icon: "gongnengicon-weiyanzhushou", icon: "gongnengicon-weiyanzhushou",
...@@ -197,7 +210,9 @@ export default { ...@@ -197,7 +210,9 @@ export default {
"client_online_status", "client_online_status",
"userid", "userid",
]), ]),
...mapState("game", ["taskData"]), // ...mapState("game", ["taskData"]),
// ...mapState("user", ["external_userid", "token", "userInfo"]),
...mapState("game", ["taskData", "accountSelect"]),
// 计算任务列表是否需要显示红点 // 计算任务列表是否需要显示红点
hasTaskRedDot() { hasTaskRedDot() {
return this.taskData.user_task > 0 || this.taskData.account_task > 0; return this.taskData.user_task > 0 || this.taskData.account_task > 0;
...@@ -258,7 +273,7 @@ export default { ...@@ -258,7 +273,7 @@ export default {
newVal, newVal,
window.location.href, window.location.href,
this.token, this.token,
Cookies.get("token") Cookies.get("token"),
); );
// 强制更新组件 // 强制更新组件
this.$forceUpdate(); this.$forceUpdate();
...@@ -279,6 +294,16 @@ export default { ...@@ -279,6 +294,16 @@ export default {
}, },
mounted() { mounted() {
// 页面刷新时从 Cookie 恢复 token 到 store // 页面刷新时从 Cookie 恢复 token 到 store
// Cookies.set(
// "token",
// "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOjQwOTAsImRhdGEiOnsiY3Nlcl9pZCI6NDA5MCwiY3Nlcl9uYW1lIjoi5q-b57uG5LqaIn0sImlhdCI6MTc2ODU0Mjk0MiwiZXhwIjoxNzcxMTM0OTQyLCJuYmYiOjE3Njg1NDI5NDIsInN1YiI6InRva2Vu6K6k6K-BIiwianRpIjoiMjU0Zjg3OGQ3NzMyNWUyMzMyNDAwZTEwZWJkMjFkY2YifQ.3hHc6iQP-Xkz9Q5rMIOFENDdh5P-NSaRs4Y4ffbJcMg"
// );
// Cookies.set("corp_id", "wweaefe716636df3d1");
// Cookies.set("userid", "maoxiya");
// Cookies.set("cser_name", "毛细亚");
// Cookies.set("external_userid", "wm5rUgMgAAG_vfF4AHClsrS1S6MImVsQ");
// Cookies.set("cser_id", 4090);
// Cookies.set("weixin_blongs_id", 2862);
const cookieToken = Cookies.get("token"); const cookieToken = Cookies.get("token");
if (cookieToken && !this.token) { if (cookieToken && !this.token) {
this.set_token(cookieToken); this.set_token(cookieToken);
......
...@@ -68,3 +68,19 @@ export function answerComment(data) { ...@@ -68,3 +68,19 @@ export function answerComment(data) {
data data
}) })
} }
// 会话生命线列表
export function sessionSummaryList(data) {
return request({
url: '/sidebar/client_session/sessionSummaryList',
method: 'post',
data
})
}
// 重新生成会话总结
export function regenerateSummary(data) {
return request({
url: '/sidebar/client_session/regenerateSummary',
method: 'post',
data
})
}
...@@ -1467,6 +1467,21 @@ export function sendEmail(data) { ...@@ -1467,6 +1467,21 @@ export function sendEmail(data) {
}) })
}) })
} }
// 获取种花道具列表
export function getPropList(data) {
return new Promise((resolve, reject) => {
cross_systemRequest({
system: 'zhangyou',
api: '/api/member/getPropData',
params: data
}).then((res) => {
resolve(res)
}).catch((error) => {
reject(error)
})
})
}
// 获取开/合服天数 // 获取开/合服天数
export function getServerDayApi(data) { export function getServerDayApi(data) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
...@@ -1481,6 +1496,20 @@ export function getServerDayApi(data) { ...@@ -1481,6 +1496,20 @@ export function getServerDayApi(data) {
}) })
}) })
} }
// 种花专属链接
export function getFlowerLink(data) {
return new Promise((resolve, reject) => {
cross_systemRequest({
system: 'zhangyou',
api: '/api/member/getPropUrl',
params: data
}).then((res) => {
resolve(res)
}).catch((error) => {
reject(error)
})
})
}
// 项目-视频分类 // 项目-视频分类
export function teachingVideoCategoryListApi(data) { export function teachingVideoCategoryListApi(data) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
...@@ -1509,3 +1538,61 @@ export function teachingVideoVideoListApi(data) { ...@@ -1509,3 +1538,61 @@ export function teachingVideoVideoListApi(data) {
}) })
}) })
} }
// 发送分身包
export function memberRegGameCloneLink(data) {
return new Promise((resolve, reject) => {
cross_systemRequest({
system: 'zhangyou',
api: '/api/member/memberRegGameCloneLink',
params: data
}).then((res) => {
resolve(res)
}).catch((error) => {
reject(error)
})
})
}
// 带教记录列表
export function roleTeachingList(data) {
return new Promise((resolve, reject) => {
cross_systemRequest({
system: 'zhangyou',
api: '/api/role/roleTeachingList',
params: data
}).then((res) => {
resolve(res)
}).catch((error) => {
reject(error)
})
})
}
// 新增带教
export function roleTeachingAdd(data) {
return new Promise((resolve, reject) => {
cross_systemRequest({
system: 'zhangyou',
api: '/api/role/roleTeachingAdd',
params: data
}).then((res) => {
resolve(res)
}).catch((error) => {
reject(error)
})
})
}
// 获取带教次数
export function roleTeachingNum(data) {
return new Promise((resolve, reject) => {
cross_systemRequest({
system: 'zhangyou',
api: '/api/role/roleTeachingNum',
params: data
}).then((res) => {
resolve(res)
}).catch((error) => {
reject(error)
})
})
}
...@@ -300,3 +300,35 @@ export function getMemberInfoApi(data) { ...@@ -300,3 +300,35 @@ export function getMemberInfoApi(data) {
data, data,
}); });
} }
// 角色礼包列表
export function getRoleSendingCodeList(data) {
return request({
url: returnApi('/corp_gift_package_list/getRoleSendingCodeList'),
method: 'post',
data,
});
}
// 跟进任务记录
export function corp_follow_up_task_index(data) {
return request({
url: returnApi('/corp_follow_up_task/index'),
method: 'post',
data
})
}
// 【智能待办】工作台-我的
export function corpIntelligentTaskMineList(data) {
return request({
url: returnApi('/corp_intelligent_task/mineList'),
method: 'post',
data
})
}
// 【智能待办】工作台-完成、未完成
export function corpIntelligentTaskExternalList(data) {
return request({
url: returnApi('/corp_intelligent_task/externalList'),
method: 'post',
data
})
}
\ No newline at end of file
<svg t="1765950660083" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5445" width="200" height="200"><path d="M512 938.666667C276.362667 938.666667 85.333333 747.637333 85.333333 512S276.362667 85.333333 512 85.333333s426.666667 191.029333 426.666667 426.666667-191.029333 426.666667-426.666667 426.666667z m0-64c200.298667 0 362.666667-162.368 362.666667-362.666667S712.298667 149.333333 512 149.333333 149.333333 311.701333 149.333333 512s162.368 362.666667 362.666667 362.666667z" p-id="5446"></path></svg>
\ No newline at end of file
<template> <template>
<div class="loading rowFlex allCenter"> <div class="loading rowFlex allCenter">
<svg-icon icon-class="loading" class="loadingIcon" /> <!-- <svg-icon icon-class="loading" class="loadingIcon" /> -->
<i class="el-icon-loading loadingIcon text-primary"></i>
<p class="text">加载中</p> <p class="text">加载中</p>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'loading', name: "loading",
data() { data() {
return { return {};
}
}, },
mounted() {}, mounted() {},
methods: {} methods: {},
} };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.loading{ .loading {
position: absolute; position: absolute;
left: 50%; left: 50%;
transform: translateX(-50%); transform: translateX(-50%);
top: 0; top: 0;
.loadingIcon{ .loadingIcon {
font-size: 24px; font-size: 24px;
animation: rotage linear 1s infinite; animation: rotage linear 1s infinite;
} }
.text{ .text {
color: #409EFF; color: #409eff;
font-size: 14px; font-size: 14px;
margin-left: 5px; margin-left: 5px;
} }
} }
@keyframes rotage { @keyframes rotage {
0%{ 0% {
transform: rotate(0deg); transform: rotate(0deg);
} }
100%{ 100% {
transform: rotate(360deg); transform: rotate(360deg);
} }
} }
</style> </style>
\ No newline at end of file
<template> <template>
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" /> <div
<svg v-else :class="svgClass" aria-hidden="true" :style="{ display: iconClass || svgName ? '' : 'none' }" v-if="isExternal"
v-on="$listeners"> :style="styleExternalIcon"
class="svg-external-icon svg-icon"
v-on="$listeners"
/>
<svg
v-else
:class="svgClass"
class="iconpark-icon"
aria-hidden="true"
:style="{ display: iconClass || svgName ? '' : 'none' }"
v-on="$listeners"
>
<use :xlink:href="iconName" /> <use :xlink:href="iconName" />
</svg> </svg>
</template> </template>
<script lang="jsx"> <script lang="jsx">
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage // doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
import { isExternal } from '@/utils/validate' import { isExternal } from "@/utils/validate";
export default { export default {
name: 'SvgIcon', name: "SvgIcon",
props: { props: {
iconClass: { iconClass: {
type: String, type: String,
default: '' default: "",
}, },
svgName: { svgName: {
type: String, type: String,
default: '' default: "",
}, },
className: { className: {
type: String, type: String,
default: '' default: "",
} },
}, },
computed: { computed: {
isExternal() { isExternal() {
return isExternal(this.iconClass) return isExternal(this.iconClass);
}, },
iconName() { iconName() {
if (this.svgName) { if (this.svgName) {
return `#${this.svgName}` return `#${this.svgName}`;
} }
return `#icon-${this.iconClass}` return `#icon-${this.iconClass}`;
}, },
svgClass() { svgClass() {
if (this.className) { if (this.className) {
return 'svg-icon ' + this.className return "svg-icon " + this.className;
} else { } else {
return 'svg-icon' return "svg-icon";
} }
}, },
styleExternalIcon() { styleExternalIcon() {
return { return {
mask: `url(${this.iconClass}) no-repeat 50% 50%`, mask: `url(${this.iconClass}) no-repeat 50% 50%`,
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%` "-webkit-mask": `url(${this.iconClass}) no-repeat 50% 50%`,
} };
} },
} },
} };
</script> </script>
<style scoped> <style scoped>
......
import Vue from 'vue' import Vue from 'vue'
{/* <iconpark-icon name="icon-fuzhi"></iconpark-icon> */} // {/* <iconpark-icon name="icon-fuzhi"></iconpark-icon> */}
const copy = { const copy = {
// 当被绑定的元素插入到DOM中时 // 当被绑定的元素插入到DOM中时
inserted: function(el, binding) { inserted: function(el, binding) {
// 创建复制图标元素 // 创建复制图标元素
const copyIcon = document.createElement('iconpark-icon') const copyIcon = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
copyIcon.innerHTML = '<use href="#icon-fuzhi"></use>'
// const copyIcon = document.createElement('div') copyIcon.setAttribute('class', 'iconpark-icon')
// copyIcon.setAttribute('icon-class', 'copy')
copyIcon.name='icon-fuzhi'
copyIcon.style.cursor = 'pointer' copyIcon.style.cursor = 'pointer'
copyIcon.style.marginLeft = '8px' copyIcon.style.marginLeft = '8px'
copyIcon.style.fontSize = '16px' copyIcon.style.height = '16px'
copyIcon.style.width = '16px'
copyIcon.title = '点击复制' copyIcon.title = '点击复制'
copyIcon.innerHTML='<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#a)"><mask id="b" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0" width="14" height="14"><path d="M14 0H0v14h14z" fill="#fff"/></mask><g mask="url(#b)" stroke="#267ef0" stroke-width=".875" stroke-linecap="round" stroke-linejoin="round"><path d="M9.333 7.525v2.45c0 2.042-.816 2.858-2.858 2.858h-2.45c-2.042 0-2.858-.816-2.858-2.858v-2.45c0-2.042.816-2.858 2.858-2.858h2.45c2.042 0 2.858.816 2.858 2.858"/><path d="M12.833 4.025v2.45c0 2.042-.816 2.858-2.858 2.858h-.642V7.525c0-2.042-.816-2.858-2.858-2.858H4.667v-.642c0-2.042.816-2.858 2.858-2.858h2.45c2.042 0 2.858.816 2.858 2.858"/></g></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h14v14H0z"/></clipPath></defs></svg>'
// 设置元素的position为relative,确保图标的absolute定位正确 // 设置元素的position为relative,确保图标的absolute定位正确
if (getComputedStyle(el).position === 'static') { if (getComputedStyle(el).position === 'static') {
...@@ -21,10 +19,10 @@ const copy = { ...@@ -21,10 +19,10 @@ const copy = {
} }
// 添加复制图标到元素后面 // 添加复制图标到元素后面
el.insertBefore(copyIcon, el.nextSibling) el.appendChild(copyIcon)
// 复制功能实现 // 复制功能实现
copyIcon.addEventListener('click', async function(e) { const clickHandler = async function(e) {
// 阻止事件冒泡 // 阻止事件冒泡
e.stopPropagation() e.stopPropagation()
try { try {
...@@ -65,7 +63,11 @@ const copy = { ...@@ -65,7 +63,11 @@ const copy = {
console.error('复制失败:', error) console.error('复制失败:', error)
Vue.prototype.$message.error('复制失败,请手动复制') Vue.prototype.$message.error('复制失败,请手动复制')
} }
}) }
copyIcon.addEventListener('click', clickHandler)
// 存储事件处理器引用,以便在unbind时正确移除
copyIcon.__clickHandler = clickHandler
// 存储图标引用,以便在组件卸载时清理 // 存储图标引用,以便在组件卸载时清理
el.__copyIcon = copyIcon el.__copyIcon = copyIcon
...@@ -75,11 +77,29 @@ const copy = { ...@@ -75,11 +77,29 @@ const copy = {
unbind: function(el) { unbind: function(el) {
// 清理事件监听器和元素 // 清理事件监听器和元素
if (el.__copyIcon) { if (el.__copyIcon) {
el.__copyIcon.removeEventListener('click', null) try {
el.parentNode.removeChild(el.__copyIcon) // 移除事件监听器
const clickHandler = el.__copyIcon.__clickHandler
if (clickHandler) {
el.__copyIcon.removeEventListener('click', clickHandler)
delete el.__copyIcon.__clickHandler
}
// 安全地移除图标元素
if (el.__copyIcon && el.__copyIcon.parentNode) {
el.__copyIcon.parentNode.removeChild(el.__copyIcon)
} else if (el.__copyIcon && el.__copyIcon.remove) {
// 如果节点还在DOM中,使用 remove() 方法
el.__copyIcon.remove()
}
} catch (error) {
// 忽略移除节点时的错误,可能节点已经被移除了
console.warn('移除复制图标时出错:', error)
} finally {
delete el.__copyIcon delete el.__copyIcon
} }
} }
}
} }
export default copy export default copy
\ No newline at end of file
...@@ -16,6 +16,7 @@ import taskList from '@/views/taskList.vue' ...@@ -16,6 +16,7 @@ import taskList from '@/views/taskList.vue'
import aiChat from '@/views/components/aiChat/aiChat.vue' import aiChat from '@/views/components/aiChat/aiChat.vue'
import Cookies from 'js-cookie' import Cookies from 'js-cookie'
import store from '@/store' import store from '@/store'
import UserAgency from '@/views/userAgency/index.vue'
Vue.use(VueRouter) Vue.use(VueRouter)
import { getParams } from '@/utils/index' import { getParams } from '@/utils/index'
const routes = [ const routes = [
...@@ -91,6 +92,11 @@ const routes = [ ...@@ -91,6 +92,11 @@ const routes = [
component: taskList component: taskList
}, },
{ {
path: '/userToDo',
name: 'userToDo',
component: UserAgency
},
{
path: '/aiChat', path: '/aiChat',
name: 'aiChat', name: 'aiChat',
component: aiChat component: aiChat
......
...@@ -25,24 +25,40 @@ ...@@ -25,24 +25,40 @@
</div> </div>
</template> </template>
<script> <script>
import AreaTransferApply from './components/ApplyRecords/AreaTransferApply.vue' import AreaTransferApply from "./components/ApplyRecords/AreaTransferApply.vue";
import errorHandle from './components/ApplyRecords/errorHandle.vue' import errorHandle from "./components/ApplyRecords/errorHandle.vue";
import TerminalTransfer from './components/ApplyRecords/TerminaTranfer.vue' import TerminalTransfer from "./components/ApplyRecords/TerminaTranfer.vue";
import report from './components/roleInfo/report.vue' import report from "./components/roleInfo/report.vue";
export default { export default {
name: 'applyRecord', name: "applyRecord",
components: { components: {
AreaTransferApply, AreaTransferApply,
errorHandle, errorHandle,
TerminalTransfer, TerminalTransfer,
report report,
}, },
data() { data() {
return { return {
activeTab: 'report' activeTab: "report",
} };
},
created() {
const related_task_info = JSON.parse(
sessionStorage.getItem("related_task_info")
);
if (related_task_info) {
const type = {
6: "report",
12: "errorHandle",
14: "serve",
13: "terminal",
};
this.activeTab = type[related_task_info.related_task_type] || "report";
} else {
this.activeTab = "report";
} }
} },
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
......
...@@ -2,99 +2,231 @@ ...@@ -2,99 +2,231 @@
<div class="terminaListArea" v-scroll="paperScroll"> <div class="terminaListArea" v-scroll="paperScroll">
<div class="addApply rowFlex spaceBetween"> <div class="addApply rowFlex spaceBetween">
<span></span> <span></span>
<el-button type="primary" size="small" icon="el-icon-plus" <el-button
@click="showaddAreaTransfer = true, areaTransferItem = {}">新增转区申请</el-button> type="primary"
size="small"
icon="el-icon-plus"
@click="(showaddAreaTransfer = true), (areaTransferItem = {})"
>新增转区申请</el-button
>
</div> </div>
<el-form ref="taskForm" :model="terminaForm" class="taskForm" label-position="top" label-width="85px"> <el-form
ref="taskForm"
:model="terminaForm"
class="taskForm"
label-position="top"
label-width="85px"
>
<el-form-item label="审批状态"> <el-form-item label="审批状态">
<el-select v-model="terminaForm.approval_status" style="width:95%;" clearable placeholder="请选择审批状态" <el-select
@change="filterChange"> v-model="terminaForm.approval_status"
<el-option v-for="item in approvalList" :key="item.value" :label="item.label" :value="item.value"> style="width: 95%"
clearable
placeholder="请选择审批状态"
@change="filterChange"
>
<el-option
v-for="item in approvalList"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="创建时间"> <el-form-item label="创建时间">
<selectDate :default-value="dateValue" :type="true" :no-clearable="true" style="width: 95%" <selectDate
@result="createResult" /> :default-value="dateValue"
:type="true"
:no-clearable="true"
style="width: 95%"
@result="createResult"
/>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div class="terminaListAreaList"> <div class="terminaListAreaList">
<!-- 举报申请 --> <!-- 举报申请 -->
<div class="scrollMain" v-if="terminaList.length > 0"> <div class="scrollMain" v-if="terminaList.length > 0">
<div v-for="(item, index) in terminaList" :key="item.id || index" class="terminaContent" <div
@click="terminaProcess(item, index)"> v-for="(item, index) in terminaList"
:key="item.id || index"
class="terminaContent"
@click="terminaProcess(item, index)"
>
<div class="terminaItem rowFlex spaceBetween columnCenter"> <div class="terminaItem rowFlex spaceBetween columnCenter">
<i :class="item.showStep ? 'el-icon-arrow-down' : 'el-icon-arrow-right'" class="svgicon"></i> <i
:class="
item.showStep ? 'el-icon-arrow-down' : 'el-icon-arrow-right'
"
class="svgicon"
></i>
<div class="terminaItemLeft"> <div class="terminaItemLeft">
<p><span class="label">新区角色:</span><span class="value">{{ item.role_name }}({{ item.server_name }})</span> <p>
<span class="label">新区角色:</span
><span class="value"
>{{ item.role_name }}({{ item.server_name }})</span
>
</p> </p>
<p><span class="label">老区角色:</span><span class="value">{{ item.old_role_name }} ({{ item.old_server_name
}}) </span></p>
<p> <p>
<span class="label">登记时间:</span><span class="value">{{ item.create_time || '' }}</span> <span class="label">老区角色:</span
><span class="value"
>{{ item.old_role_name }} ({{ item.old_server_name }})
</span>
</p>
<p>
<span class="label">登记时间:</span
><span class="value">{{ item.create_time || "" }}</span>
</p> </p>
</div> </div>
<div class="terminaItemRight columnFlex columnCenter"> <div class="terminaItemRight columnFlex columnCenter">
<el-button v-if="item.approval_status == 4 && item.related_request_id == 0" type="primary" size="mini" <el-button
style="margin-bottom:15px;" @click.stop="resubmitApproval(item)">重新提交</el-button> v-if="item.approval_status == 4 && item.related_request_id == 0"
type="primary"
size="mini"
style="margin-bottom: 15px"
@click.stop="resubmitApproval(item)"
>重新提交</el-button
>
<!-- 改成 svg-icon 图标 --> <!-- 改成 svg-icon 图标 -->
<svg-icon v-if="item.approval_status == 1" icon-class="shenpi1" class="icon" /> <svg-icon
<svg-icon v-else-if="item.approval_status == 2" icon-class="shenpi2" class="icon" /> v-if="item.approval_status == 1"
<svg-icon v-else-if="item.approval_status == 3" icon-class="shenpi3" class="icon" /> icon-class="shenpi1"
<svg-icon v-else-if="item.approval_status == 4" icon-class="shenpi4" class="icon" /> class="icon"
<svg-icon v-else-if="item.approval_status == 5" icon-class="shenpi5" class="icon" /> />
<svg-icon
v-else-if="item.approval_status == 2"
icon-class="shenpi2"
class="icon"
/>
<svg-icon
v-else-if="item.approval_status == 3"
icon-class="shenpi3"
class="icon"
/>
<svg-icon
v-else-if="item.approval_status == 4"
icon-class="shenpi4"
class="icon"
/>
<svg-icon
v-else-if="item.approval_status == 5"
icon-class="shenpi5"
class="icon"
/>
</div> </div>
</div> </div>
<!-- 审批进度 --> <!-- 审批进度 -->
<el-collapse-transition> <el-collapse-transition>
<div v-if="item.showStep" class="terminaProcessList"> <div v-if="item.showStep" class="terminaProcessList">
<el-steps direction="vertical" :active="item.current" finish-status="success"> <el-steps
<el-step v-for="(items, indexs) in item.terminaProcessList" :key="'trans_item_' + indexs" direction="vertical"
:title="items.node_name"> :active="item.current"
finish-status="success"
>
<el-step
v-for="(items, indexs) in item.terminaProcessList"
:key="'trans_item_' + indexs"
:title="items.node_name"
>
<template slot="description"> <template slot="description">
<div v-if="items" class="trans-follow-1 card-style"> <div v-if="items" class="trans-follow-1 card-style">
<div class="follow-item"> <div class="follow-item">
<span class="follow-info-label label-font"> <span class="follow-info-label label-font">
{{ items.node_sort !== '0' ? '审批人:' : '登记人:' }} {{ items.node_sort !== "0" ? "审批人:" : "登记人:" }}
</span> </span>
<span class="info-value value-font"> <span class="info-value value-font">
{{ Array.isArray(items.user_name) ? items.user_name[0] : items.user_name }} {{
Array.isArray(items.user_name)
? items.user_name[0]
: items.user_name
}}
</span> </span>
<el-tooltip v-if="Array.isArray(items.user_name) && items.user_name.length > 1" class="item" <el-tooltip
effect="dark" :content="items.user_name.slice(1).join('、')" placement="top"> v-if="
Array.isArray(items.user_name) &&
items.user_name.length > 1
"
class="item"
effect="dark"
:content="items.user_name.slice(1).join('、')"
placement="top"
>
<span class="info-value value-font info-value-color"> <span class="info-value value-font info-value-color">
{{ `+${items.user_name.length - 1}` }} {{ `+${items.user_name.length - 1}` }}
</span> </span>
</el-tooltip> </el-tooltip>
</div> </div>
<div v-if="items.node_sort !== '0' || items.node_name === '系统'" class="follow-item"> <div
v-if="
items.node_sort !== '0' || items.node_name === '系统'
"
class="follow-item"
>
<span class="follow-info-label label-font"> <span class="follow-info-label label-font">
审批结果: 审批结果:
</span> </span>
<span class="info-value value-font" <span
:class="items.current < indexs ? '' : switchStateTag(items.approval_result)"> class="info-value value-font"
{{ items.current < indexs ? '' : items.approval_result_text }} </span> :class="
items.current < indexs
? ''
: switchStateTag(items.approval_result)
"
>
{{
items.current < indexs
? ""
: items.approval_result_text
}}
</span>
</div> </div>
<div class="follow-item"> <div class="follow-item">
<span class="follow-info-label label-font"> <span class="follow-info-label label-font">
{{ items.node_sort !== '0' || items.node_name === '系统' ? '审批时间:' : '登记时间:' }} {{
items.node_sort !== "0" ||
items.node_name === "系统"
? "审批时间:"
: "登记时间:"
}}
</span> </span>
<span class="info-value value-font"> <span class="info-value value-font">
{{ items.node_sort === '0' ? items.create_time : items.update_time }} {{
items.node_sort === "0"
? items.create_time
: items.update_time
}}
</span> </span>
</div> </div>
<div v-if="(items.node_sort !== '0' || items.node_name === '系统') && items.approval_result === '2'" <div
class="follow-item"> v-if="
(items.node_sort !== '0' ||
items.node_name === '系统') &&
items.approval_result === '2'
"
class="follow-item"
>
<span class="follow-info-label label-font"> <span class="follow-info-label label-font">
驳回原因: 驳回原因:
</span> </span>
<span class="info-value value-font" v-html="items.extra_attribution.approval_remark || ''"> <span
class="info-value value-font"
v-html="items.extra_attribution.approval_remark || ''"
>
</span> </span>
</div> </div>
<div <div
v-if="items.node_sort === item.terminaProcessList[item.terminaProcessList.length - 1].node_sort + '' && items.approval_result === '1' && items.node_sort !== '0'" v-if="
class="follow-item-remark follow-item"> items.node_sort ===
item.terminaProcessList[
item.terminaProcessList.length - 1
].node_sort +
'' &&
items.approval_result === '1' &&
items.node_sort !== '0'
"
class="follow-item-remark follow-item"
>
<span class="follow-info-label label-font"> <span class="follow-info-label label-font">
处理结果: 处理结果:
</span> </span>
...@@ -102,18 +234,37 @@ ...@@ -102,18 +234,37 @@
{{ items.extra_attribution.banned_text }} {{ items.extra_attribution.banned_text }}
</span> </span>
</div> </div>
<div v-if="items.node_name !== '系统' && items.extra_attribution && items.extra_attribution.remark" <div
class="info-item-remark"> v-if="
<div style="display: flex;"> items.node_name !== '系统' &&
items.extra_attribution &&
items.extra_attribution.remark
"
class="info-item-remark"
>
<div style="display: flex">
<span class="info-label remark-label">详情:</span> <span class="info-label remark-label">详情:</span>
<span class="preview-btn" @click.stop="previewRemark(items.extra_attribution.remark)"> <span
class="preview-btn"
@click.stop="
previewRemark(items.extra_attribution.remark)
"
>
<i class="el-icon-view"></i> <i class="el-icon-view"></i>
点击查看大图 点击查看大图
</span> </span>
</div> </div>
<div class="remark-value" <div
v-html="formatImg(items.extra_attribution && items.extra_attribution.remark ? items.extra_attribution.remark : '')"> class="remark-value"
</div> v-html="
formatImg(
items.extra_attribution &&
items.extra_attribution.remark
? items.extra_attribution.remark
: '',
)
"
></div>
</div> </div>
</div> </div>
</template> </template>
...@@ -125,66 +276,79 @@ ...@@ -125,66 +276,79 @@
</div> </div>
<noContent v-else /> <noContent v-else />
</div> </div>
<el-dialog :visible.sync="dialogRemarkVisible" append-to-body title="查看大图" custom-class="remake-dialog"> <el-dialog
:visible.sync="dialogRemarkVisible"
append-to-body
title="查看大图"
custom-class="remake-dialog"
>
<div class="remake-box"> <div class="remake-box">
<div v-html="dialogRemake"></div> <div v-html="dialogRemake"></div>
</div> </div>
</el-dialog> </el-dialog>
<!-- 编辑误操作 --> <!-- 编辑误操作 -->
<AreaTransferDialog v-if="showaddAreaTransfer" :visible.sync="showaddAreaTransfer" <AreaTransferDialog
:area-transfer-item="areaTransferItem" @updateList="updateList" /> v-if="showaddAreaTransfer"
:visible.sync="showaddAreaTransfer"
:area-transfer-item="areaTransferItem"
@updateList="updateList"
/>
</div> </div>
</template> </template>
<script> <script>
import { searchcondition, transfer_server_request_list, transfer_server_request_process } from '@/api/game' import {
import { mapState } from 'vuex' searchcondition,
import { removeDp, formatNumber, debounce } from '@/utils/index' transfer_server_request_list,
import AreaTransferDialog from './AreaTransferDialog.vue' transfer_server_request_process,
import selectDate from '@/components/selectDate.vue' } from "@/api/game";
import { mapState } from "vuex";
import { removeDp, formatNumber, debounce } from "@/utils/index";
import AreaTransferDialog from "./AreaTransferDialog.vue";
import selectDate from "@/components/selectDate.vue";
// 导入审批状态图标 // 导入审批状态图标
import shenpi1 from '@/assets/icon/svg/shenpi1.svg' import shenpi1 from "@/assets/icon/svg/shenpi1.svg";
import shenpi2 from '@/assets/icon/svg/shenpi2.svg' import shenpi2 from "@/assets/icon/svg/shenpi2.svg";
import shenpi3 from '@/assets/icon/svg/shenpi3.svg' import shenpi3 from "@/assets/icon/svg/shenpi3.svg";
import shenpi4 from '@/assets/icon/svg/shenpi4.svg' import shenpi4 from "@/assets/icon/svg/shenpi4.svg";
import shenpi5 from '@/assets/icon/svg/shenpi5.svg' import shenpi5 from "@/assets/icon/svg/shenpi5.svg";
import noContent from '@/components/noContent.vue' import noContent from "@/components/noContent.vue";
export default { export default {
name: 'AreaTransferApply', name: "AreaTransferApply",
computed: { computed: {
...mapState('game', ['accountSelect']), ...mapState("game", ["accountSelect"]),
...mapState('user', ['userInfo']) ...mapState("user", ["userInfo"]),
}, },
components: { components: {
AreaTransferDialog, AreaTransferDialog,
selectDate, selectDate,
noContent noContent,
}, },
data() { data() {
return { return {
pickerOptions: { pickerOptions: {
disabledDate(time) { disabledDate(time) {
const curDate = (new Date()).getTime() const curDate = new Date().getTime();
const three = 90 * 24 * 3600 * 1000 const three = 90 * 24 * 3600 * 1000;
const threeMonths = curDate - three const threeMonths = curDate - three;
return time.getTime() > Date.now() || time.getTime() < threeMonths return time.getTime() > Date.now() || time.getTime() < threeMonths;
} },
}, },
terminaForm: { terminaForm: {
member_id: '', member_id: "",
create_time_start: '', create_time_start: "",
create_time_end: '', create_time_end: "",
approval_status: '' approval_status: "",
}, },
dateValue: [], dateValue: [],
pageInfo: { pageInfo: {
page: 1, page: 1,
page_size: 20 page_size: 20,
}, },
terminaList: [], terminaList: [],
isMoreRecord: false, isMoreRecord: false,
approvalList: [], approvalList: [],
dialogRemarkVisible: false, dialogRemarkVisible: false,
dialogRemake: '', dialogRemake: "",
showaddAreaTransfer: false, showaddAreaTransfer: false,
formatNumber: formatNumber, formatNumber: formatNumber,
// 审批状态图标 // 审批状态图标
...@@ -192,173 +356,202 @@ export default { ...@@ -192,173 +356,202 @@ export default {
shenpi2, shenpi2,
shenpi3, shenpi3,
shenpi4, shenpi4,
shenpi5 shenpi5,
} };
}, },
watch: { watch: {
accountSelect(newVal, oldVal) { accountSelect(newVal, oldVal) {
console.log(newVal, 'newVal') console.log(newVal, "newVal");
if (newVal && newVal !== '') { if (newVal && newVal !== "") {
this.pageInfo = { this.pageInfo = {
page: 0, page: 0,
page_size: 20, page_size: 20,
total: 0 total: 0,
} };
this.isMoreRecord = true this.isMoreRecord = true;
this.filterChange() this.filterChange();
}
} }
}, },
},
mounted() { mounted() {
this.dateValue = [ this.dateValue = [
this.$moment().subtract(6, 'days').format('YYYY-MM-DD HH:mm:ss'), this.$moment().subtract(6, "days").format("YYYY-MM-DD HH:mm:ss"),
this.$moment().format('YYYY-MM-DD HH:mm:ss') this.$moment().format("YYYY-MM-DD HH:mm:ss"),
] ];
this.terminaForm.create_time_start = this.dateValue[0] this.terminaForm.create_time_start = this.dateValue[0];
this.terminaForm.create_time_end = this.dateValue[1] this.terminaForm.create_time_end = this.dateValue[1];
this.requstApprovalList() this.requstApprovalList();
this.filterChange() this.filterChange();
}, },
methods: { methods: {
updateList() { updateList() {
this.filterChange() this.filterChange();
}, },
createResult: debounce(function (data) { createResult: debounce(function (data) {
if (data && Array.isArray(data) && data.length === 2) { if (data && Array.isArray(data) && data.length === 2) {
this.terminaForm.create_time_start = data[0] this.terminaForm.create_time_start = data[0];
this.terminaForm.create_time_end = data[1] this.terminaForm.create_time_end = data[1];
this.dateValue = data this.dateValue = data;
} else { } else {
this.terminaForm.create_time_start = '' this.terminaForm.create_time_start = "";
this.terminaForm.create_time_end = '' this.terminaForm.create_time_end = "";
this.dateValue = [] this.dateValue = [];
} }
this.filterChange() this.filterChange();
}, 300), }, 300),
filterChange() { filterChange() {
this.pageInfo.page = 1 this.pageInfo.page = 1;
this.terminaList = [] this.terminaList = [];
this.isMoreRecord = true this.isMoreRecord = true;
this.terminaIndex() this.terminaIndex();
}, },
resubmitApproval(item) { resubmitApproval(item) {
this.showaddAreaTransfer = true this.showaddAreaTransfer = true;
this.areaTransferItem = item this.areaTransferItem = item;
}, },
async requstApprovalList() { async requstApprovalList() {
const data = { const data = {
type: 'dictionaries', type: "dictionaries",
table_name: 'zs_refund_request', table_name: "zs_refund_request",
field_name: 'approval_status' field_name: "approval_status",
} };
const res = await searchcondition(data) const res = await searchcondition(data);
if (res.status_code === 1) { if (res.status_code === 1) {
this.approvalList = res.data.data this.approvalList = res.data.data;
} }
}, },
previewRemark(remark) { previewRemark(remark) {
this.dialogRemake = remark this.dialogRemake = remark;
this.dialogRemarkVisible = true this.dialogRemarkVisible = true;
}, },
async terminaProcess(item, index) { async terminaProcess(item, index) {
item.showStep = !item.showStep item.showStep = !item.showStep;
if (item.terminaProcessList.length === 0) { if (item.terminaProcessList.length === 0) {
try { try {
const res = await transfer_server_request_process({ id: item.id }) const res = await transfer_server_request_process({ id: item.id });
item.terminaProcessList = res.data.data item.terminaProcessList = res.data.data;
res.data.data.map((items) => { res.data.data.map((items) => {
if (items.approval_result !== '0' && items.approval_result !== '2') { if (
item.current += 1 items.approval_result !== "0" &&
items.approval_result !== "2"
) {
item.current += 1;
} }
}) });
} catch (error) { } catch (error) {
this.$message.error('获取审批进度失败') this.$message.error("获取审批进度失败");
console.error(error) console.error(error);
} }
} }
this.$forceUpdate() this.$forceUpdate();
}, },
paperScroll() { paperScroll() {
if (!this.isMoreRecord) { if (!this.isMoreRecord) {
console.log('没有更多数据了') console.log("没有更多数据了");
return false return false;
} }
this.requestNextPage() this.requestNextPage();
}, },
requestNextPage(pageInfo) { requestNextPage(pageInfo) {
this.pageInfo.page++ this.pageInfo.page++;
this.terminaIndex() this.terminaIndex();
}, },
handleCurrentChange(val) { handleCurrentChange(val) {
this.pageInfo.page = val this.pageInfo.page = val;
}, },
switchStateTag(status) { switchStateTag(status) {
switch (status) { switch (status) {
case '0': case "0":
return 'unhandle' return "unhandle";
case '1': case "1":
return 'handled' return "handled";
case '2': case "2":
return 'sendFail' return "sendFail";
default: default:
return '' return "";
} }
}, },
formatImg(html) { formatImg(html) {
if (html) { if (html) {
return html.replaceAll(/<img/g, '<img style="max-width:100px;"') return html.replaceAll(/<img/g, '<img style="max-width:100px;"');
} }
return html return html;
}, },
switchStateText(status) { switchStateText(status) {
switch (status) { switch (status) {
case '0': case "0":
return '待审批' return "待审批";
case '1': case "1":
return '通过' return "通过";
case '2': case "2":
return '驳回' return "驳回";
} }
}, },
async terminaIndex() { async terminaIndex() {
if (this.accountSelect === '') { if (this.accountSelect === "") {
this.$message.warning('暂无关联的账号,请先去关联账号!') this.$message.warning("暂无关联的账号,请先去关联账号!");
return false return false;
} }
if (this.pageInfo.page === 1) { if (this.pageInfo.page === 1) {
this.terminaList = [] this.terminaList = [];
} }
const { create_time_start, create_time_end, approval_status } = this.terminaForm const { create_time_start, create_time_end, approval_status } =
const data = { this.terminaForm;
// const data = {
// approval_status,
// create_time_start,
// create_time_end,
// member_id: this.accountSelect,
// ...this.pageInfo
// }
const related_task_info = JSON.parse(
sessionStorage.getItem("related_task_info"),
);
let data;
if (related_task_info && related_task_info.related_task_type === 14) {
data = { ...this.pageInfo, id: related_task_info.related_task_id };
this.terminaForm.create_time_start = "";
this.terminaForm.create_time_end = "";
this.dateValue = [];
//展示一次后清除携带过来的id
this.$nextTick(() => {
setTimeout(() => {
sessionStorage.removeItem("related_task_info");
}, 200);
});
} else {
data = {
approval_status, approval_status,
create_time_start, create_time_start,
create_time_end, create_time_end,
member_id: this.accountSelect, member_id: this.accountSelect,
...this.pageInfo ...this.pageInfo,
};
} }
const res = await transfer_server_request_list(data) const res = await transfer_server_request_list(data);
if (this.pageInfo.page === 1) { if (this.pageInfo.page === 1) {
this.terminaList = res.data.data this.terminaList = res.data.data;
} else { } else {
this.terminaList = this.terminaList.concat(res.data.data) this.terminaList = this.terminaList.concat(res.data.data);
} }
if (this.terminaList.length > 0) { if (this.terminaList.length > 0) {
this.terminaList.map((item) => { this.terminaList.map((item) => {
item.showStep = false item.showStep = false;
item.current = 0 item.current = 0;
item.terminaProcessList = [] item.terminaProcessList = [];
}) });
} else { } else {
this.terminaList = [] this.terminaList = [];
} }
if (res.data.data.length < 20) { if (res.data.data.length < 20) {
this.isMoreRecord = false this.isMoreRecord = false;
} else { } else {
this.isMoreRecord = true this.isMoreRecord = true;
}
}
} }
} },
},
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
...@@ -408,7 +601,7 @@ export default { ...@@ -408,7 +601,7 @@ export default {
font-size: 12px; font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC; font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400; font-weight: 400;
color: #409EFF; color: #409eff;
border: none; border: none;
} }
...@@ -543,30 +736,30 @@ export default { ...@@ -543,30 +736,30 @@ export default {
width: 1px; width: 1px;
} }
::v-deep .el-step>.is-success { ::v-deep .el-step > .is-success {
color: #409EFF; color: #409eff;
border-color: #409EFF; border-color: #409eff;
.el-step__line { .el-step__line {
background-color: #e5e6eb; background-color: #e5e6eb;
} }
} }
::v-deep .el-step__main>.is-success { ::v-deep .el-step__main > .is-success {
color: #409EFF; color: #409eff;
} }
::v-deep .el-step>.is-process { ::v-deep .el-step > .is-process {
color: #409EFF; color: #409eff;
border-color: #409EFF; border-color: #409eff;
.el-step__line { .el-step__line {
background-color: #e5e6eb; background-color: #e5e6eb;
} }
} }
::v-deep .el-step__main>.is-process { ::v-deep .el-step__main > .is-process {
color: #409EFF; color: #409eff;
} }
.form-item-btn { .form-item-btn {
...@@ -587,7 +780,7 @@ export default { ...@@ -587,7 +780,7 @@ export default {
.preview-btn { .preview-btn {
cursor: pointer; cursor: pointer;
font-size: 14px; font-size: 14px;
color: #409EFF; color: #409eff;
margin: 0 0 0 10px; margin: 0 0 0 10px;
i { i {
...@@ -691,7 +884,7 @@ export default { ...@@ -691,7 +884,7 @@ export default {
height: 80px; height: 80px;
} }
&:hover>.preview-pic { &:hover > .preview-pic {
z-index: 100; z-index: 100;
} }
} }
...@@ -743,7 +936,7 @@ export default { ...@@ -743,7 +936,7 @@ export default {
} }
.info-value-color { .info-value-color {
color: #409EFF; color: #409eff;
margin-left: 5px; margin-left: 5px;
} }
} }
......
...@@ -2,82 +2,177 @@ ...@@ -2,82 +2,177 @@
<div class="terminaListContent" v-scroll="paperScroll"> <div class="terminaListContent" v-scroll="paperScroll">
<div class="addApply rowFlex spaceBetween"> <div class="addApply rowFlex spaceBetween">
<span></span> <span></span>
<el-button type="primary" icon="el-icon-plus" size="small" <el-button
@click="(showaddAreaTransfer = true, areaTransferItem = {})">新增转端申请</el-button> type="primary"
icon="el-icon-plus"
size="small"
@click="(showaddAreaTransfer = true), (areaTransferItem = {})"
>新增转端申请</el-button
>
</div> </div>
<el-form ref="taskForm" :model="terminaForm" label-position="top" class="terminaListForm" label-width="85px"> <el-form
ref="taskForm"
:model="terminaForm"
label-position="top"
class="terminaListForm"
label-width="85px"
>
<el-form-item label="审批状态"> <el-form-item label="审批状态">
<el-select v-model="terminaForm.approval_status" style="width:95%;" clearable placeholder="请选择审批状态" <el-select
@change="filterChange"> v-model="terminaForm.approval_status"
<el-option v-for="item in approvalList" :key="item.value" :label="item.label" :value="item.value"> style="width: 95%"
clearable
placeholder="请选择审批状态"
@change="filterChange"
>
<el-option
v-for="item in approvalList"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="创建时间"> <el-form-item label="创建时间">
<selectDate :default-value="dateValue" :type="true" style="width: 95%" @result="createResult" /> <selectDate
:default-value="dateValue"
:type="true"
style="width: 95%"
@result="createResult"
/>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div class="terminaListContentList"> <div class="terminaListContentList">
<!-- 举报申请 --> <!-- 举报申请 -->
<div v-if="terminaList.length > 0" class="scrollMain"> <div v-if="terminaList.length > 0" class="scrollMain">
<div v-for="(item, index) in terminaList" :key="index" class="terminaContent" <div
@click="terminaProcess(item, index)"> v-for="(item, index) in terminaList"
<div class="terminaItem rowFlex spaceBetween columnCenter"> :key="index"
class="terminaContent"
@click="terminaProcess(item, index)"
>
<div class="terminaItem columnFlex spaceBetween columnCenter">
<div class="terminaItemLeft"> <div class="terminaItemLeft">
<p><span class="label">角色名称:</span><span class="value">{{ item.role_name }}</span></p>
<p> <p>
<span class="label">累计充值:</span><span class="value">{{ formatNumber(item.recharge_total_amount) }} <span class="label">角色名称:</span
</span> ><span class="value">{{ item.role_name }}</span>
</p>
<p>
<span class="label">累计充值:</span
><span class="value"
>{{ formatNumber(item.recharge_total_amount) }}</span
>
</p> </p>
<p> <p>
<span class="label">登记时间:</span><span class="value">{{ item.create_time || '' }}</span> <span class="label">登记时间:</span
><span class="value">{{ item.create_time || "" }}</span>
</p> </p>
<p><span class="label">转端状态:</span><span class="value">{{ item.trans_check_status_text || '-' }}</span> <p>
<span class="label">转端状态:</span
><span class="value">{{
item.trans_check_status_text || "-"
}}</span>
</p> </p>
</div> </div>
<!-- 审批进度 --> <!-- 审批进度 -->
<el-collapse-transition> <el-collapse-transition>
<div v-if="item.showStep" class="terminaProcessList"> <div v-if="item.showStep" class="terminaProcessList">
<el-steps direction="vertical" :active="item.current" finish-status="success"> <el-steps
<el-step v-for="(items, indexs) in item.terminaProcessList" :key="'trans_item_' + indexs" direction="vertical"
:title="items.node_name"> :active="item.current"
finish-status="success"
>
<el-step
v-for="(items, indexs) in item.terminaProcessList"
:key="'trans_item_' + indexs"
:title="items.node_name"
>
<template slot="description"> <template slot="description">
<div v-if="items" class="trans-follow-1 card-style"> <div v-if="items" class="trans-follow-1 card-style">
<div class="follow-item"> <div class="follow-item">
<span class="follow-info-label label-font"> <span class="follow-info-label label-font">
{{ items.node_sort !== '0' ? '审批人:' : '登记人:' }} {{
items.node_sort !== "0" ? "审批人:" : "登记人:"
}}
</span> </span>
<span class="info-value value-font"> <span class="info-value value-font">
{{ Array.isArray(items.user_name) ? items.user_name[0] : items.user_name }} {{
Array.isArray(items.user_name)
? items.user_name[0]
: items.user_name
}}
</span> </span>
<el-tooltip v-if="Array.isArray(items.user_name) && items.user_name.length > 1" class="item" <el-tooltip
effect="dark" :content="items.user_name.slice(1).join('、')" placement="top"> v-if="
<span class="info-value value-font info-value-color"> Array.isArray(items.user_name) &&
items.user_name.length > 1
"
class="item"
effect="dark"
:content="items.user_name.slice(1).join('、')"
placement="top"
>
<span
class="info-value value-font info-value-color"
>
{{ `+${items.user_name.length - 1}` }} {{ `+${items.user_name.length - 1}` }}
</span> </span>
</el-tooltip> </el-tooltip>
</div> </div>
<div v-if="items.node_sort !== '0' || items.node_name === '系统'" class="follow-item"> <div
v-if="
items.node_sort !== '0' ||
items.node_name === '系统'
"
class="follow-item"
>
<span class="follow-info-label label-font"> <span class="follow-info-label label-font">
审批结果: 审批结果:
</span> </span>
<span class="info-value value-font" <span
:class="items.current < indexs ? '' : switchStateTag(items.approval_result)"> class="info-value value-font"
{{ items.current < indexs ? '' : items.approval_result_text == '通过' ? '完成' : :class="
items.approval_result_text }} </span> items.current < indexs
? ''
: switchStateTag(items.approval_result)
"
>
{{
items.current < indexs
? ""
: items.approval_result_text == "通过"
? "完成"
: items.approval_result_text
}}
</span>
</div> </div>
<div class="follow-item"> <div class="follow-item">
<span class="follow-info-label label-font"> <span class="follow-info-label label-font">
{{ items.node_sort !== '0' || items.node_name === '系统' ? '审批时间:' : '登记时间:' }} {{
items.node_sort !== "0" ||
items.node_name === "系统"
? "审批时间:"
: "登记时间:"
}}
</span> </span>
<span class="info-value value-font"> <span class="info-value value-font">
{{ items.node_sort === '0' ? items.create_time : items.update_time }} {{
items.node_sort === "0"
? items.create_time
: items.update_time
}}
</span> </span>
</div> </div>
<div <div
v-if="(items.node_sort !== '0' || items.node_name === '系统') && items.approval_result === '2'" v-if="
class="follow-item"> (items.node_sort !== '0' ||
items.node_name === '系统') &&
items.approval_result === '2'
"
class="follow-item"
>
<span class="follow-info-label label-font"> <span class="follow-info-label label-font">
驳回原因: 驳回原因:
</span> </span>
...@@ -87,8 +182,17 @@ ...@@ -87,8 +182,17 @@
</div> </div>
<div <div
v-if="items.node_sort === item.terminaProcessList[item.terminaProcessList.length - 1].node_sort + '' && items.approval_result === '1' && items.node_sort !== '0'" v-if="
class="follow-item-remark follow-item"> items.node_sort ===
item.terminaProcessList[
item.terminaProcessList.length - 1
].node_sort +
'' &&
items.approval_result === '1' &&
items.node_sort !== '0'
"
class="follow-item-remark follow-item"
>
<span class="follow-info-label label-font"> <span class="follow-info-label label-font">
处理结果: 处理结果:
</span> </span>
...@@ -97,18 +201,36 @@ ...@@ -97,18 +201,36 @@
</span> </span>
</div> </div>
<div <div
v-if="items.node_name !== '系统' && items.extra_attribution && items.extra_attribution.remark" v-if="
class="info-item-remark"> items.node_name !== '系统' &&
<div style="display: flex;"> items.extra_attribution &&
items.extra_attribution.remark
"
class="info-item-remark"
>
<div style="display: flex">
<span class="info-label remark-label">详情:</span> <span class="info-label remark-label">详情:</span>
<span class="preview-btn" @click.stop="previewRemark(items.extra_attribution.remark)"> <span
class="preview-btn"
@click.stop="
previewRemark(items.extra_attribution.remark)
"
>
<i class="el-icon-view"></i> <i class="el-icon-view"></i>
点击查看大图 点击查看大图
</span> </span>
</div> </div>
<div class="remark-value" <div
v-html="formatImg(items.extra_attribution && items.extra_attribution.remark ? items.extra_attribution.remark : '')"> class="remark-value"
</div> v-html="
formatImg(
items.extra_attribution &&
items.extra_attribution.remark
? items.extra_attribution.remark
: '',
)
"
></div>
</div> </div>
</div> </div>
</template> </template>
...@@ -123,66 +245,79 @@ ...@@ -123,66 +245,79 @@
<noContent /> <noContent />
</div> </div>
</div> </div>
<el-dialog :visible.sync="dialogRemarkVisible" append-to-body title="查看大图" custom-class="remake-dialog"> <el-dialog
:visible.sync="dialogRemarkVisible"
append-to-body
title="查看大图"
custom-class="remake-dialog"
>
<div class="remake-box"> <div class="remake-box">
<div v-html="dialogRemake"></div> <div v-html="dialogRemake"></div>
</div> </div>
</el-dialog> </el-dialog>
<!-- 编辑误操作 --> <!-- 编辑误操作 -->
<TerminalTransferDialog v-if="showaddAreaTransfer" :visible.sync="showaddAreaTransfer" <TerminalTransferDialog
:area-transfer-item="areaTransferItem" @updateList="updateList" /> v-if="showaddAreaTransfer"
:visible.sync="showaddAreaTransfer"
:area-transfer-item="areaTransferItem"
@updateList="updateList"
/>
</div> </div>
</template> </template>
<script> <script>
import { searchcondition, member_trans_request_list, member_trans_request_process } from '@/api/game' import {
import { mapState } from 'vuex' searchcondition,
import { removeDp, formatNumber, debounce } from '@/utils/index' member_trans_request_list,
import TerminalTransferDialog from './TerminalTransferDialog.vue' member_trans_request_process,
import selectDate from '@/components/selectDate.vue' } from "@/api/game";
import { mapState } from "vuex";
import { removeDp, formatNumber, debounce } from "@/utils/index";
import TerminalTransferDialog from "./TerminalTransferDialog.vue";
import selectDate from "@/components/selectDate.vue";
// 导入审批状态图标 // 导入审批状态图标
import shenpi1 from '@/assets/icon/svg/shenpi1.svg' import shenpi1 from "@/assets/icon/svg/shenpi1.svg";
import shenpi2 from '@/assets/icon/svg/shenpi2.svg' import shenpi2 from "@/assets/icon/svg/shenpi2.svg";
import shenpi4 from '@/assets/icon/svg/shenpi4.svg' import shenpi4 from "@/assets/icon/svg/shenpi4.svg";
import shenpi5 from '@/assets/icon/svg/shenpi5.svg' import shenpi5 from "@/assets/icon/svg/shenpi5.svg";
import shenpi6 from '@/assets/icon/svg/shenpi6.svg' import shenpi6 from "@/assets/icon/svg/shenpi6.svg";
import noContent from '@/components/noContent.vue' import noContent from "@/components/noContent.vue";
export default { export default {
name: 'terminaTranfer', name: "terminaTranfer",
computed: { computed: {
...mapState('game', ['accountSelect']), ...mapState("game", ["accountSelect"]),
...mapState('user', ['userInfo']) ...mapState("user", ["userInfo"]),
}, },
components: { components: {
TerminalTransferDialog, TerminalTransferDialog,
noContent, noContent,
selectDate selectDate,
}, },
data() { data() {
return { return {
pickerOptions: { pickerOptions: {
disabledDate(time) { disabledDate(time) {
const curDate = (new Date()).getTime() const curDate = new Date().getTime();
const three = 90 * 24 * 3600 * 1000 const three = 90 * 24 * 3600 * 1000;
const threeMonths = curDate - three const threeMonths = curDate - three;
return time.getTime() >= Date.now() || time.getTime() <= threeMonths return time.getTime() >= Date.now() || time.getTime() <= threeMonths;
} },
}, },
terminaForm: { terminaForm: {
member_id: '', member_id: "",
create_time_start: '', create_time_start: "",
create_time_end: '', create_time_end: "",
approval_status: '' approval_status: "",
}, },
dateValue: [], dateValue: [],
pageInfo: { pageInfo: {
page: 1, page: 1,
page_size: 20 page_size: 20,
}, },
terminaList: [], terminaList: [],
isMoreRecord: false, isMoreRecord: false,
approvalList: [], approvalList: [],
dialogRemarkVisible: false, dialogRemarkVisible: false,
dialogRemake: '', dialogRemake: "",
showaddAreaTransfer: false, showaddAreaTransfer: false,
formatNumber: formatNumber, formatNumber: formatNumber,
// 审批状态图标 // 审批状态图标
...@@ -190,178 +325,208 @@ export default { ...@@ -190,178 +325,208 @@ export default {
shenpi2, shenpi2,
shenpi4, shenpi4,
shenpi5, shenpi5,
shenpi6 shenpi6,
} };
}, },
watch: { watch: {
accountSelect(newVal, oldVal) { accountSelect(newVal, oldVal) {
console.log(newVal, 'newVal') console.log(newVal, "newVal");
if (newVal && newVal !== '') { if (newVal && newVal !== "") {
this.pageInfo = { this.pageInfo = {
page: 0, page: 0,
page_size: 20, page_size: 20,
total: 0 total: 0,
} };
this.isMoreRecord = true this.isMoreRecord = true;
this.filterChange() this.filterChange();
}
} }
}, },
},
mounted() { mounted() {
this.dateValue = [ this.dateValue = [
this.$moment().subtract(6, 'days').format('YYYY-MM-DD HH:mm:ss'), this.$moment().subtract(6, "days").format("YYYY-MM-DD HH:mm:ss"),
this.$moment().format('YYYY-MM-DD HH:mm:ss') this.$moment().format("YYYY-MM-DD HH:mm:ss"),
] ];
this.terminaForm.create_time_start = this.dateValue[0] this.terminaForm.create_time_start = this.dateValue[0];
this.terminaForm.create_time_end = this.dateValue[1] this.terminaForm.create_time_end = this.dateValue[1];
this.requstApprovalList() this.requstApprovalList();
this.filterChange() this.filterChange();
}, },
methods: { methods: {
updateList() { updateList() {
this.filterChange() this.filterChange();
}, },
resubmitApproval(item) { resubmitApproval(item) {
this.showaddAreaTransfer = true this.showaddAreaTransfer = true;
this.areaTransferItem = item this.areaTransferItem = item;
}, },
createResult: debounce(function (data) { createResult: debounce(function (data) {
if (data && Array.isArray(data) && data.length === 2) { if (data && Array.isArray(data) && data.length === 2) {
this.terminaForm.create_time_start = data[0] this.terminaForm.create_time_start = data[0];
this.terminaForm.create_time_end = data[1] this.terminaForm.create_time_end = data[1];
this.dateValue = data this.dateValue = data;
} else { } else {
this.terminaForm.create_time_start = '' this.terminaForm.create_time_start = "";
this.terminaForm.create_time_end = '' this.terminaForm.create_time_end = "";
this.dateValue = [] this.dateValue = [];
} }
this.filterChange() this.filterChange();
}, 300), }, 300),
filterChange() { filterChange() {
this.pageInfo.page = 1 this.pageInfo.page = 1;
this.terminaList = [] this.terminaList = [];
this.isMoreRecord = true this.isMoreRecord = true;
this.terminaIndex() this.terminaIndex();
}, },
async requstApprovalList() { async requstApprovalList() {
const data = { const data = {
type: 'dictionaries', type: "dictionaries",
table_name: 'zs_refund_request', table_name: "zs_refund_request",
field_name: 'approval_status' field_name: "approval_status",
} };
const res = await searchcondition(data) const res = await searchcondition(data);
if (res.status_code === 1) { if (res.status_code === 1) {
this.approvalList = res.data.data this.approvalList = res.data.data;
} }
}, },
previewRemark(remark) { previewRemark(remark) {
this.dialogRemake = remark this.dialogRemake = remark;
this.dialogRemarkVisible = true this.dialogRemarkVisible = true;
}, },
async terminaProcess(item, index) { async terminaProcess(item, index) {
item.showStep = !item.showStep item.showStep = !item.showStep;
if (item.terminaProcessList.length === 0) { if (item.terminaProcessList.length === 0) {
try { try {
const res = await member_trans_request_process({ id: item.id }) const res = await member_trans_request_process({ id: item.id });
item.terminaProcessList = res.data.data item.terminaProcessList = res.data.data;
res.data.data.map((items) => { res.data.data.map((items) => {
if (items.approval_result !== '0' && items.approval_result !== '2') { if (
item.current += 1 items.approval_result !== "0" &&
items.approval_result !== "2"
) {
item.current += 1;
} }
}) });
} catch (error) { } catch (error) {
this.$message.error('获取审批进度失败') this.$message.error("获取审批进度失败");
console.error('获取审批进度失败:', error) console.error("获取审批进度失败:", error);
} }
} }
this.$forceUpdate() this.$forceUpdate();
}, },
paperScroll() { paperScroll() {
if (!this.isMoreRecord) { if (!this.isMoreRecord) {
console.log('没有更多数据了') console.log("没有更多数据了");
return false return false;
} }
this.requestNextPage() this.requestNextPage();
}, },
requestNextPage(pageInfo) { requestNextPage(pageInfo) {
this.pageInfo.page++ this.pageInfo.page++;
this.terminaIndex() this.terminaIndex();
}, },
handleCurrentChange(val) { handleCurrentChange(val) {
this.pageInfo.page = val this.pageInfo.page = val;
}, },
switchStateTag(status) { switchStateTag(status) {
switch (status) { switch (status) {
case '0': case "0":
return 'unhandle' return "unhandle";
case '1': case "1":
return 'handled' return "handled";
case '2': case "2":
return 'sendFail' return "sendFail";
} }
}, },
formatImg(html) { formatImg(html) {
if (html) { if (html) {
return html.replaceAll(/<img/g, '<img style="max-width:100px;"') return html.replaceAll(/<img/g, '<img style="max-width:100px;"');
} }
return html return html;
}, },
switchStateText(status) { switchStateText(status) {
switch (status) { switch (status) {
case '0': case "0":
return '待审批' return "待审批";
case '1': case "1":
return '通过' return "通过";
case '2': case "2":
return '驳回' return "驳回";
} }
}, },
async terminaIndex() { async terminaIndex() {
if (this.accountSelect === '') { if (this.accountSelect === "") {
this.$message.warning('暂无关联的账号,请先去关联账号!') this.$message.warning("暂无关联的账号,请先去关联账号!");
return false return false;
} }
if (this.pageInfo.page === 1) { if (this.pageInfo.page === 1) {
this.terminaList = [] this.terminaList = [];
} }
const { create_time_start, create_time_end, approval_status } = this.terminaForm const { create_time_start, create_time_end, approval_status } =
const data = { this.terminaForm;
// const data = {
// approval_status,
// create_time_start,
// create_time_end,
// member_id: this.accountSelect,
// ...this.pageInfo
// }
const related_task_info = JSON.parse(
sessionStorage.getItem("related_task_info"),
);
let data = {};
if (related_task_info && related_task_info.related_task_type === 13) {
data = { ...this.pageInfo, id: related_task_info.related_task_id };
this.terminaForm.create_time_start = "";
this.terminaForm.create_time_end = "";
this.dateValue = [];
//展示一次后清除携带过来的id
this.$nextTick(() => {
setTimeout(() => {
sessionStorage.removeItem("related_task_info");
}, 200);
});
} else {
data = {
approval_status, approval_status,
create_time_start, create_time_start,
create_time_end, create_time_end,
member_id: this.accountSelect, member_id: this.accountSelect,
...this.pageInfo ...this.pageInfo,
};
} }
const res = await member_trans_request_list(data)
const res = await member_trans_request_list(data);
if (this.pageInfo.page === 1) { if (this.pageInfo.page === 1) {
this.terminaList = res.data.data this.terminaList = res.data.data;
} else { } else {
this.terminaList = this.terminaList.concat(res.data.data) this.terminaList = this.terminaList.concat(res.data.data);
} }
if (this.terminaList.length > 0) { if (this.terminaList.length > 0) {
this.terminaList.map((item) => { this.terminaList.map((item) => {
item.showStep = false item.showStep = false;
item.current = 0 item.current = 0;
item.terminaProcessList = [] item.terminaProcessList = [];
}) });
} else { } else {
this.terminaList = [] this.terminaList = [];
} }
if (res.data.data.length < 20) { if (res.data.data.length < 20) {
this.isMoreRecord = false this.isMoreRecord = false;
} else { } else {
this.isMoreRecord = true this.isMoreRecord = true;
}
} }
} },
} },
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.terminaListContent { .terminaListContent {
width: 100%; width: 100%;
height: 100%; height: 100%;
overflow: auto;
overflow-x: hidden;
.TerminaTranferContent { .TerminaTranferContent {
width: 100%; width: 100%;
height: 100%; height: 100%;
...@@ -411,7 +576,7 @@ export default { ...@@ -411,7 +576,7 @@ export default {
font-size: 12px; font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC; font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400; font-weight: 400;
color: #409EFF; color: #409eff;
border: none; border: none;
} }
...@@ -537,30 +702,30 @@ export default { ...@@ -537,30 +702,30 @@ export default {
width: 1px; width: 1px;
} }
::v-deep .el-step>.is-success { ::v-deep .el-step > .is-success {
color: #409EFF; color: #409eff;
border-color: #409EFF; border-color: #409eff;
.el-step__line { .el-step__line {
background-color: #e5e6eb; background-color: #e5e6eb;
} }
} }
::v-deep .el-step__main>.is-success { ::v-deep .el-step__main > .is-success {
color: #409EFF; color: #409eff;
} }
::v-deep .el-step>.is-process { ::v-deep .el-step > .is-process {
color: #409EFF; color: #409eff;
border-color: #409EFF; border-color: #409eff;
.el-step__line { .el-step__line {
background-color: #e5e6eb; background-color: #e5e6eb;
} }
} }
::v-deep .el-step__main>.is-process { ::v-deep .el-step__main > .is-process {
color: #409EFF; color: #409eff;
} }
.form-item-btn { .form-item-btn {
...@@ -581,7 +746,7 @@ export default { ...@@ -581,7 +746,7 @@ export default {
.preview-btn { .preview-btn {
cursor: pointer; cursor: pointer;
font-size: 14px; font-size: 14px;
color: #409EFF; color: #409eff;
margin: 0 0 0 10px; margin: 0 0 0 10px;
i { i {
...@@ -685,7 +850,7 @@ export default { ...@@ -685,7 +850,7 @@ export default {
height: 80px; height: 80px;
} }
&:hover>.preview-pic { &:hover > .preview-pic {
z-index: 100; z-index: 100;
} }
} }
...@@ -737,7 +902,7 @@ export default { ...@@ -737,7 +902,7 @@ export default {
} }
.info-value-color { .info-value-color {
color: #409EFF; color: #409eff;
margin-left: 5px; margin-left: 5px;
} }
} }
......
...@@ -3,23 +3,53 @@ ...@@ -3,23 +3,53 @@
<div class="detailsErrorHandleContent" v-scroll="requestOrderList"> <div class="detailsErrorHandleContent" v-scroll="requestOrderList">
<div class="addApply rowFlex spaceBetween"> <div class="addApply rowFlex spaceBetween">
<span></span> <span></span>
<el-button type="primary" size="small" icon="el-icon-plus" <el-button
@click="showAddErrorHandle = true, info = null">新增误操作</el-button> type="primary"
size="small"
icon="el-icon-plus"
@click="(showAddErrorHandle = true), (info = null)"
>新增误操作</el-button
>
</div> </div>
<el-form class="filterList" label-position="top" size="small"> <el-form class="filterList" label-position="top" size="small">
<el-form-item label="角色名称" style="margin-bottom:15px;"> <el-form-item label="角色名称" style="margin-bottom: 15px">
<searchSelect :account-change="accountChange" style="width:100%;" placeholder="请输入角色名称" <searchSelect
@result="selectResult" /> :account-change="accountChange"
style="width: 100%"
placeholder="请输入角色名称"
@result="selectResult"
/>
</el-form-item> </el-form-item>
<el-form-item label="状态" style="margin-bottom:15px;"> <el-form-item label="状态" style="margin-bottom: 15px">
<el-select v-model="pay_type" clearable placeholder="状态" style="width:100%;" @change="payTypeResult"> <el-select
<el-option v-for="item in statusList" :key="item.value" :label="item.label" :value="item.value"> v-model="pay_type"
clearable
placeholder="状态"
style="width: 100%"
@change="payTypeResult"
>
<el-option
v-for="item in statusList"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="创建时间" style="margin-bottom:15px;"> <el-form-item label="创建时间" style="margin-bottom: 15px">
<el-date-picker v-model="searchDate" type="daterange" clearable style="width:100%;" value-format="yyyy-MM-dd" <el-date-picker
range-separator="~" start-placeholder="开始日期" end-placeholder="结束日期" @change="dateResult"> </el-date-picker> v-model="searchDate"
type="daterange"
clearable
style="width: 100%"
value-format="yyyy-MM-dd"
range-separator="~"
start-placeholder="开始日期"
end-placeholder="结束日期"
@change="dateResult"
>
</el-date-picker>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div class="list"> <div class="list">
...@@ -27,14 +57,20 @@ ...@@ -27,14 +57,20 @@
<!-- 订单列表 --> <!-- 订单列表 -->
<div class="orderDetailsScroll"> <div class="orderDetailsScroll">
<div v-if="orderList.length > 0" class="orderDetailsScrollContent"> <div v-if="orderList.length > 0" class="orderDetailsScrollContent">
<div v-for="(item, index) in orderList" :key="index" class="orderDetails"> <div
v-for="(item, index) in orderList"
:key="index"
class="orderDetails"
>
<div class="orderDetailsList"> <div class="orderDetailsList">
<el-collapse v-model="collapseValue" @change="handleChange"> <el-collapse v-model="collapseValue" @change="handleChange">
<el-collapse-item :name="item.order_id"> <el-collapse-item :name="item.order_id">
<template slot="title"> <template slot="title">
<div class="orderDetailsTitle"> <div class="orderDetailsTitle">
<div class="money rowFlex spaceBetween"> <div class="money rowFlex spaceBetween">
<p class="text hidden">角色名称:{{ item.role_name }}</p> <p class="text hidden">
角色名称:{{ item.role_name }}
</p>
</div> </div>
</div> </div>
</template> </template>
...@@ -54,25 +90,53 @@ ...@@ -54,25 +90,53 @@
<div class="item rowFlex columnCenter spaceBetween"> <div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex"> <div class="rowFlex">
<span class="label">状态</span> <span class="label">状态</span>
<p v-if="item.approval_status == 1" class="unhandle" style="margin-left:10px;">{{ <p
item.approval_status_text }}</p> v-if="item.approval_status == 1"
<p v-else-if="item.approval_status == 2" style="margin-left:10px;" class="noSend">{{ class="unhandle"
item.approval_status_text }}</p> style="margin-left: 10px"
<p v-else-if="item.approval_status == 3" style="margin-left:10px;" class="sended">{{ >
item.approval_status_text }}</p> {{ item.approval_status_text }}
<p v-else-if="item.approval_status == 4" style="margin-left:10px;" class="sendFail">{{ </p>
item.approval_status_text }} <p
v-else-if="item.approval_status == 2"
style="margin-left: 10px"
class="noSend"
>
{{ item.approval_status_text }}
</p>
<p
v-else-if="item.approval_status == 3"
style="margin-left: 10px"
class="sended"
>
{{ item.approval_status_text }}
</p>
<p
v-else-if="item.approval_status == 4"
style="margin-left: 10px"
class="sendFail"
>
{{ item.approval_status_text }}
</p>
<p
v-else-if="item.approval_status == 5"
style="margin-left: 10px"
class="handled"
>
{{ item.approval_status_text }}
</p> </p>
<p v-else-if="item.approval_status == 5" style="margin-left:10px;" class="handled">{{
item.approval_status_text }}</p>
</div> </div>
</div> </div>
<div class="item rowFlex columnCenter spaceBetween"> <div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex"> <div class="rowFlex">
<span class="label">补发道具</span> <span class="label">补发道具</span>
<div v-if="item.reissue_prop.length" style="width:75%;"> <div v-if="item.reissue_prop.length" style="width: 75%">
<p v-for="(items, indexs) in item.reissue_prop" :key="indexs" class="text">{{ items.name }}{{ <p
`(${items.num})` }} v-for="(items, indexs) in item.reissue_prop"
:key="indexs"
class="text"
>
{{ items.name }}{{ `(${items.num})` }}
</p> </p>
</div> </div>
</div> </div>
...@@ -80,9 +144,13 @@ ...@@ -80,9 +144,13 @@
<div class="item rowFlex columnCenter spaceBetween"> <div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex"> <div class="rowFlex">
<span class="label">返回道具</span> <span class="label">返回道具</span>
<div v-if="item.return_prop.length" style="width:75%;"> <div v-if="item.return_prop.length" style="width: 75%">
<p v-for="(items, indexs) in item.return_prop" :key="indexs" class="text">{{ items.name }}{{ <p
`(${items.num})` }} v-for="(items, indexs) in item.return_prop"
:key="indexs"
class="text"
>
{{ items.name }}{{ `(${items.num})` }}
</p> </p>
</div> </div>
</div> </div>
...@@ -97,146 +165,150 @@ ...@@ -97,146 +165,150 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<!-- 编辑误操作 --> <!-- 编辑误操作 -->
<addErrorHandle v-if="showAddErrorHandle" :show.sync="showAddErrorHandle" :info="info" title="玩家误操作" width="320px" <addErrorHandle
@updateList="updateList" /> v-if="showAddErrorHandle"
:show.sync="showAddErrorHandle"
:info="info"
title="玩家误操作"
width="320px"
@updateList="updateList"
/>
</div> </div>
</template> </template>
<script> <script>
import { mapMutations, mapActions, mapState } from 'vuex' import { mapMutations, mapActions, mapState } from "vuex";
import searchSelect from '../order/searchUser.vue' import searchSelect from "../order/searchUser.vue";
import { memberView, misoperationIndex, searchcondition } from '@/api/game' import { memberView, misoperationIndex, searchcondition } from "@/api/game";
import addErrorHandle from './addErrorHandle.vue' import addErrorHandle from "./addErrorHandle.vue";
import noContent from '@/components/noContent.vue' import noContent from "@/components/noContent.vue";
export default { export default {
name: 'errorHandle', name: "errorHandle",
components: { components: {
searchSelect, searchSelect,
addErrorHandle, addErrorHandle,
noContent noContent,
}, },
data() { data() {
return { return {
pay_type: 0, pay_type: 0,
info: {}, info: {},
searchDate: [], searchDate: [],
create_time_start: '', create_time_start: "",
create_time_end: '', create_time_end: "",
showAddErrorHandle: false, showAddErrorHandle: false,
isloadMore: true, isloadMore: true,
collapseValue: ['1'], collapseValue: ["1"],
orderList: [], orderList: [],
gameUserInfo: { gameUserInfo: {
recharge_total: 0, recharge_total: 0,
today_amount: 0 today_amount: 0,
}, },
statusList: [], statusList: [],
role_id: '', role_id: "",
accountChange: false, accountChange: false,
pageInfo: { pageInfo: {
page: 0, page: 0,
page_size: 20, page_size: 20,
total: 0 total: 0,
} },
} };
}, },
computed: { computed: {
...mapState('game', ['accountSelect']), ...mapState("game", ["accountSelect"]),
...mapState('user', ['userInfo']) ...mapState("user", ["userInfo"]),
}, },
watch: { watch: {
accountSelect(newVal, oldVal) { accountSelect(newVal, oldVal) {
if (newVal && newVal !== '') { if (newVal && newVal !== "") {
this.pageInfo = { this.pageInfo = {
page: 0, page: 0,
page_size: 20, page_size: 20,
total: 0 total: 0,
} };
this.isloadMore = true this.isloadMore = true;
this.orderList = [] this.orderList = [];
this.requestOrderList('msg') this.requestOrderList("msg");
// this.gameMemberView() // this.gameMemberView()
this.accountChange = true this.accountChange = true;
setTimeout(() => { setTimeout(() => {
this.accountChange = false this.accountChange = false;
}, 200) }, 200);
}
} }
},
}, },
mounted() { mounted() {
this.requstStatusList() this.requstStatusList();
// this.gameMemberView() // this.gameMemberView()
this.requestOrderList('msg') this.requestOrderList("msg");
}, },
methods: { methods: {
async requstStatusList() { async requstStatusList() {
const data = { const data = {
type: 'dictionaries', type: "dictionaries",
table_name: 'zs_refund_request', table_name: "zs_refund_request",
field_name: 'approval_status' field_name: "approval_status",
} };
const res = await searchcondition(data) const res = await searchcondition(data);
if (res.status_code === 1) { if (res.status_code === 1) {
this.statusList = res.data.data this.statusList = res.data.data;
this.statusList.unshift({ label: '全部', value: 0 }) this.statusList.unshift({ label: "全部", value: 0 });
} }
}, },
dateResult(data) { dateResult(data) {
if (data) { if (data) {
this.create_time_start = data[0] this.create_time_start = data[0];
this.create_time_end = data[1] this.create_time_end = data[1];
} else { } else {
this.create_time_start = '' this.create_time_start = "";
this.create_time_end = '' this.create_time_end = "";
} }
this.pageInfo = { this.pageInfo = {
page: 0, page: 0,
page_size: 20, page_size: 20,
total: 0 total: 0,
} };
this.isloadMore = true this.isloadMore = true;
this.orderList = [] this.orderList = [];
this.requestOrderList() this.requestOrderList();
}, },
updateList() { updateList() {
this.pageInfo = { this.pageInfo = {
page: 0, page: 0,
page_size: 20, page_size: 20,
total: 0 total: 0,
} };
this.isloadMore = true this.isloadMore = true;
this.orderList = [] this.orderList = [];
this.requestOrderList() this.requestOrderList();
}, },
editErrorHanle(item) { editErrorHanle(item) {
this.showAddErrorHandle = true this.showAddErrorHandle = true;
this.info = item this.info = item;
}, },
payTypeResult() { payTypeResult() {
this.isloadMore = true this.isloadMore = true;
this.pageInfo = { this.pageInfo = {
page: 0, page: 0,
page_size: 20, page_size: 20,
total: 0 total: 0,
} };
this.isloadMore = true this.isloadMore = true;
this.orderList = [] this.orderList = [];
this.requestOrderList() this.requestOrderList();
}, },
selectResult(value) { selectResult(value) {
this.pageInfo = { this.pageInfo = {
page: 0, page: 0,
page_size: 20, page_size: 20,
total: 0 total: 0,
} };
this.isloadMore = true this.isloadMore = true;
this.orderList = [] this.orderList = [];
this.role_id = value this.role_id = value;
this.requestOrderList() this.requestOrderList();
}, },
// onConfirm() { // onConfirm() {
// const data = { // const data = {
...@@ -264,41 +336,62 @@ export default { ...@@ -264,41 +336,62 @@ export default {
// }) // })
// }, // },
handleChange(val) { handleChange(val) {
console.log(val) console.log(val);
}, },
requestOrderList(msg) { requestOrderList(msg) {
if (this.accountSelect == '') { if (this.accountSelect == "") {
this.$message.warning('暂无关联的账号,请先去关联账号!') this.$message.warning("暂无关联的账号,请先去关联账号!");
return false return false;
} }
if (!this.isloadMore) { if (!this.isloadMore) {
console.log('没有更多数据了') console.log("没有更多数据了");
return false return false;
} }
this.pageInfo.page += 1 this.pageInfo.page += 1;
const data = { // const data = {
// role_id: this.role_id,
// member_id: this.accountSelect,
// create_time_start: this.create_time_start,
// create_time_end: this.create_time_end,
// approval_status: this.pay_type,
// ...this.pageInfo
// }
const related_task_info = JSON.parse(
sessionStorage.getItem("related_task_info"),
);
const data = related_task_info
? { ...this.pageInfo, id: related_task_info.related_task_id }
: {
role_id: this.role_id, role_id: this.role_id,
member_id: this.accountSelect, member_id: this.accountSelect,
create_time_start: this.create_time_start, create_time_start: this.create_time_start,
create_time_end: this.create_time_end, create_time_end: this.create_time_end,
approval_status: this.pay_type, approval_status: this.pay_type,
...this.pageInfo ...this.pageInfo,
} };
misoperationIndex(data).then(res => { //展示一次后清除携带过来的id
this.$nextTick(() => {
setTimeout(() => {
sessionStorage.removeItem("related_task_info");
}, 200);
});
misoperationIndex(data).then((res) => {
if (res.data.data && res.data.data.length < 20) { if (res.data.data && res.data.data.length < 20) {
this.isloadMore = false this.isloadMore = false;
} }
this.orderList = this.orderList.concat(res.data.data) this.orderList = this.orderList.concat(res.data.data);
this.orderList.map(item => { this.orderList.map((item) => {
!item.remarks || item.remarks.length === 0 ? item.remarks = [{ remark: '' }] : '' !item.remarks || item.remarks.length === 0
}) ? (item.remarks = [{ remark: "" }])
: "";
});
if (res.status_code == 1 && !msg) { if (res.status_code == 1 && !msg) {
// this.$message.success(res.msg) // this.$message.success(res.msg)
} }
}) });
} },
} },
} };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.detailsErrorHandle { .detailsErrorHandle {
...@@ -334,7 +427,7 @@ export default { ...@@ -334,7 +427,7 @@ export default {
.tabSelect { .tabSelect {
width: 100%; width: 100%;
height: 60px; height: 60px;
border-bottom: 1px solid #EBEEF5; border-bottom: 1px solid #ebeef5;
cursor: pointer; cursor: pointer;
.tabSelectItem { .tabSelectItem {
...@@ -348,8 +441,8 @@ export default { ...@@ -348,8 +441,8 @@ export default {
} }
.tabSelectItemActive { .tabSelectItemActive {
color: #409EFF; color: #409eff;
border-bottom: 2px solid #409EFF; border-bottom: 2px solid #409eff;
} }
} }
...@@ -421,7 +514,7 @@ export default { ...@@ -421,7 +514,7 @@ export default {
display: inline-block; display: inline-block;
width: 8px; width: 8px;
height: 8px; height: 8px;
background: #F45454; background: #f45454;
border-radius: 5px; border-radius: 5px;
} }
...@@ -429,7 +522,7 @@ export default { ...@@ -429,7 +522,7 @@ export default {
display: inline-block; display: inline-block;
width: 8px; width: 8px;
height: 8px; height: 8px;
background: #409EFF; background: #409eff;
border-radius: 5px; border-radius: 5px;
} }
...@@ -437,7 +530,7 @@ export default { ...@@ -437,7 +530,7 @@ export default {
display: inline-block; display: inline-block;
width: 8px; width: 8px;
height: 8px; height: 8px;
background: #FF9D02; background: #ff9d02;
border-radius: 5px; border-radius: 5px;
} }
} }
...@@ -462,7 +555,7 @@ export default { ...@@ -462,7 +555,7 @@ export default {
p { p {
font-size: 22px; font-size: 22px;
color: #409EFF; color: #409eff;
} }
} }
} }
...@@ -511,7 +604,7 @@ export default { ...@@ -511,7 +604,7 @@ export default {
font-size: 8px; font-size: 8px;
font-family: PingFangSC-Regular, PingFang SC; font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400; font-weight: 400;
color: #FF9D02; color: #ff9d02;
transform: rotate(48deg); transform: rotate(48deg);
z-index: 100; z-index: 100;
position: absolute; position: absolute;
...@@ -531,7 +624,7 @@ export default { ...@@ -531,7 +624,7 @@ export default {
.orderDetailsTitle { .orderDetailsTitle {
width: 100%; width: 100%;
background: #F9FAFF; background: #f9faff;
.money { .money {
width: 100%; width: 100%;
...@@ -554,18 +647,18 @@ export default { ...@@ -554,18 +647,18 @@ export default {
} }
.btnnot { .btnnot {
background: #FFDDDD; background: #ffdddd;
font-family: PingFangSC-Regular, PingFang SC; font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400; font-weight: 400;
color: #F56C6C; color: #f56c6c;
border: none; border: none;
} }
.btnsuccess { .btnsuccess {
background: #E1FFF0; background: #e1fff0;
font-family: PingFangSC-Regular, PingFang SC; font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400; font-weight: 400;
color: #409EFF; color: #409eff;
border: none; border: none;
} }
...@@ -573,24 +666,24 @@ export default { ...@@ -573,24 +666,24 @@ export default {
padding: 0 8px; padding: 0 8px;
height: 20px; height: 20px;
line-height: 20px; line-height: 20px;
background: #E1FFF0; background: #e1fff0;
border-radius: 4px; border-radius: 4px;
font-size: 12px; font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC; font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400; font-weight: 400;
color: #409EFF; color: #409eff;
} }
.noSend { .noSend {
padding: 0 8px; padding: 0 8px;
height: 20px; height: 20px;
line-height: 20px; line-height: 20px;
background: #FFFAE0; background: #fffae0;
border-radius: 4px; border-radius: 4px;
font-size: 12px; font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC; font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400; font-weight: 400;
color: #FFA81D; color: #ffa81d;
} }
} }
...@@ -611,8 +704,8 @@ export default { ...@@ -611,8 +704,8 @@ export default {
.orderDetailsList { .orderDetailsList {
width: 100%; width: 100%;
height: auto; height: auto;
background: #FFFFFF; background: #ffffff;
border: 1px solid #EBEEF5; border: 1px solid #ebeef5;
position: relative; position: relative;
.titleFix { .titleFix {
...@@ -623,7 +716,6 @@ export default { ...@@ -623,7 +716,6 @@ export default {
} }
} }
} }
} }
::v-deep .el-tabs__item { ::v-deep .el-tabs__item {
...@@ -639,6 +731,5 @@ export default { ...@@ -639,6 +731,5 @@ export default {
height: 100%; height: 100%;
font-size: 300px; font-size: 300px;
} }
} }
</style> </style>
...@@ -33,10 +33,10 @@ ...@@ -33,10 +33,10 @@
@click="previewVideo(item)" @click="previewVideo(item)"
> >
<div class="flex items-center"> <div class="flex items-center">
<iconpark-icon <svg-icon
name="xiaoxicaozuo-chakan" svgName="xiaoxicaozuo-chakan"
class="mr-[4px] text-[14px]" class="mr-[4px] h-[14px] w-[14px] text-[14px]"
></iconpark-icon> ></svg-icon>
预览 预览
</div> </div>
</el-button> </el-button>
...@@ -44,10 +44,10 @@ ...@@ -44,10 +44,10 @@
@click="sendVideo(item)" @click="sendVideo(item)"
class="h-[24px] ml-[8px] cursor-pointer hover:bg-[#E7F1FD] text-[12px] w-[58px] p-0 flex justify-center items-center rounded-full bg-[#F7F8FA] text-[#267EF0]" class="h-[24px] ml-[8px] cursor-pointer hover:bg-[#E7F1FD] text-[12px] w-[58px] p-0 flex justify-center items-center rounded-full bg-[#F7F8FA] text-[#267EF0]"
> >
<iconpark-icon <svg-icon
name="icon-fasonghuashu" svgName="icon-fasonghuashu"
class="text-[14px] mr-[4px]" class="text-[14px] w-[14px] h-[14px] mr-[4px]"
></iconpark-icon> ></svg-icon>
<span> 发送</span> <span> 发送</span>
</div> </div>
</div> </div>
......
<template>
<div
class="p-[16px] h-full overflow-y-auto"
ref="conversationLifeline"
@scroll="handleScroll"
>
<div
class="flex justify-between"
v-for="(v, index) in sessionSummaryList"
:key="v._id"
>
<div class="flex flex-col py-[4px] min-w-[24px] shrink-0 items-center">
<div class="bg-primary h-[12px] w-[12px] rounded-full"></div>
<div class="pt-[10px] flex-1">
<div class="w-[1px] h-full bg-[#D6D9E0]"></div>
</div>
</div>
<div class="text-[#323335] text-[14px] flex-1">
<div class="leading-[20px] text-[12px] text-[#C9CDD4]">
{{ v.allot_time }}{{ v.close_time }}
</div>
<div
class="py-[8px] px-[12px] rounded-[8px] border-[1px] border-solid border-[#E5E6EB]"
>
<div class="flex items-center justify-between">
<span class="font-medium">会话总结</span>
<span class="text-[#86909C] text-[14px]"
>客服:{{ v.zq_user_name }}</span
>
</div>
<div class="px-[12px] py-[8px] rounded-[4px] bg-[#F7F8FA] mt-[4px]">
{{ v.session_summary }}
</div>
<div class="pt-[8px]">
<span class="font-medium">会话分析</span>
</div>
<div class="px-[12px] py-[8px] rounded-[4px] bg-[#F7F8FA] mt-[4px]">
{{ v.session_analysis }}
</div>
<div class="flex flex-wrap gap-[8px] mt-[8px]">
<div
v-for="(tag, tagIndex) in v.session_summary_label_str?.split(',')"
:key="tagIndex"
class="px-[6px] leading-[22px] rounded-[4px] bg-[#F5F5F5] text-[#131920] text-[13px]"
>
{{ tag }}
</div>
</div>
</div>
<div class="flex justify-end">
<el-button
type="text"
icon="el-icon-redo"
:loading="v.loading"
@click="getRegenerateSummary(v)"
>重新生成</el-button
>
</div>
</div>
</div>
<div
v-if="sessionSummaryList.length === 0 && !loading"
class="text-center py-8 text-[#C9CDD4]"
>
暂无会话总结
</div>
<div v-if="loading" class="text-center py-4 text-[#C9CDD4]">加载中...</div>
</div>
</template>
<script>
import { sessionSummaryList, regenerateSummary } from "@/api/aiChat";
import { mapState } from "vuex";
export default {
name: "ConversationLifeline",
data() {
return {
sessionSummaryList: [],
loading: false,
page: 1,
pageSize: 10,
total: 0,
isLastPage: false,
};
},
computed: {
...mapState("game", ["chatUserInfo"]),
...mapState("user", ["corp_id"]),
},
mounted() {
this.getSessionSummaryList();
},
methods: {
/**
* 获取会话总结列表
* @param {boolean} isLoadMore - 是否为加载更多
*/
async getSessionSummaryList(isLoadMore = false) {
// 如果已经是最后一页,则不再加载
if (isLoadMore && this.isLastPage) {
return;
}
try {
this.loading = true;
// 如果是加载更多,则页码+1
const currentPage = isLoadMore ? this.page + 1 : 1;
// 获取企业ID和外部用户ID
const corpId = this.corp_id;
const externalUserId = this.chatUserInfo.external_userid;
const params = {
corp_id: corpId,
external_userid: externalUserId,
page: currentPage,
page_size: this.pageSize,
};
const res = await sessionSummaryList(params);
if (res.status_code === 1) {
const newData = res.data.data.map((item) => ({
...item,
loading: false,
}));
const totalCount = res.data.page_info.total;
// 合并数据
if (isLoadMore) {
this.sessionSummaryList = [...this.sessionSummaryList, ...newData];
this.page = currentPage;
} else {
this.sessionSummaryList = newData;
this.page = 1;
}
this.total = totalCount;
// 判断是否为最后一页
this.isLastPage = this.sessionSummaryList.length >= this.total;
console.log("会话总结列表数据:", res.data);
return this.sessionSummaryList;
} else {
this.$message({
message: res.data.msg,
type: "error",
});
return [];
}
} catch (error) {
console.error("获取会话总结列表失败:", error);
this.$message({
message: "获取会话总结列表失败",
type: "error",
});
return [];
} finally {
this.loading = false;
}
},
/**
* 滚动到底部触发分页
*/
handleScroll() {
const container = this.$refs.conversationLifeline;
if (!container || this.loading || this.isLastPage) return;
// 滚动到底部的判断条件
const scrollTop = container.scrollTop;
const scrollHeight = container.scrollHeight;
const clientHeight = container.clientHeight;
// 当距离底部20px时触发加载更多
if (scrollHeight - scrollTop - clientHeight < 20) {
this.getSessionSummaryList(true);
}
},
// 重新生成会话总结
async getRegenerateSummary(data) {
data.loading = true;
try {
await regenerateSummary({ session_id: data.session_id });
if (res.status_code === 1) {
this.$message({
message: "重新生成成功",
type: "success",
});
// 重新加载数据
this.getSessionSummaryList();
} else {
this.$message({
message: res.data.msg,
type: "error",
});
}
} catch (error) {
console.error("重新生成会话总结失败:", error);
} finally {
data.loading = false;
}
},
},
};
</script>
...@@ -8,48 +8,56 @@ ...@@ -8,48 +8,56 @@
<el-tab-pane label="AI 跟进记录" name="aiFollow"> <el-tab-pane label="AI 跟进记录" name="aiFollow">
<summaryList v-if="activeName === 'aiFollow'" /> <summaryList v-if="activeName === 'aiFollow'" />
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="跟进任务记录" name="aiFollowTask">
<followTask v-if="activeName === 'aiFollowTask'" />
</el-tab-pane>
<el-tab-pane label="会话生命线" name="ConversationLifeline">
<ConversationLifeline v-if="activeName === 'ConversationLifeline'" />
</el-tab-pane>
</el-tabs> </el-tabs>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import aiArgenChat from './aiArgenChat.vue' import aiArgenChat from "./aiArgenChat.vue";
import summaryList from './summaryList.vue' import summaryList from "./summaryList.vue";
import { mapActions } from 'vuex' import followTask from "./followTask.vue";
import ConversationLifeline from "./ConversationLifeline.vue";
import { mapActions } from "vuex";
export default { export default {
name: 'quickSendGame', name: "quickSendGame",
components: { components: {
aiArgenChat, aiArgenChat,
summaryList, summaryList,
followTask,
ConversationLifeline,
}, },
data() { data() {
return { return {
activeName: 'aiChat' activeName: "aiChat",
} };
},
created() {
}, },
created() {},
mounted() { mounted() {
// this.initializeWecom() // this.initializeWecom()
}, },
methods: { methods: {
...mapActions('user', ['initWecom']), ...mapActions("user", ["initWecom"]),
async initializeWecom() { async initializeWecom() {
try { try {
console.log('🚀 开始初始化企业微信 SDK') console.log("🚀 开始初始化企业微信 SDK");
const result = await this.initWecom() const result = await this.initWecom();
console.log('✅ 企业微信 SDK 初始化成功', result) console.log("✅ 企业微信 SDK 初始化成功", result);
} catch (error) { } catch (error) {
console.error('❌ 企业微信 SDK 初始化失败:', error) console.error("❌ 企业微信 SDK 初始化失败:", error);
} }
}, },
} },
} };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.quickSendGame { .quickSendGame {
::v-deep .el-tabs__nav-next, ::v-deep .el-tabs__nav-next,
::v-deep .el-tabs__nav-prev { ::v-deep .el-tabs__nav-prev {
line-height: 50px; line-height: 50px;
......
<template>
<div class="follow-task">
<!-- 消息列表 -->
<div v-infinite-scroll="requestDataList" v-loading="loading"
:infinite-scroll-disabled="!isloadMore" class="follow-task__scroll">
<div v-if="messageList.length > 0" class="follow-task__list">
<div v-for="(item, index) in messageList" :key="index" class="follow-task__item">
<div class="follow-task__date">{{ `${item.message_log_start_date} - ${item.message_log_end_date}` }}</div>
<div class="follow-task__content">
<div v-if="item.summary" class="follow-task__detail">
<div class="follow-task__detail-text" v-html="item.summary"></div>
</div>
<div v-else class="follow-task__no-detail">
<span>暂无详情</span>
</div>
</div>
</div>
</div>
<noContent v-else-if="!loading && messageList.length == 0" />
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
import { corp_follow_up_task_index } from '@/api/works'
import { throttle } from '@/utils'
import noContent from '@/components/noContent.vue'
export default {
name: 'FollowTask',
props: {
chatUserDetails: {
typeof: Object,
default: () => { }
}
},
data() {
return {
loading: false,
isloadMore: true,
messageList: [],
pageInfo: {
page: 0,
page_size: 20
}
}
},
components: {
noContent
},
computed: {
...mapState('game', ['accountSelect', 'bindGameUserList']),
...mapState('user', ['corp_id']),
},
watch: {
accountSelect(newVal) {
if (newVal && newVal !== '' ) {
this.pageInfo = {
page: 0,
page_size: 20
}
this.isloadMore = true
this.messageList = []
this.requestDataList()
}
}
},
mounted() {
this.pageInfo = {
page: 0,
page_size: 20
}
this.isloadMore = true
this.messageList = []
this.loading = true
this.requestDataList()
},
methods: {
requestDataList: throttle(function () {
if (!this.isloadMore) {
return false
}
this.loading = true
this.pageInfo.page += 1
const bindGameUser = this.bindGameUserList.find(item => item.member_id == this.accountSelect)
const data = {
username: bindGameUser.username || '',
corp_id: this.corp_id,
status: 1,
...this.pageInfo
}
corp_follow_up_task_index(data).then(
(res) => {
this.loading = false
if (res.data.data && res.data.data.length < 20) {
this.isloadMore = false
}
this.messageList = this.messageList.concat(res.data.data)
if (res.data.page_info) {
this.pageInfo = res.data.page_info
}
},
(err) => {
this.loading = false
}
)
}, 500)
}
}
</script>
<style lang="scss" scoped>
.follow-task {
width: 100%;
height: 100%;
background: #fff;
&__scroll {
width: 100%;
height: 100%;
overflow: auto;
overflow-x: hidden;
padding: 16px;
}
&__empty {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
color: #999;
font-size: 14px;
.svg-icon {
font-size: 300px;
margin-bottom: 16px;
}
}
&__list {
display: flex;
flex-direction: column;
gap: 12px;
}
&__item {
display: flex;
flex-direction: column;
gap: 6px;
}
&__date {
font-size: 12px;
color: #c9cdd4;
font-weight: 400;
font-family: 'PingFang SC', sans-serif;
line-height: 1.6666666666666667em;
}
&__content {
background: #f7f8fa;
border-radius: 2px 6px 6px 6px;
padding: 8px 12px;
}
&__detail {
display: flex;
gap: 10px;
}
&__detail-text {
font-size: 14px;
color: #323335;
line-height: 1.5714285714285714em;
font-weight: 400;
font-family: 'PingFang SC', sans-serif;
word-break: break-word;
}
&__no-detail {
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
color: #999;
font-size: 14px;
}
}
</style>
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
</el-input> </el-input>
<el-popover placement="bottom" width="180" trigger="click"> <el-popover placement="bottom" width="180" trigger="click">
<div> <div>
<div>注游戏</div> <div class="mt-[12px]">主游戏名</div>
<el-select <el-select
v-model="form.main_game_id" v-model="form.main_game_id"
filterable filterable
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
> >
</el-option> </el-option>
</el-select> </el-select>
<div>区服</div> <div class="mt-[12px]">区服</div>
<el-select <el-select
v-model.trim="form.server_info" v-model.trim="form.server_info"
filterable filterable
...@@ -61,8 +61,15 @@ ...@@ -61,8 +61,15 @@
> >
</el-option> </el-option>
</el-select> </el-select>
<div class="mt-[12px]">CP角色ID</div>
<el-input
v-model.trim="form.cp_role_id"
:disabled="form.main_game_id == ''"
placeholder="请输入CP角色ID"
>
</el-input>
<div class="flex items-center justify-end"> <div class="flex items-center justify-end">
<el-button type="text" @click="" class="text-[#323335]"> <el-button type="text" @click="resizeData" class="text-[#323335]">
重置 重置
</el-button> </el-button>
<el-button <el-button
...@@ -79,10 +86,10 @@ ...@@ -79,10 +86,10 @@
slot="reference" slot="reference"
class="shrink-0 !h-[32px] !w-[32px] ml-[8px] !p-[7px]" class="shrink-0 !h-[32px] !w-[32px] ml-[8px] !p-[7px]"
> >
<iconpark-icon <svg-icon
name="icon-shaixuan" svgName="icon-shaixuan"
class="text-[16px] text-[#D6D9E0]" class="text-[16px] text-[#D6D9E0]"
></iconpark-icon> ></svg-icon>
</el-button> </el-button>
</el-popover> </el-popover>
</div> </div>
...@@ -103,13 +110,13 @@ ...@@ -103,13 +110,13 @@
>{{ "" }}</el-radio >{{ "" }}</el-radio
> >
<div class="mx-[12px]"> <div class="mx-[12px]">
<iconpark-icon <svg-icon
name="icon-shouqi" svgName="icon-shouqi"
class="text-[18px] text-[#B0B2B5] transition-transform" class="text-[18px] text-[#B0B2B5] transition-transform"
:class="{ 'rotate-90': item.isExpand }" :class="{ 'rotate-90': item.isExpand }"
v-show="!item.loading" v-show="!item.loading"
@click.stop="expandTag(item)" @click.stop="expandTag(item)"
></iconpark-icon> ></svg-icon>
<i class="el-icon-loading" v-show="item.loading"></i> <i class="el-icon-loading" v-show="item.loading"></i>
</div> </div>
<div class="flex-1"> <div class="flex-1">
...@@ -177,7 +184,7 @@ ...@@ -177,7 +184,7 @@
<p class="text"> <p class="text">
{{ {{
moment(item.userDetails.seq_time * 1000).format( moment(item.userDetails.seq_time * 1000).format(
"YYYY-MM-DD" "YYYY-MM-DD",
) )
}} }}
</p> </p>
...@@ -187,7 +194,7 @@ ...@@ -187,7 +194,7 @@
<p class="text"> <p class="text">
{{ {{
moment(item.userDetails.reg_time * 1000).format( moment(item.userDetails.reg_time * 1000).format(
"YYYY-MM-DD" "YYYY-MM-DD",
) )
}} }}
</p> </p>
...@@ -251,6 +258,18 @@ ...@@ -251,6 +258,18 @@
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item
label="请输入CP角色ID"
prop="username"
>
<el-input
v-model.trim="form.cp_role_id"
placeholder="请先选择主游戏"
:disabled="form.main_game_id==''"
class="input-with-select"
>
</el-input>
</el-form-item>
<el-form-item label="请输入区服" prop="server_info"> <el-form-item label="请输入区服" prop="server_info">
<el-select <el-select
v-model.trim="form.server_info" v-model.trim="form.server_info"
...@@ -274,11 +293,7 @@ ...@@ -274,11 +293,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="请输入角色名" prop="role_name"> <el-form-item label="请输入角色名" prop="role_name">
<el-input <el-input v-model.trim="form.role_name" :disabled="form.main_game_id==''" placeholder="请先选择主游戏" class="input-with-select">
v-model.trim="form.role_name"
placeholder="请输入角色"
class="input-with-select"
>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
...@@ -405,6 +420,7 @@ export default { ...@@ -405,6 +420,7 @@ export default {
member_id: "", member_id: "",
username: "", username: "",
role_name: "", role_name: "",
cp_role_id: "",
main_game_id: "", main_game_id: "",
server_info: "", server_info: "",
}, },
...@@ -533,7 +549,7 @@ export default { ...@@ -533,7 +549,7 @@ export default {
}, },
expandTag(item) { expandTag(item) {
const index = this.tableList.findIndex( const index = this.tableList.findIndex(
(i) => i.member_id == item.member_id (i) => i.member_id == item.member_id,
); );
if (!item.userDetails) { if (!item.userDetails) {
this.$set(this.tableList[index], "loading", true); this.$set(this.tableList[index], "loading", true);
...@@ -567,6 +583,7 @@ export default { ...@@ -567,6 +583,7 @@ export default {
role_name: "", role_name: "",
main_game_id: "", main_game_id: "",
server_info: "", server_info: "",
cp_role_id: "",
}; };
this.inputValue = ""; this.inputValue = "";
this.tableList = []; this.tableList = [];
...@@ -670,12 +687,15 @@ export default { ...@@ -670,12 +687,15 @@ export default {
text-align: left; text-align: left;
margin-bottom: 10px; margin-bottom: 10px;
} }
.content-wrapper {
.content {
width: 100%; width: 100%;
overflow: auto; overflow: auto;
padding-bottom: 200px; padding-bottom: 200px;
}
.content {
width: 100%;
padding: 0 10px;
.inputContent { .inputContent {
width: 100%; width: 100%;
} }
......
...@@ -142,6 +142,13 @@ export default { ...@@ -142,6 +142,13 @@ export default {
} }
} }
}, },
show_game_name(item) {
if (process.env.NODE_ENV == "production") {
return item.main_game_id == 187;
} else {
return item.main_game_id == 174;
}
},
addNewUser() { addNewUser() {
this.showLayer = true; this.showLayer = true;
}, },
...@@ -162,7 +169,7 @@ export default { ...@@ -162,7 +169,7 @@ export default {
this.chatUserDetails.self_defined_columns.length > 0 this.chatUserDetails.self_defined_columns.length > 0
) { ) {
this.memberCheckList = this.chatUserDetails.self_defined_columns.map( this.memberCheckList = this.chatUserDetails.self_defined_columns.map(
(item) => item.name (item) => item.name,
); );
} else { } else {
this.memberCheckList = []; this.memberCheckList = [];
......
...@@ -41,6 +41,18 @@ ...@@ -41,6 +41,18 @@
> >
</el-table-column> </el-table-column>
<el-table-column <el-table-column
label="CP角色ID"
prop="cp_role_id"
width="140"
>
</el-table-column>
<el-table-column
label="马甲包"
prop="game_name"
width="140"
>
</el-table-column>
<el-table-column
label="充值金额" label="充值金额"
prop="recharge_total" prop="recharge_total"
> >
......
<template>
<div v-loading="loading" class="role-gift-container">
<div ref="giftList" class="gift-list" @scroll="handleScroll">
<div v-for="item in giftList" :key="item._id" class="gift-item">
<div class="gift-info">
<div v-if="item.gift_package_group_name ">分组: {{ item.gift_package_group_name }}</div>
<div>礼包名称: {{ item.gift_package_name }}</div>
<div>发送时间: {{ item.send_time }}</div>
<div class="giftCodeText">{{ item.code }}</div>
<div>领取角色: <span v-if="item.role_name">{{ item.role_name }}</span> <span v-else>-</span> </div>
<div>W 账号: {{ item.username || '-' }}</div>
<div class="rowFlex spaceBetween columnCenter gift-sender">
<div>发送客服: {{ item.cser_name || '自助链接' }}</div>
<i class="el-icon-document-copy" style="cursor: pointer;" @click="handleCopy(item.code)"></i>
</div>
</div>
</div>
<div v-if="loading" class="loading-more">加载中...</div>
<div v-if="!hasMore && giftList.length > 0" class="no-more">没有更多数据了</div>
<div v-if="giftList.length == 0" class="noContent rowFlex allCenter">
<svg-icon icon-class="noContent" />
</div>
</div>
</div>
</template>
<script>
import { getRoleSendingCodeList } from '@/api/works'
import { debounce,copyText, sendChatMessage} from '@/utils/index'
import { mapState } from 'vuex'
export default {
name: 'roleGift',
data() {
return {
loading: false,
giftList: [],
page: 1,
pageSize: 20,
hasMore: true
}
},
computed: {
...mapState('game', ['accountSelect'])
},
created() {
if(this.accountSelect && this.accountSelect !== ''){
this.fetchGiftList()
} else {
this.$message.warning('请先关联W账号!')
}
},
methods: {
async fetchGiftList() {
if (this.loading || !this.hasMore) return
this.loading = true
try {
const params = {
page: this.page,
page_size: this.pageSize,
member_id: this.accountSelect
}
const res = await getRoleSendingCodeList(params)
if (res.data && res.data.data) {
this.giftList = this.page === 1 ? res.data.data : [...this.giftList, ...res.data.data]
this.hasMore = res.data.data.length === this.pageSize
this.page++
}
} catch (error) {
console.error('获取礼包列表失败:', error)
} finally {
this.loading = false
}
},
handleScroll: debounce(function(e) {
const { scrollHeight, scrollTop, clientHeight } = e.target
if (scrollHeight - scrollTop - clientHeight < 50) {
this.fetchGiftList()
}
}, 500),
handleCopy(code) {
console.log(code, 'code')
copyText('giftCodeText', this)
sendChatMessage(code, 'text')
}
}
}
</script>
<style lang="scss" scoped>
.role-gift-container {
height: calc(100vh - 70px);
width: 100%;
background-color: #fff;
.gift-list {
height: 100%;
overflow-y: auto;
padding: 10px;
.gift-item {
padding: 16px;
background: #F7F8FA;
border-radius: 12px;
border: 1px solid #E5E6EB;
margin-bottom:12px;
.gift-info {
div{
line-height: 26px;
}
.gift-name {
font-weight: 400;
font-size: 14px;
color: #4E5969;
text-align: left;
font-style: normal;
}
.gift-code {
display: flex;
align-items: center;
justify-content: space-between;
border-radius: 4px;
font-family: PingFangSC, PingFang SC;
font-weight: 500;
font-size: 14px;
color: #323335;
text-align: justify;
font-style: normal;
span {
color: #323335;
font-size: 14px;
font-family: PingFangSC-Medium;
}
.el-button {
padding: 5px 12px;
border: 1px solid #dcdfe6;
border-radius: 4px;
font-size: 13px;
color: #606266;
&:hover {
color: #409eff;
border-color: #c6e2ff;
background-color: #ecf5ff;
}
}
}
.gift-sender {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 12px;
color: #4E5969;
line-height: 18px;
text-align: justify;
font-style: normal;
i{
color: #00BF8A;
font-size: 14px;
}
}
}
}
.loading-more,
.no-more,
.empty-data {
text-align: center;
padding: 16px;
color: #999999;
font-size: 13px;
}
}
}
</style>
\ No newline at end of file
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<div v-if="item.gift_package_group_name">分组: {{ item.gift_package_group_name }}</div> <div v-if="item.gift_package_group_name">分组: {{ item.gift_package_group_name }}</div>
<div>礼包名称: {{ item.gift_package_name }}</div> <div>礼包名称: {{ item.gift_package_name }}</div>
<div>发送时间: {{ item.send_time }}</div> <div>发送时间: {{ item.send_time }}</div>
<div>礼包码: {{ item.code }}</div> <div class="giftCodeText">礼包码: {{ item.code }}</div>
<div>领取角色: <span v-if="item.role_name && item.role_name != 0">{{ item.role_name }}</span> <span <div>领取角色: <span v-if="item.role_name && item.role_name != 0">{{ item.role_name }}</span> <span
v-else>-</span> v-else>-</span>
</div> </div>
......
<template>
<el-drawer
title="选择角色"
:visible="dialogVisible"
direction="rtl"
size="80%"
@close="close"
>
<div class="flower-link-dialog">
<el-form
:model="form"
label-position="top"
:rules="rules"
ref="formRef"
>
<el-form-item label="W账号" prop="member_id">
<el-select
v-model="form.member_id"
placeholder="请选择W账号"
style="width: 100%"
@change="handleAccountChange"
>
<el-option
v-for="item in bindGameUserList"
:key="item.member_id"
:label="item.username"
:value="item.member_id"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="角色" prop="role_id">
<el-select
v-model="form.role_id"
placeholder="请选择角色"
style="width: 100%"
@change="handleRoleChange"
>
<el-option
v-for="item in roleList"
:key="item.role_id"
:label="item.role_name"
:value="item.role_id"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="道具" prop="prop_id">
<el-select
v-model="form.prop_id"
placeholder="请选择道具"
style="width: 100%"
:disabled="!form.role_id"
>
<el-option
v-for="item in propList"
:key="item.prop_id"
:label="item.prop_name"
:value="item.prop_id"
></el-option>
</el-select>
</el-form-item>
</el-form>
<div class="drawer-footer">
<el-button @click="close">取消</el-button>
<el-button type="primary" :loading="loading" @click="submitForm">确定</el-button>
</div>
</div>
</el-drawer>
</template>
<script>
import { getRoleHoLo, getPropList, getFlowerLink } from '@/api/game'
export default {
name: 'FlowerLinkDialog',
props: {
dialogVisible: {
type: Boolean,
default: false
},
bindGameUserList: {
type: Array,
default: () => []
},
member_id: {
type: String,
default: ''
}
},
data() {
return {
form: {
member_id: '',
role_id: '',
prop_id: ''
},
rules: {
member_id: [{ required: true, message: '请选择W账号', trigger: 'change' }],
role_id: [{ required: true, message: '请选择角色', trigger: 'change' }],
prop_id: [{ required: true, message: '请选择道具', trigger: 'change' }]
},
loading: false,
roleList: [],
propList: [],
}
},
mounted() {
this.form.member_id = this.member_id
this.handleAccountChange(this.member_id)
},
methods: {
// 处理W账号变化
async handleAccountChange(memberId) {
this.form.role_id = ''
this.form.prop_id = ''
this.roleList = []
this.propList = []
if (memberId) {
await this.requestRoleList(memberId)
}
},
// 处理角色变化
async handleRoleChange(roleId) {
this.form.prop_id = ''
this.propList = []
if (roleId && this.form.member_id) {
await this.requestPropList(this.form.member_id, roleId)
}
},
// 请求角色列表
requestRoleList(memberId) {
return new Promise((resolve, reject) => {
const data = {
api_search_name: '',
member_id: memberId,
search_type: 'list',
page: 1,
page_size: 100
}
getRoleHoLo(data).then(
(res) => {
if (res.status_code == 1) {
this.roleList = res.data.data || []
} else {
this.roleList = []
this.$message.error(res.msg || '获取角色列表失败')
}
resolve()
},
(err) => {
reject(err)
}
)
})
},
// 请求道具列表
requestPropList(memberId, roleId) {
return new Promise((resolve, reject) => {
const data = {
member_id: memberId,
role_id: roleId
}
getPropList(data).then(
(res) => {
if (res.status_code == 1) {
this.propList = res.data.data || []
} else {
this.propList = []
this.$message.error(res.msg || '获取道具列表失败')
}
resolve()
},
(err) => {
reject(err)
}
)
})
},
// 提交表单
submitForm() {
this.$refs.formRef.validate(async (valid) => {
if (valid) {
try {
this.loading = true
// 获取选中的道具信息,用于获取main_game_id
const selectedProp = this.propList.find(item => item.prop_id === this.form.prop_id)
if (!selectedProp) {
this.$message.error('未找到选中的道具信息')
return
}
// 请求种花专属链接
const res = await getFlowerLink({
main_game_id: selectedProp.main_game_id,
prop_id: this.form.prop_id
})
if (res.status_code == 1) {
// 发送成功,通过事件通知父组件
this.$emit('success', res.data.data.url)
this.close()
} else {
this.$message.error(res.msg || '获取种花链接失败')
}
} catch (error) {
this.$message.error(res.msg)
} finally {
this.loading = false
}
}
})
},
// 重置表单
close() {
this.form = {
member_id: this.member_id,
role_id: '',
prop_id: ''
}
this.roleList = []
this.propList = []
this.$emit('update:dialogVisible', false)
if (this.$refs.formRef) {
this.$refs.formRef.resetFields()
}
}
}
}
</script>
<style lang="scss" scoped>
.flower-link-dialog {
padding: 20px;
padding-top: 0px;
}
.el-form {
margin-bottom: 30px;
}
.el-form-item {
margin-bottom: 20px;
}
.el-form-item__label {
font-weight: 500;
}
.drawer-footer {
position: absolute;
bottom: 20px;
left: 20px;
right: 20px;
display: flex;
justify-content: flex-end;
padding-top: 20px;
border-top: 1px solid #ebeef5;
background-color: #fff;
}
</style>
<!-- <!--
* @Author: maoxiya 937667504@qq.com * @Author: maoxiya 937667504@qq.com
* @Date: 2025-08-28 15:59:46 * @Date: 2025-08-28 15:59:46
* @LastEditors: maoxiya 937667504@qq.com * @LastEditors: 金多虾 937667504@qq.com
* @LastEditTime: 2025-09-02 09:51:24 * @LastEditTime: 2026-01-13 10:21:28
* @FilePath: /company_wx_frontend/src/views/works/component/chat/giftCodeDialog.vue * @FilePath: /company_wx_frontend/src/views/works/component/chat/giftCodeDialog.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
--> -->
...@@ -54,6 +54,7 @@ export default { ...@@ -54,6 +54,7 @@ export default {
member_id: '', member_id: '',
username: '', username: '',
role_id: '', role_id: '',
recharge_total: 0,
role_name: '', role_name: '',
}, },
rules: { rules: {
...@@ -81,13 +82,14 @@ export default { ...@@ -81,13 +82,14 @@ export default {
handleMemberIdChange(value) { handleMemberIdChange(value) {
this.form.role_id = '' this.form.role_id = ''
this.form.role_name = '' this.form.role_name = ''
this.form.recharge_total = 0
const userInfo = this.bindGameUserList.find(item => item.value === value) const userInfo = this.bindGameUserList.find(item => item.value === value)
this.form.username = userInfo.label || userInfo.username this.form.username = userInfo.label || userInfo.username
this.form.member_id = value this.form.member_id = value
}, },
handleSelectionChange(roleInfo) { handleSelectionChange(roleInfo) {
console.log(roleInfo, 'roleInfo')
this.form.role_name = roleInfo.label || '' this.form.role_name = roleInfo.label || ''
this.form.recharge_total = roleInfo.recharge_total || 0
}, },
closeDialog() { closeDialog() {
this.$emit('update:dialogVisible', false) this.$emit('update:dialogVisible', false)
......
...@@ -97,6 +97,12 @@ ...@@ -97,6 +97,12 @@
> >
下载二维码 下载二维码
</p> </p>
<!-- h5 安卓游戏 IOS游戏 发送分身包 -->
<div v-if="[2].includes(item.game_type)">
<p class="sendLink" @click="sendTransferCloneGame(2,items)">发送分身包-H5</p>
<p class="sendLink" @click="sendTransferCloneGame(3,items)">发送分身包-安卓</p>
<p class="sendLink" @click="sendTransferCloneGame(4,items)">发送分身包-IOS</p>
</div>
</div> </div>
<el-button <el-button
slot="reference" slot="reference"
...@@ -279,48 +285,23 @@ ...@@ -279,48 +285,23 @@
<p>{{ items.label + "/" + items.id }}</p> <p>{{ items.label + "/" + items.id }}</p>
<!--game_type: 1 微信小游戏 2 H5 游戏 3 安卓游戏 4 IOS 游戏 5 抖音小游戏 --> <!--game_type: 1 微信小游戏 2 H5 游戏 3 安卓游戏 4 IOS 游戏 5 抖音小游戏 -->
<!-- 微信小游戏 安卓游戏 IOS游戏 处理逻辑 --> <!-- 微信小游戏 安卓游戏 IOS游戏 处理逻辑 -->
<el-popover <el-popover v-if="items.game_type == 1 || items.game_type == 3 || items.game_type == 4 || items.game_type == 5" placement="top" trigger="click">
v-if=" <div v-if="items.game_type!=5">
items.game_type == 1 || <p class="sendLink" @click="sendChannelGame(items, item)">发送链接/渠道二维码</p>
items.game_type == 3 || <p class="sendLink" @click="handleGameType(items, item, item.game_type, index)">发送落地页</p>
items.game_type == 4
"
placement="top"
trigger="click"
>
<p class="sendLink" @click="sendChannelGame(items, item)">
发送链接/渠道二维码
</p>
<p
class="sendLink"
@click="
handleGameType(items, item, item.game_type, index)
"
>
发送落地页
</p>
<div v-if="items.game_type == 1"> <div v-if="items.game_type == 1">
<!-- 发送 H5 安卓分身包 --> <!-- 发送 H5 安卓分身包 -->
<p <p class="sendLink" @click="sendH5CloneGame(items, 'android')">发送H5-安卓分身包</p>
class="sendLink"
@click="sendH5CloneGame(items, 'android')"
>
发送H5-安卓分身包
</p>
<!-- 发送 H5 IOS 分身包 --> <!-- 发送 H5 IOS 分身包 -->
<p <p class="sendLink" @click="sendH5CloneGame(items, 'ios')">发送H5-IOS分身包</p>
class="sendLink"
@click="sendH5CloneGame(items, 'ios')"
>
发送H5-IOS分身包
</p>
</div> </div>
<el-button </div>
slot="reference" <!-- 抖音小游戏发送落地页 -->
size="mini" <div v-else>
:disabled="accountSelect == ''" <p class="sendLink" @click="handleGameType(items, item, item.game_type, index)">发送落地页</p>
>发送</el-button </div>
> <el-button slot="reference" size="mini" :disabled="accountSelect == ''">发送</el-button>
</el-popover> </el-popover>
<el-button <el-button
v-else v-else
...@@ -426,6 +407,7 @@ import { ...@@ -426,6 +407,7 @@ import {
getClonePackageLink, getClonePackageLink,
getLandingPageConfig, getLandingPageConfig,
getMemberTransStatus, getMemberTransStatus,
memberRegGameCloneLink
} from "@/api/game"; } from "@/api/game";
import { import {
getRecentSendLog, getRecentSendLog,
...@@ -492,6 +474,7 @@ export default { ...@@ -492,6 +474,7 @@ export default {
showSendChannel: false, showSendChannel: false,
channelInfoList: {}, channelInfoList: {},
transMemberStatus: true, transMemberStatus: true,
h5CloneGameInfo: {},
qrCodeValue: "", // 二维码内容 qrCodeValue: "", // 二维码内容
qrCodeSize: 200, // 二维码大小 qrCodeSize: 200, // 二维码大小
}; };
...@@ -834,13 +817,17 @@ export default { ...@@ -834,13 +817,17 @@ export default {
item.children && item.children &&
item.children.length > 0 item.children.length > 0
) { ) {
// 过滤掉 game_name 为"破日开天"的数据 // 过滤掉 game_name 为"破日开天"的数据 英雄霸业 741:独步天龙 912:神权之战 繁华梦/2274
const filteredChildren = item.children.filter((child) => { const filteredChildren = item.children.filter((child) => {
return ( return (
child.game_name !== "破日开天" && child.game_name !== "破日开天" &&
child.game_name !== "英雄霸业" && child.game_name !== "英雄霸业" &&
child.game_id !== "741" && child.game_id !== "741" &&
child.game_id !== "912" child.game_id !== "912" &&
child.game_name !== '神权之战' &&
child.game_id !== '741' &&
child.game_id !== '2274' &&
child.game_name !== '繁华梦'
); );
}); });
this.$set( this.$set(
...@@ -1035,13 +1022,6 @@ export default { ...@@ -1035,13 +1022,6 @@ export default {
).username; ).username;
passwardEncryption({ member_id: this.accountSelect }) passwardEncryption({ member_id: this.accountSelect })
.then((res) => { .then((res) => {
// const list = [
// {
// msgtype: 'text',
// text: { content: `账号:${username} \n密码:${res.data.password}`, key: res.data.key, iv: res.data.iv }
// }
// ]
// this.set_sendSkillMessage(list)
this.sendChatMessage( this.sendChatMessage(
`账号:${username} \n密码:${res.data.password}`, `账号:${username} \n密码:${res.data.password}`,
"text" "text"
...@@ -1053,7 +1033,6 @@ export default { ...@@ -1053,7 +1033,6 @@ export default {
const list = [ const list = [
{ msgtype: "text", text: { content: `账号:${username}` } }, { msgtype: "text", text: { content: `账号:${username}` } },
]; ];
// this.set_sendSkillMessage(list)
this.sendChatMessage(`账号:${username}`, "text"); this.sendChatMessage(`账号:${username}`, "text");
item.type = 1; item.type = 1;
this.sendGameLog(item); this.sendGameLog(item);
...@@ -1094,7 +1073,6 @@ export default { ...@@ -1094,7 +1073,6 @@ export default {
}, },
}, },
]; ];
// this.set_sendSkillMessage(list)
this.sendChatMessage( this.sendChatMessage(
`${str}${item.url} \n账号:${username} \n密码:${res.data.password}`, `${str}${item.url} \n账号:${username} \n密码:${res.data.password}`,
"text" "text"
...@@ -1110,7 +1088,6 @@ export default { ...@@ -1110,7 +1088,6 @@ export default {
text: { content: `${str}${item.url} \n账号:${username}` }, text: { content: `${str}${item.url} \n账号:${username}` },
}, },
]; ];
// this.set_sendSkillMessage(list)
this.sendChatMessage(`${str}${item.url} \n账号:${username}`, "text"); this.sendChatMessage(`${str}${item.url} \n账号:${username}`, "text");
this.sendGameLog(item); this.sendGameLog(item);
console.log(err); console.log(err);
...@@ -1119,7 +1096,6 @@ export default { ...@@ -1119,7 +1096,6 @@ export default {
// 发送游戏落地页 // 发送游戏落地页
startSendPage(value) { startSendPage(value) {
console.log(value, "value"); console.log(value, "value");
// this.set_sendSkillMessage(list)
this.getMediaId(value, "image"); this.getMediaId(value, "image");
}, },
// 转端发送落地页面 // 转端发送落地页面
...@@ -1135,6 +1111,53 @@ export default { ...@@ -1135,6 +1111,53 @@ export default {
); );
this.showSendPage = true; this.showSendPage = true;
}, 500), }, 500),
// 转端发送游戏分身包 h5 安卓游戏 IOS游戏 发送分身包
async sendTransferCloneGame(type,items) {
if(!this.h5CloneGameInfo?.data?.h5_download_url){
this.h5CloneGameInfo = await memberRegGameCloneLink({ member_id: this.accountSelect ,game_id:items.game_id}) || {}
}
if (this.h5CloneGameInfo?.status_code == 1) {
// 通过 type 判断 用 switch
switch (type) {
case 2:
if (!this.h5CloneGameInfo?.data?.h5_download_url) {
this.$message.warning('H5安卓分身包链接不存在,请联系掌游配置')
return
}
break
case 3:
if (!this.h5CloneGameInfo?.data?.android_download_url) {
this.$message.warning('安卓分身包链接不存在,请联系掌游配置')
return
}
break
case 4:
if (!this.h5CloneGameInfo?.data?.ios_download_url) {
this.$message.warning('IOS分身包链接不存在,请联系掌游配置')
return
}
break
default:
this.$message.warning('不支持的游戏类型')
return
}
let srt = ''
switch (type) {
case 2:
srt = this.h5CloneGameInfo?.data?.h5_download_url
break
case 3:
srt = this.h5CloneGameInfo?.data?.android_download_url
break
case 4:
srt = this.h5CloneGameInfo?.data?.ios_download_url
break
}
this.sendChatMessage(srt, "text");
} else {
this.$message.warning(this.h5CloneGameInfo?.msg)
}
},
// 转端发送游戏二维码 // 转端发送游戏二维码
sendDownLoadQrCode: throttleStart(async function (items, type, index) { sendDownLoadQrCode: throttleStart(async function (items, type, index) {
if (!this.transMemberStatus) { if (!this.transMemberStatus) {
...@@ -1339,14 +1362,12 @@ export default { ...@@ -1339,14 +1362,12 @@ export default {
page: data.share_data.page, page: data.share_data.page,
imgUrl: data.share_data.share_img, imgUrl: data.share_data.share_img,
}; };
// this.set_sendSkillMessage(list)
this.sendChatMessage(miniprogramInfo, "miniprogram"); this.sendChatMessage(miniprogramInfo, "miniprogram");
const game_data = this.$clone(data.game_data); const game_data = this.$clone(data.game_data);
game_data.type = 3; game_data.type = 3;
console.log(game_data, "data----------"); console.log(game_data, "data----------");
this.sendGameLog(game_data); this.sendGameLog(game_data);
} else { } else {
// this.set_sendSkillMessage(list)
this.getMediaId(data.game_data.game_url, "image"); this.getMediaId(data.game_data.game_url, "image");
this.sendGameLog(data.game_data); this.sendGameLog(data.game_data);
} }
...@@ -1399,8 +1420,6 @@ export default { ...@@ -1399,8 +1420,6 @@ export default {
}, },
}, },
]; ];
// 这里需要特殊处理,因为有taskInfo参数
// this.set_sendSkillMessage(list)
this.sendChatMessage( this.sendChatMessage(
`${str}${item.game_url} \n账号:${username} \n密码:${res.data.password}`, `${str}${item.game_url} \n账号:${username} \n密码:${res.data.password}`,
"text" "text"
...@@ -1414,12 +1433,7 @@ export default { ...@@ -1414,12 +1433,7 @@ export default {
const params = { const params = {
main_game_id: items.main_game_id, main_game_id: items.main_game_id,
weixin_blongs_id: items.weixin_blongs_id, weixin_blongs_id: items.weixin_blongs_id,
type: type: items.game_type == 1 || items.game_type == 5 ? 2 : items.game_type == 3 || items.game_type == 4 ? 1 : ''
items.game_type == 1
? 2
: items.game_type == 3 || items.game_type == 4
? 1
: "",
}; };
const res = await getLandingPageConfig(params); const res = await getLandingPageConfig(params);
if (res.status_code === 1 && res.data) { if (res.status_code === 1 && res.data) {
...@@ -1511,16 +1525,10 @@ export default { ...@@ -1511,16 +1525,10 @@ export default {
}, },
// 主方法 // 主方法
async handleGameType(items, item, type, index) { async handleGameType(items, item, type, index) {
if ( if ((items.game_type == 1 || items.game_type == 3 || items.game_type == 4 || items.game_type == 5) && items.main_game_id && items.weixin_blongs_id) {
(items.game_type == 1 ||
items.game_type == 3 ||
items.game_type == 4) &&
items.main_game_id &&
items.weixin_blongs_id
) {
const result = await this.getLandingPageConfig(items, item); const result = await this.getLandingPageConfig(items, item);
if (result && result.data?.data?.tag) { if (result && result.data?.data?.tag) {
if (items.game_type == 1) { if (items.game_type == 1 || items.game_type == 5) {
// 处理微信小程序游戏 // 处理微信小程序游戏
this.handleWechatMiniGame(items, item, index); this.handleWechatMiniGame(items, item, index);
} else { } else {
...@@ -1541,15 +1549,6 @@ export default { ...@@ -1541,15 +1549,6 @@ export default {
// 小游戏游戏确认 // 小游戏游戏确认
async handleWxGameConfirm(value) { async handleWxGameConfirm(value) {
console.log(value, "value"); console.log(value, "value");
// const list = [
// {
// msgtype: 'image',
// image: {
// picurl: value
// }
// }
// ]
// this.set_sendSkillMessage(list)
this.getMediaId(value, "image"); this.getMediaId(value, "image");
}, },
SendTransAppGameClose() { SendTransAppGameClose() {
...@@ -1561,15 +1560,6 @@ export default { ...@@ -1561,15 +1560,6 @@ export default {
// 安卓或者 IOS 游戏处理 // 安卓或者 IOS 游戏处理
handleAppGameConfirm(data) { handleAppGameConfirm(data) {
this.selectedAppGameList = []; this.selectedAppGameList = [];
// const list = [
// {
// msgtype: 'text',
// text: {
// content: `游戏地址:${data.landing_page_url} \n账号:${data.username} \n密码:${data.password}`
// }
// }
// ]
// this.set_sendSkillMessage(list)
this.sendChatMessage( this.sendChatMessage(
`游戏地址:${data.landing_page_url} \n账号:${data.username} \n密码:${data.password}`, `游戏地址:${data.landing_page_url} \n账号:${data.username} \n密码:${data.password}`,
"text" "text"
......
...@@ -326,6 +326,7 @@ ...@@ -326,6 +326,7 @@
this.$emit('confirm', res.data.data) this.$emit('confirm', res.data.data)
this.$message.success('发送成功') this.$message.success('发送成功')
} }
} catch (error) { } catch (error) {
this.loading = false this.loading = false
console.error('获取链接失败:', error) console.error('获取链接失败:', error)
......
...@@ -3,18 +3,20 @@ ...@@ -3,18 +3,20 @@
<el-drawer <el-drawer
title="选择游戏" title="选择游戏"
:visible="show" :visible="show"
size="360px" size="80%"
append-to-body
@close="close" @close="close"
> >
<div class="sendTransWxGame">
<el-form ref="wxGameForm" :model="wxGameForm" :rules="wxGameRules" label-position="top" class="game-select-container"> <el-form ref="wxGameForm" :model="wxGameForm" :rules="wxGameRules" label-position="top" class="game-select-container">
<!-- 微信小游戏 --> <!-- 微信/抖音小游戏 -->
<el-form-item label=""> <el-form-item label="">
<template slot="label"> <template slot="label">
<p class="formLabel">微信小游戏</p> <p class="formLabel">微信/抖音小游戏</p>
</template> </template>
<el-select <el-select
v-model="wxGameForm.wx_game_send_id" v-model="wxGameForm.wx_game_send_id"
placeholder="请选择微信小游戏" placeholder="请选择微信/抖音小游戏"
style="width: 100%" style="width: 100%"
disabled disabled
> >
...@@ -27,22 +29,71 @@ ...@@ -27,22 +29,71 @@
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label=""> <el-form-item label="选择渠道">
<el-select <el-select
v-model="wxGameForm.wx_game_channel" v-model="wxGameForm.wx_game_channel"
placeholder="请选择渠道" placeholder="请选择渠道"
style="width: 100%" style="width: 100%"
:clearable="true" :clearable="true"
@change="handleChannelChange"
> >
<el-option <el-option
v-for="(item,index) in wxGameChannelList" v-for="(item,index) in wxGameChannelList"
:key="index" :key="item.key"
:label="item.name" :label="item.name"
:value="item.key" :value="item.key"
> >
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- 选择背景图 新增背景图的选项 -->
<el-form-item v-if="backgroundImgsList.length > 0" label="" style="margin-bottom: 100px;">
<template slot="label">
<p class="formLabel">
<span class="required-mark">*</span>
<span>背景图</span>
</p>
</template>
<el-radio-group v-model="wxGameForm.selectedBackgroundIndex" @change="handleBackgroundChange">
<div class="background-options">
<el-radio
v-for="(item, index) in backgroundImgsList"
:key="item.background_img"
:label="index"
class="background-radio-item"
>
<div class="background-card">
<div class="background-preview-wrapper">
<img
:ref="`bgImg_${index}`"
:src="item.background_img"
class="background-preview"
alt="背景图预览"
@load="handleBackgroundImageLoad(index, item)"
>
<!-- 二维码叠加显示 -->
<img
v-if="channelQrcode && item.qrStyle"
:src="channelQrcode"
class="background-qrcode"
:style="item.qrStyle"
alt="二维码"
>
</div>
<!-- 左上角小眼睛图标 -->
<div class="eye-icon" :class="{'eye-icon-checked': wxGameForm.selectedBackgroundIndex === index}" @click.stop="showPreview(item, index)">
<i class="el-icon-view"></i>
</div>
<!-- 右上角选中/未选中图标 -->
<div class="status-icon">
<i v-if="wxGameForm.selectedBackgroundIndex === index" class="el-icon-success status-icon-checked"></i>
<svg-icon v-else icon-class="uncheck" class="status-icon-unchecked"></svg-icon>
</div>
</div>
</el-radio>
</div>
</el-radio-group>
</el-form-item>
</el-form> </el-form>
<span class="dialog-footer rowFlex"> <span class="dialog-footer rowFlex">
<el-button class="btn" @click="close" size="small">取消</el-button> <el-button class="btn" @click="close" size="small">取消</el-button>
...@@ -75,6 +126,40 @@ ...@@ -75,6 +126,40 @@
> >
</div> </div>
</div> </div>
<!-- 大图预览弹窗 -->
<el-drawer
title="预览"
:visible.sync="previewVisible"
size="80%"
:modal="false"
:close-on-click-modal="false"
append-to-body
class="preview-dialog"
>
<div class="preview-content">
<div class="preview-wrapper" v-if="previewImageInfo">
<img
ref="previewBgImgDisplay"
:src="previewImageInfo.background_img"
class="preview-background"
alt="背景图"
@load="handlePreviewImageLoad"
>
<img
v-if="previewImageInfo.channel_qrcode"
ref="previewQrImgDisplay"
:src="previewImageInfo.channel_qrcode"
class="preview-qrcode"
:style="previewQrcodeStyle"
alt="二维码"
>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="previewVisible = false">关闭</el-button>
</span>
</el-drawer>
</div>
</el-drawer> </el-drawer>
</template> </template>
...@@ -119,14 +204,20 @@ ...@@ -119,14 +204,20 @@
wxGameForm: { wxGameForm: {
wx_game_send_id: '', wx_game_send_id: '',
wx_game_send_info: {}, wx_game_send_info: {},
wx_game_channel: '' wx_game_channel: '',
selectedBackgroundIndex: 0 // 选中的背景图索引
}, },
messageInfo: null, messageInfo: null,
handleConfirmWithDebounce: {}, handleConfirmWithDebounce: {},
wxGameChannelList: [], wxGameChannelList: [],
backgroundImgsList: [], // 背景图列表
channelQrcode: '', // 二维码链接
previewVisible: false, // 预览弹窗显示状态
previewImageInfo: null, // 预览图片信息(包含背景图和二维码)
previewQrcodeStyle: {}, // 预览二维码样式
wxGameRules: { wxGameRules: {
wx_game_send_id: [ wx_game_send_id: [
{ required: true, message: '请选择微信小游戏', trigger: 'change' } { required: true, message: '请选择微信/抖音小游戏', trigger: 'change' }
], ],
wx_game_channel: [ wx_game_channel: [
{ required: true, message: '请选择渠道', trigger: 'change' } { required: true, message: '请选择渠道', trigger: 'change' }
...@@ -150,6 +241,8 @@ ...@@ -150,6 +241,8 @@
wx_game_channel: '' wx_game_channel: ''
} }
this.wxGameChannelList = [] this.wxGameChannelList = []
this.backgroundImgsList = []
this.channelQrcode = ''
this.closeMessage() this.closeMessage()
this.loading = false this.loading = false
// 清理图片资源 // 清理图片资源
...@@ -320,6 +413,19 @@ ...@@ -320,6 +413,19 @@
} }
}) })
}, },
// 处理渠道选择变化
async handleChannelChange(value) {
if (!value) {
// 清空渠道时,清空背景图列表
this.backgroundImgsList = []
this.channelQrcode = ''
this.wxGameForm.selectedBackgroundIndex = 0
this.imageInfo = {}
return
}
// 选择渠道后自动请求接口
await this.handleWxGameChannel()
},
async uploadCos(File) { async uploadCos(File) {
const uploadConfig = { const uploadConfig = {
dir: '/company_wx/service/avatars/' dir: '/company_wx/service/avatars/'
...@@ -336,7 +442,30 @@ ...@@ -336,7 +442,30 @@
} }
}, },
handleConfirm() { handleConfirm() {
this.handleWxGameChannel() if (!this.imageInfo.background_img ) {
this.$message.warning('请先选择背景图')
return false
}
if (!this.imageInfo.channel_qrcode) {
this.$message.warning('渠道二维码图片不存在')
return false
}
// 检查是否选择了渠道
if (!this.wxGameForm.wx_game_channel) {
this.$message.warning('请选择渠道')
return
}
// 如果有背景图列表,直接合成图片
if (this.backgroundImgsList.length > 0) {
this.confirmAndCompose()
} else {
// 如果没有背景图列表,说明接口返回的是旧格式,直接合成
if (this.imageInfo.background_img) {
this.confirmAndCompose()
} else {
this.$message.warning('请先选择渠道')
}
}
}, },
// 保存微信小游戏的信息 // 保存微信小游戏的信息
...@@ -387,11 +516,37 @@ ...@@ -387,11 +516,37 @@
const linkRes = await getLandingPageMemberLink(params) const linkRes = await getLandingPageMemberLink(params)
console.log('获取到的落地页数据:', linkRes) console.log('获取到的落地页数据:', linkRes)
if (linkRes?.data?.data) { if (linkRes?.data?.data) {
// 检查返回的数据结构 const responseData = linkRes.data.data
console.log('设置前的imageInfo:', this.imageInfo) // 保存二维码链接
this.imageInfo = linkRes.data.data this.channelQrcode = responseData.channel_qrcode || ''
console.log('设置后的imageInfo:', this.imageInfo)
await this.composeImage() // 处理背景图列表
if (responseData.background_imgs && responseData.background_imgs.length > 0) {
// 如果有背景图列表,使用列表中的图片
// 初始化二维码样式
this.backgroundImgsList = responseData.background_imgs.map(item => ({
...item,
qrStyle: null // 等待图片加载后计算
}))
// 默认选中第一个
this.wxGameForm.selectedBackgroundIndex = 0
// 设置默认的 imageInfo
this.updateImageInfo(0)
// 不立即合成,等待用户选择后点击确认
this.loading = false
return
} else {
// 如果没有背景图列表,使用默认背景图(兼容旧逻辑)
this.backgroundImgsList = []
this.imageInfo = {
background_img: responseData.background_img || '',
channel_qrcode: this.channelQrcode,
'x-coordinate': responseData['x-coordinate'] || 0,
'y-coordinate': responseData['y-coordinate'] || 0
}
// 不立即合成,等待用户点击确认
this.loading = false
}
} else { } else {
throw new Error('获取落地页数据失败') throw new Error('获取落地页数据失败')
} }
...@@ -405,19 +560,179 @@ ...@@ -405,19 +560,179 @@
}, },
close() { close() {
this.closeMessage() this.closeMessage()
// 清理背景图相关数据
this.backgroundImgsList = []
this.channelQrcode = ''
this.wxGameForm.selectedBackgroundIndex = 0
this.imageInfo = {}
this.previewVisible = false
this.previewImageInfo = null
this.$emit('close') this.$emit('close')
this.$emit('update:show', false) this.$emit('update:show', false)
},
// 处理背景图选择变化
handleBackgroundChange(index) {
this.updateImageInfo(index)
},
// 更新 imageInfo
updateImageInfo(index) {
if (this.backgroundImgsList.length > 0 && this.backgroundImgsList[index]) {
const selectedBg = this.backgroundImgsList[index]
this.imageInfo = {
background_img: selectedBg.background_img,
channel_qrcode: this.channelQrcode,
'x-coordinate': selectedBg['x-coordinate'] || 0,
'y-coordinate': selectedBg['y-coordinate'] || 0
}
}
},
// 确认选择背景图后合成图片
async confirmAndCompose() {
if (this.backgroundImgsList.length === 0) {
// 如果没有背景图列表,直接合成(兼容旧逻辑)
await this.composeImage()
return
} }
// 确保 imageInfo 已设置
if (!this.imageInfo.background_img) {
this.updateImageInfo(this.wxGameForm.selectedBackgroundIndex)
} }
await this.composeImage()
},
// 显示大图预览
showPreview(item, index) {
// 构建预览图片信息
const previewInfo = {
background_img: item.background_img,
channel_qrcode: this.channelQrcode,
'x-coordinate': item['x-coordinate'] || 0,
'y-coordinate': item['y-coordinate'] || 0
}
this.previewImageInfo = previewInfo
this.previewVisible = true
// 重置二维码样式,等待图片加载后计算
this.previewQrcodeStyle = {}
// 等待 DOM 更新后,检查图片是否已加载
this.$nextTick(() => {
if (this.$refs.previewBgImgDisplay) {
const bgImg = this.$refs.previewBgImgDisplay
// 如果图片已经加载完成(complete 属性为 true),直接计算样式
if (bgImg.complete && bgImg.naturalWidth > 0) {
this.calculatePreviewQrcodeStyle()
} }
</script> }
})
},
// 处理预览背景图加载完成
handlePreviewImageLoad() {
this.calculatePreviewQrcodeStyle()
},
// 计算预览二维码样式
calculatePreviewQrcodeStyle() {
if (!this.previewImageInfo || !this.$refs.previewBgImgDisplay) {
return
}
const bgImg = this.$refs.previewBgImgDisplay
// 参考生成图片时的逻辑:背景图宽度固定为 750px
const bgOriginalWidth = 750 // 原始宽度(生成图片时的宽度)
// 等待下一帧,确保图片已渲染
this.$nextTick(() => {
// 获取背景图的实际显示尺寸(参考生成图片时的逻辑)
// 使用 getBoundingClientRect 获取实际渲染尺寸
const imgRect = bgImg.getBoundingClientRect()
const displayWidth = imgRect.width
const displayHeight = imgRect.height
// 如果图片还没有渲染完成,延迟重试
if (displayWidth === 0 || displayHeight === 0) {
setTimeout(() => {
this.calculatePreviewQrcodeStyle()
}, 100)
return
}
// 计算缩放比例(基于实际显示宽度与原始宽度的比例)
// 参考生成图片时:width = 750, height = (naturalHeight / naturalWidth) * width
const scale = displayWidth / bgOriginalWidth
// 计算二维码位置和尺寸(参考生成图片时的逻辑)
// x-coordinate 和 y-coordinate 是相对于 750px 宽度的绝对位置
// 二维码直接使用坐标值,相对于背景图容器定位
const qrSize = 180 * scale
const qrLeft = (this.previewImageInfo['x-coordinate'] || 0) * scale
const qrTop = (this.previewImageInfo['y-coordinate'] || 0) * scale
this.previewQrcodeStyle = {
position: 'absolute',
left: `${qrLeft}px`,
top: `${qrTop}px`,
width: `${qrSize}px`,
height: `${qrSize}px`
}
})
},
// 处理背景图列表中的图片加载完成
handleBackgroundImageLoad(index, item) {
const bgImgRef = this.$refs[`bgImg_${index}`]
// Vue 2 中,ref 可能是数组或单个元素
const bgImg = Array.isArray(bgImgRef) ? bgImgRef[0] : bgImgRef
if (!bgImg) {
return
}
// 参考生成图片时的逻辑:背景图宽度固定为 750px
const bgOriginalWidth = 750 // 原始宽度(生成图片时的宽度)
// 等待下一帧,确保图片已渲染
this.$nextTick(() => {
// 获取背景图的实际显示尺寸(参考生成图片时的逻辑)
// 使用 getBoundingClientRect 获取实际渲染尺寸
const imgRect = bgImg.getBoundingClientRect()
const displayWidth = imgRect.width
const displayHeight = imgRect.height
// 计算缩放比例(基于实际显示宽度与原始宽度的比例)
// 参考生成图片时:width = 750, height = (naturalHeight / naturalWidth) * width
const scale = displayWidth / bgOriginalWidth
// 计算二维码位置和尺寸(参考生成图片时的逻辑)
// x-coordinate 和 y-coordinate 是相对于 750px 宽度的绝对位置
// 二维码直接使用坐标值,相对于背景图容器定位
const qrSize = 180 * scale
const qrLeft = (item['x-coordinate'] || 0) * scale
const qrTop = (item['y-coordinate'] || 0) * scale
// 更新二维码样式
this.$set(this.backgroundImgsList[index], 'qrStyle', {
position: 'absolute',
left: `${qrLeft}px`,
top: `${qrTop}px`,
width: `${qrSize}px`,
height: `${qrSize}px`
})
})
}
}
}
</script>
<style scoped lang="scss"> <style scoped lang="scss">
.formLabel{ .formLabel{
font-size: 16px; font-size: 16px;
font-weight: 500; font-weight: 500;
} }
.dialog-footer{ .sendTransWxGame{
width: 100%;
height: 100%;
overflow: auto;
padding-bottom: 50px;
}
.dialog-footer{
width: calc(100%); width: calc(100%);
height: auto; height: auto;
position: absolute; position: absolute;
...@@ -432,8 +747,8 @@ ...@@ -432,8 +747,8 @@
width:84px ; width:84px ;
height: 32px; height: 32px;
} }
} }
.game-select-container { .game-select-container {
padding: 0 20px; padding: 0 20px;
::v-deep .el-icon-circle-close{ ::v-deep .el-icon-circle-close{
color: #C0C4CC !important; color: #C0C4CC !important;
...@@ -442,36 +757,190 @@ ...@@ -442,36 +757,190 @@
line-height: 32px; line-height: 32px;
padding: 3px; padding: 3px;
} }
} }
.compose-container { .compose-container {
position: fixed; position: fixed;
left: -9999px; left: -9999px;
top: -9999px; top: -9999px;
overflow: hidden; overflow: hidden;
z-index: -1; z-index: -1;
} }
.image-wrapper { .image-wrapper {
position: relative; position: relative;
display: none; display: none;
font-size: 0; font-size: 0;
width: 750px; /* 固定容器宽度 */ width: 750px; /* 固定容器宽度 */
} }
.background-img { .background-img {
display: block; display: block;
width: 750px !important; /* 固定宽度 */ width: 750px !important; /* 固定宽度 */
height: auto !important; /* 高度自适应 */ height: auto !important; /* 高度自适应 */
object-fit: contain; object-fit: contain;
} }
.qr-code { .qr-code {
position: absolute; position: absolute;
display: block; display: block;
width: 180px !important; width: 180px !important;
height: 180px !important; height: 180px !important;
object-fit: contain; object-fit: contain;
pointer-events: none; pointer-events: none;
}
.required-mark {
color: #f53f3f;
margin-right: 4px;
}
.background-options {
display: flex;
flex-wrap: wrap;
gap: 16px;
width: 100%;
}
.background-radio-item {
margin-right: 0 !important;
margin-bottom: 0 !important;
width: 120px;
::v-deep .el-radio__input {
display: none;
}
::v-deep .el-radio__label {
padding-left: 0;
cursor: pointer;
width: 100%;
} }
</style> }
.background-card {
position: relative;
width: 100%;
height: 200px;
background: #fff;
border: 1.5px solid #e5e7eb;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
transition: all 0.3s;
padding: 10px 30px;
}
.background-radio-item.is-checked .background-card {
border-color: #00bf8a;
}
.background-preview-wrapper {
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
.background-preview {
width: 100%;
object-fit:100% 100%;
pointer-events: none;
border-radius: 5px;
}
.background-qrcode {
pointer-events: none;
object-fit: contain;
}
.eye-icon {
position: absolute;
left: 6.5px;
top: 6.5px;
width: 16px;
height: 16px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
z-index: 10;
i {
font-size: 16px;
color: #C9CDD4;
}
&:hover {
opacity: 0.8;
color: #00bf8a;
}
}
.eye-icon-checked {
i{
color: #00bf8a;
}
}
.status-icon {
position: absolute;
right: 6.5px;
top: 6.5px;
width: 16px;
height: 16px;
z-index: 10;
.status-icon-checked {
font-size: 14px;
color: #00bf8a;
width: 14px;
height: 14px;
display: flex;
align-items: center;
justify-content: center;
}
.status-icon-unchecked {
font-size: 14px;
color: #b1b2b4;
width: 14px;
height: 14px;
display: flex;
align-items: center;
justify-content: center;
}
}
.preview-dialog {
height: auto;
background: none;
}
.preview-content {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
min-height: 400px;
padding: 20px;
padding-top: 0;
}
.preview-wrapper {
position: relative;
display: flex;
justify-content: center;
}
.preview-background {
display: block;
border-radius: 10px;
max-width: 100%;
}
.preview-qrcode {
object-fit: contain;
pointer-events: none;
}
</style>
\ No newline at end of file
...@@ -147,7 +147,6 @@ export default { ...@@ -147,7 +147,6 @@ export default {
// list = [{ msgtype: 'text', text: { content: str }}] // list = [{ msgtype: 'text', text: { content: str }}]
this.sendChatMessage(str,'text') this.sendChatMessage(str,'text')
} }
// this.set_sendSkillMessage(list)
// 3:召回 召回的时候请求召回染色的接口 // 3:召回 召回的时候请求召回染色的接口
this.recallChannelSeq() this.recallChannelSeq()
} }
......
...@@ -37,9 +37,6 @@ export default { ...@@ -37,9 +37,6 @@ export default {
close() { close() {
this.$emit('update:show', false) this.$emit('update:show', false)
}, },
// const list = [{ msgtype: 'text', text: { content: `${str}${item.url}` }}]
// this.set_sendSkillMessage(list)
onConfirm() { onConfirm() {
if (this.webForm.channel_id === '') { if (this.webForm.channel_id === '') {
this.$message.warning('请选择渠道') this.$message.warning('请选择渠道')
...@@ -105,8 +102,6 @@ export default { ...@@ -105,8 +102,6 @@ export default {
// list = [{ msgtype: 'text', text: { content: str }}] // list = [{ msgtype: 'text', text: { content: str }}]
this.sendChatMessage(str,'text') this.sendChatMessage(str,'text')
} }
// this.set_sendSkillMessage(list)
// this.sendChatMessage(str,'text')
// 3:召回 召回的时候请求召回染色的接口 // 3:召回 召回的时候请求召回染色的接口
this.recallChannelSeq() this.recallChannelSeq()
} }
......
...@@ -2,262 +2,373 @@ ...@@ -2,262 +2,373 @@
<div class="vipToolsContent"> <div class="vipToolsContent">
<div class="gameList"> <div class="gameList">
<!-- VIP 自助工具 暂时不显示 --> <!-- VIP 自助工具 暂时不显示 -->
<div class="gameListItemApp rowFlex columnCenter spaceBetween" v-if="false"> <div
class="gameListItemApp rowFlex columnCenter spaceBetween"
v-if="false"
>
<p class="rowFlex columnCenter"> <p class="rowFlex columnCenter">
<img src="@/assets/icon/svg/vipIcon.svg" alt="vipIcon" style="width: 16px;height: 16px;margin-right: 5px;"> <img
src="@/assets/icon/svg/vipIcon.svg"
alt="vipIcon"
style="width: 16px; height: 16px; margin-right: 5px"
/>
VIP自助工具 VIP自助工具
</p> </p>
<el-button size="mini" :disabled="accountSelect == ''" @click="sendVipGift">发送</el-button> <el-button
size="mini"
:disabled="accountSelect == ''"
@click="sendVipGift"
>发送</el-button
>
</div> </div>
<!-- 自助链接(举报、申诉、礼包申请) --> <!-- 自助链接(举报、申诉、礼包申请) -->
<div class="gameListItemApp rowFlex columnCenter spaceBetween"> <div class="gameListItemApp rowFlex columnCenter spaceBetween">
<p class="rowFlex columnCenter"> <p class="rowFlex columnCenter">
<i class="el-icon-s-operation" style="font-size:16px;margin-right:5px;"></i> <i
class="el-icon-s-operation"
style="font-size: 16px; margin-right: 5px"
></i>
自助链接(举报、申诉、礼包申请) 自助链接(举报、申诉、礼包申请)
</p> </p>
<el-button size="mini" :disabled="accountSelect == ''" @click="sendReportLink">发送</el-button> <el-button
size="mini"
:disabled="accountSelect == ''"
@click="sendReportLink"
>发送</el-button
>
</div> </div>
<div class="rowFlex columnCenter spaceBetween gameCodeTitle" @click="showGameCode = !showGameCode"> <!-- 专属种花链接 -->
<div class="gameListItemApp rowFlex columnCenter spaceBetween">
<p class="rowFlex columnCenter">
<i
class="el-icon-s-operation"
style="font-size: 16px; margin-right: 5px"
></i>
专属 H5 链接(种花)
</p>
<el-button
size="mini"
:disabled="accountSelect == ''"
@click="showFlowerLinkDialog"
>发送</el-button
>
</div>
<div
class="rowFlex columnCenter spaceBetween gameCodeTitle"
@click="showGameCode = !showGameCode"
>
<p class="rowFlex columnCenter spaceBetween"> <p class="rowFlex columnCenter spaceBetween">
<svg-icon icon-class="gift" style="font-size:20px;margin-right: 5px;margin-top: -2px;"></svg-icon> <svg-icon
icon-class="gift"
style="font-size: 20px; margin-right: 5px; margin-top: -2px"
></svg-icon>
<span class="giftCode">礼包码</span> <span class="giftCode">礼包码</span>
</p> </p>
<i :class="showGameCode ? 'el-icon-arrow-right' : 'el-icon-arrow-down'"></i> <i
:class="showGameCode ? 'el-icon-arrow-right' : 'el-icon-arrow-down'"
></i>
</div> </div>
<el-collapse-transition> <el-collapse-transition>
<el-collapse v-show="showGameCode" v-if="giftCodeGame.length > 0" :disabled="disabled" class="giftGameCollapse"> <el-collapse
<el-collapse-item v-for="(item, index) in giftCodeGame" :key="index" :title="item.label" v-show="showGameCode"
style="margin-bottom: 10px;"> v-if="giftCodeGame.length > 0"
:disabled="disabled"
class="giftGameCollapse"
>
<el-collapse-item
v-for="(item, index) in giftCodeGame"
:key="index"
:title="item.label"
style="margin-bottom: 10px"
>
<div v-if="giftCodeGame.length > 0"> <div v-if="giftCodeGame.length > 0">
<div v-for="(items, indexs) in item.children" :key="indexs" class="gameListItemChange"> <div
v-for="(items, indexs) in item.children"
:key="indexs"
class="gameListItemChange"
>
<div class="gameListItemApp gameListItemAppAC"> <div class="gameListItemApp gameListItemAppAC">
<p v-if="items.gift_package_group_name" class="gameName">{{ items.gift_package_group_name }}</p> <p v-if="items.gift_package_group_name" class="gameName">
<div class="rowFlex columnCenter spaceBetween" style="margin-left: 20px;"> {{ items.gift_package_group_name }}
</p>
<div
class="rowFlex columnCenter spaceBetween"
style="margin-left: 20px"
>
<p class="rowFlex columnCenter spaceBetween"> <p class="rowFlex columnCenter spaceBetween">
<el-popover placement="top" width="300" trigger="hover"> <el-popover placement="top" width="300" trigger="hover">
<div>{{ items.name }}</div> <div>{{ items.name }}</div>
<div slot="reference" class="gameName">{{ items.name }}</div> <div slot="reference" class="gameName">
{{ items.name }}
</div>
</el-popover> </el-popover>
<el-popover placement="top" trigger="hover"> <el-popover placement="top" trigger="hover">
<div class="contentPopover" v-html="items.content"> <div
</div> class="contentPopover"
<el-button slot="reference" type="text" size="medium" v-html="items.content"
style="margin-right: 10px;">礼包内容</el-button> ></div>
<el-button
slot="reference"
type="text"
size="medium"
style="margin-right: 10px"
>礼包内容</el-button
>
</el-popover> </el-popover>
</p> </p>
<el-button size="mini" type="primary" :loading="loading" <el-button
@click="sendGameCodeCopyDialog(items)">发送礼包码</el-button> size="mini"
</div> type="primary"
:loading="loading"
@click="sendGameCodeCopyDialog(items)"
>发送礼包码</el-button
>
</div> </div>
</div> </div>
</div> </div>
<div v-else class="rowFlex allCenter">
暂无游戏
</div> </div>
<div v-else class="rowFlex allCenter">暂无游戏</div>
</el-collapse-item> </el-collapse-item>
</el-collapse> </el-collapse>
</el-collapse-transition> </el-collapse-transition>
</div> </div>
<giftCodeDialog v-if="dialogVisible" :game-name="game_name" :dialogVisible.sync="dialogVisible" <giftCodeDialog
@result="getGiftCodeSubmit" /> v-if="dialogVisible"
:game-name="game_name"
:dialogVisible.sync="dialogVisible"
@result="getGiftCodeSubmit"
/>
<!-- 种花链接弹窗 -->
<flowerLinkDialog
v-if="flowerLinkDialogVisible"
:dialogVisible.sync="flowerLinkDialogVisible"
:member_id="accountSelect"
:bindGameUserList="bindGameUserList"
@success="handleFlowerLinkSuccess"
/>
</div> </div>
</template> </template>
<script> <script>
import { mapState, mapMutations } from 'vuex' import { mapState, mapMutations } from "vuex";
import { passwardEncryption, createVipUrl } from '@/api/game' import { passwardEncryption, createVipUrl } from "@/api/game";
import { giftCodeList, sendGiftCode, getZyouAuthLink } from '@/api/works' import { giftCodeList, sendGiftCode, getZyouAuthLink } from "@/api/works";
import giftCodeDialog from './giftCodeDialog.vue' import giftCodeDialog from "./giftCodeDialog.vue";
import flowerLinkDialog from "./flowerLinkDialog.vue";
export default { export default {
name: 'vipTools', name: "vipTools",
data() { data() {
return { return {
disabled: true, disabled: true,
showGameCode: false, showGameCode: false,
giftCodeGame: [], giftCodeGame: [],
dialogVisible: false, dialogVisible: false,
game_name: '', game_name: "",
flowerLinkDialogVisible: false,
giftCodeForm: { giftCodeForm: {
member_id: '', member_id: "",
username: '', username: "",
role_name: '', role_name: "",
role_id: '', role_id: "",
gift_package_id: '', gift_package_id: "",
recharge_total: undefined
}, },
loading: false loading: false,
} };
}, },
components: { components: {
giftCodeDialog giftCodeDialog,
flowerLinkDialog,
}, },
mounted() { mounted() {
this.requestGiftCode() this.requestGiftCode();
}, },
destroyed() { destroyed() {
this.giftCodeForm = { this.giftCodeForm = {
member_id: '', member_id: "",
username: '', username: "",
role_name: '', role_name: "",
role_id: '', role_id: "",
gift_package_id: '' gift_package_id: "",
} recharge_total: undefined
};
}, },
computed: { computed: {
...mapState('game', ['accountSelect', 'bindGameUserList', 'chatUserInfo']), ...mapState("game", ["accountSelect", "bindGameUserList", "chatUserInfo"]),
...mapState('user', ['userid']), ...mapState("user", ["userid"]),
},
props: {
}, },
props: {},
watch: { watch: {
accountSelect(newVal, oldVal) { accountSelect(newVal, oldVal) {
if (newVal && newVal !== '' && this.bindGameUserList.length > 0) { if (newVal && newVal !== "" && this.bindGameUserList.length > 0) {
this.disabled = false this.disabled = false;
} else { } else {
this.disabled = true this.disabled = true;
}
} }
}, },
},
methods: { methods: {
initGiftCodeForm() { initGiftCodeForm() {
const username = this.bindGameUserList.find(item => item.member_id === this.accountSelect).username const username = this.bindGameUserList.find(
(item) => item.member_id === this.accountSelect
).username;
this.giftCodeForm = { this.giftCodeForm = {
member_id: this.accountSelect, member_id: this.accountSelect,
username: username, username: username,
role_name: '', role_name: "",
role_id: '', role_id: "",
gift_package_id: '', gift_package_id: "",
} recharge_total: undefined
};
}, },
sendVipGift() { sendVipGift() {
if (this.bindGameUserList.length > 0) { if (this.bindGameUserList.length > 0) {
createVipUrl({ member_id: this.accountSelect }).then(res => { createVipUrl({ member_id: this.accountSelect }).then((res) => {
if (res.data.url && res.data.url != '') { if (res.data.url && res.data.url != "") {
this.sendChatMessage(res.data.url, 'text') this.sendChatMessage(res.data.url, "text");
} else { } else {
this.$message.warning('暂无vip链接') this.$message.warning("暂无vip链接");
} }
}) });
} else { } else {
this.$message.warning('请先关联游戏账号') this.$message.warning("请先关联游戏账号");
} }
}, },
sendChatMessage(content, type) { sendChatMessage(content, type) {
let message = {} let message = {};
if (type == 'text') { if (type == "text") {
message = { message = {
msgtype: 'text', msgtype: "text",
text: { text: {
content: content content: content,
}, },
success: (res) => { success: (res) => {
console.log(res, '发送文本成功') console.log(res, "发送文本成功");
}, },
fail: (err) => { fail: (err) => {
console.log(err, '发送文本失败') console.log(err, "发送文本失败");
} },
} };
} else if (type == 'link') { } else if (type == "link") {
message = { message = {
msgtype: 'news', msgtype: "news",
news: content, news: content,
success: (res) => { success: (res) => {
console.log(res, '发送 news 成功') console.log(res, "发送 news 成功");
}, },
fail: (err) => { fail: (err) => {
console.log(err, '发送 news 失败') console.log(err, "发送 news 失败");
} },
} };
} else if (type == 'image') { } else if (type == "image") {
message = { message = {
msgtype: 'image', msgtype: "image",
image: { image: {
mediaid: content mediaid: content,
}, },
success: (res) => { success: (res) => {
console.log(res, '发送 image 成功') console.log(res, "发送 image 成功");
}, },
fail: (err) => { fail: (err) => {
console.log(err, '发送 image 失败') console.log(err, "发送 image 失败");
},
};
} }
console.log(message, "1231");
this.$ww.sendChatMessage(message);
},
// 显示种花链接弹窗
showFlowerLinkDialog() {
if (this.accountSelect === "") {
this.$message.warning("请先关联游戏账号");
return;
} }
this.flowerLinkDialogVisible = true;
},
// 处理种花链接发送成功
handleFlowerLinkSuccess(url) {
if (url) {
this.sendChatMessage(url, "text");
this.$message.success('发送成功')
} }
console.log(message, '1231')
this.$ww.sendChatMessage(message)
}, },
// 发送举报申诉自助链接 // 发送举报申诉自助链接
async sendReportLink() { async sendReportLink() {
const res = await getZyouAuthLink() const res = await getZyouAuthLink();
if (res.status_code == 1) { if (res.status_code == 1) {
const link = { const link = {
title: '服务中心', title: "服务中心",
imgUrl: 'https://companywxcdn.zwnet.cn/company_wx/service/avatars/20250308/t3zztJ5FMMSnSXRtG3K8X5HaxsZMdk8W1741420608159.jpg', imgUrl:
desc: '点击此处提交申请', "https://companywxcdn.zwnet.cn/company_wx/service/avatars/20250308/t3zztJ5FMMSnSXRtG3K8X5HaxsZMdk8W1741420608159.jpg",
link: res.data.url desc: "点击此处提交申请",
} link: res.data.url,
this.sendChatMessage(link, 'link') };
this.sendChatMessage(link, "link");
} else { } else {
this.$message.warning('暂无申诉自助链接') this.$message.warning("暂无申诉自助链接");
} }
}, },
async requestGiftCode() { async requestGiftCode() {
this.giftCodeGame = [] this.giftCodeGame = [];
// 1 企微 2 微信 // 1 企微 2 微信
const data = { const data = {
userid: this.userid, userid: this.userid,
user_type: 1 user_type: 1,
} };
const res = await giftCodeList(data) const res = await giftCodeList(data);
if (res.status_code == 1 && res.data.length > 0) { if (res.status_code == 1 && res.data.length > 0) {
// this.giftCodeGame = res.data // this.giftCodeGame = res.data
this.handleChildren(res.data) this.handleChildren(res.data);
this.giftCodeGame = res.data this.giftCodeGame = res.data;
} else { } else {
this.giftCodeGame = { this.giftCodeGame = {
label: '礼包码', label: "礼包码",
children: [] children: [],
} };
} }
}, },
handleChildren(list) { handleChildren(list) {
list.map(item => { list.map((item) => {
item.main_game_id?item.label = item.main_game_name + '/' + item.main_game_id:item.label = item.main_game_name item.main_game_id
item.value = item.main_game_id ? (item.label = item.main_game_name + "/" + item.main_game_id)
item.children = item.gift_package_list : (item.label = item.main_game_name);
item.group_name = item.gift_package_group_name item.value = item.main_game_id;
}) item.children = item.gift_package_list;
item.group_name = item.gift_package_group_name;
});
}, },
// 确定提交 // 确定提交
getGiftCodeSubmit(form) { getGiftCodeSubmit(form) {
const { member_id, role_id, username, role_name } = form const { member_id, role_id, username, role_name ,recharge_total} = form;
this.giftCodeForm.username = username this.giftCodeForm.username = username;
this.giftCodeForm.role_name = role_name this.giftCodeForm.role_name = role_name;
this.giftCodeForm.member_id = member_id this.giftCodeForm.member_id = member_id;
this.giftCodeForm.role_id = role_id this.giftCodeForm.role_id = role_id;
this.sendGameCode() this.giftCodeForm.recharge_total = recharge_total
this.sendGameCode();
}, },
sendGameCodeCopyDialog(items) { sendGameCodeCopyDialog(items) {
if (items.package_type !== 1 && items.package_type!==4) { if (items.package_type !== 1 && items.package_type !== 4) {
if (this.accountSelect && this.bindGameUserList.length > 0) { if (this.accountSelect && this.bindGameUserList.length > 0) {
this.game_name = items.name this.game_name = items.name;
this.initGiftCodeForm() this.initGiftCodeForm();
this.giftCodeForm.gift_package_id = items.id this.giftCodeForm.gift_package_id = items.id;
if (items.package_type == 3) { if (items.package_type == 3) {
this.dialogVisible = true this.dialogVisible = true;
} else { } else {
this.sendGameCode() this.sendGameCode();
} }
} else { } else {
this.$message.warning('请先关联游戏账号') this.$message.warning("请先关联游戏账号");
} }
} else { } else {
this.giftCodeForm.gift_package_id = items.id this.giftCodeForm.gift_package_id = items.id;
this.sendGameCode() this.sendGameCode();
} }
}, },
// 发送礼包码 // 发送礼包码
async sendGameCode(items) { async sendGameCode(items) {
this.loading = true this.loading = true;
const data = { const data = {
userid: this.chatUserInfo.userid, userid: this.chatUserInfo.userid,
external_userid: this.chatUserInfo.external_userid, external_userid: this.chatUserInfo.external_userid,
...@@ -266,58 +377,69 @@ export default { ...@@ -266,58 +377,69 @@ export default {
role_name: this.giftCodeForm.role_name, role_name: this.giftCodeForm.role_name,
role_id: this.giftCodeForm.role_id, role_id: this.giftCodeForm.role_id,
gift_package_id: this.giftCodeForm.gift_package_id, gift_package_id: this.giftCodeForm.gift_package_id,
user_type: 3 user_type: 3,
};
// 如果存在 recharge_total 则添加到请求参数中 表示是 角色礼包
if (this.giftCodeForm.recharge_total !== undefined && this.giftCodeForm.recharge_total !== null) {
data.recharge_total = this.giftCodeForm.recharge_total
} }
const res = await sendGiftCode(data) const res = await sendGiftCode(data);
if (res.status_code === 1) { if (res.status_code === 1) {
this.$message.success('发送成功') this.$message.success("发送成功");
this.sendChatMessage(res.data, 'text') this.sendChatMessage(res.data, "text");
} else { } else {
this.$message.error(res.msg || '发送失败') this.$message.error(res.msg || "发送失败");
} }
this.loading = false this.giftCodeForm.recharge_total = undefined
this.loading = false;
}, },
handleAccount() { handleAccount() {
if (this.bindGameUserList.length > 0) { if (this.bindGameUserList.length > 0) {
const account = this.bindGameUserList.find(item => item.member_id == this.accountSelect) const account = this.bindGameUserList.find(
(item) => item.member_id == this.accountSelect
);
if (account) { if (account) {
return true return true;
} else { } else {
return false return false;
} }
} else { } else {
return false return false;
} }
}, },
sendMessage(item, type) { sendMessage(item, type) {
const result = this.handleAccount() const result = this.handleAccount();
if (!result) { if (!result) {
this.$message.warning('请稍后再试') this.$message.warning("请稍后再试");
return false return false;
} }
let str = '' let str = "";
if (type == 2) { if (type == 2) {
str = '网页游戏链接:' str = "网页游戏链接:";
} else if (type == 3) { } else if (type == 3) {
str = '安卓游戏链接:' str = "安卓游戏链接:";
} else if (type == 4) { } else if (type == 4) {
str = 'IOS游戏链接:' str = "IOS游戏链接:";
} else { } else {
} }
const username = this.bindGameUserList.find(item => item.member_id == this.accountSelect).username const username = this.bindGameUserList.find(
passwardEncryption({ member_id: this.accountSelect }).then(res => { (item) => item.member_id == this.accountSelect
this.sendChatMessage(`${str}${item.url} \n账号:${username} \n密码:${res.data.password}`, 'text') ).username;
}).catch(err => { passwardEncryption({ member_id: this.accountSelect })
this.sendChatMessage(`${str}${item.url} \n账号:${username}`, 'text') .then((res) => {
console.log(err) this.sendChatMessage(
`${str}${item.url} \n账号:${username} \n密码:${res.data.password}`,
"text"
);
}) })
.catch((err) => {
this.sendChatMessage(`${str}${item.url} \n账号:${username}`, "text");
console.log(err);
});
}, },
showPopover() { showPopover() {},
},
} };
}
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.vipToolsContent { .vipToolsContent {
...@@ -332,7 +454,7 @@ export default { ...@@ -332,7 +454,7 @@ export default {
} }
.sendLink:hover { .sendLink:hover {
color: #409EFF; color: #409eff;
} }
.giftGameCollapse { .giftGameCollapse {
...@@ -360,7 +482,7 @@ export default { ...@@ -360,7 +482,7 @@ export default {
} }
.btnActive { .btnActive {
background: #409EFF; background: #409eff;
color: #fff; color: #fff;
} }
} }
...@@ -388,8 +510,7 @@ export default { ...@@ -388,8 +510,7 @@ export default {
.gameListItemApp { .gameListItemApp {
width: 100%; width: 100%;
padding-left: 20px; margin-bottom: 10px;
.gameName { .gameName {
max-width: 120px; max-width: 120px;
overflow: hidden; overflow: hidden;
......
...@@ -163,7 +163,7 @@ ...@@ -163,7 +163,7 @@
<div v-if="items" class="trans-follow-1 card-style"> <div v-if="items" class="trans-follow-1 card-style">
<div class="follow-item"> <div class="follow-item">
<span class="follow-info-label label-font"> <span class="follow-info-label label-font">
{{ items.node_sort !== '0' ? '审批人:' : '登记人:' }} {{ items.node_sort !== "0" ? "审批人:" : "登记人:" }}
</span> </span>
<span class="info-value value-font"> <span class="info-value value-font">
{{ {{
...@@ -207,7 +207,7 @@ ...@@ -207,7 +207,7 @@
> >
{{ {{
items.current < indexs items.current < indexs
? '' ? ""
: items.approval_result_text : items.approval_result_text
}} }}
</span> </span>
...@@ -215,15 +215,15 @@ ...@@ -215,15 +215,15 @@
<div class="follow-item"> <div class="follow-item">
<span class="follow-info-label label-font"> <span class="follow-info-label label-font">
{{ {{
items.node_sort !== '0' || items.node_sort !== "0" ||
items.node_name === '系统' items.node_name === "系统"
? '审批时间:' ? "审批时间:"
: '登记时间:' : "登记时间:"
}} }}
</span> </span>
<span class="info-value value-font"> <span class="info-value value-font">
{{ {{
items.node_sort === '0' items.node_sort === "0"
? items.create_time ? items.create_time
: items.update_time : items.update_time
}} }}
...@@ -289,7 +289,7 @@ ...@@ -289,7 +289,7 @@
items.extra_attribution && items.extra_attribution &&
items.extra_attribution.remark items.extra_attribution.remark
? items.extra_attribution.remark ? items.extra_attribution.remark
: '' : '',
) )
" "
></div> ></div>
...@@ -338,27 +338,27 @@ import { ...@@ -338,27 +338,27 @@ import {
reportIndex, reportIndex,
reportCancel, reportCancel,
reportProcess, reportProcess,
} from '@/api/game'; } from "@/api/game";
import { mapState, mapMutations } from 'vuex'; import { mapState, mapMutations } from "vuex";
import { removeDp, formatNumber, debounce } from '@/utils/index'; import { removeDp, formatNumber, debounce } from "@/utils/index";
import resubmitReport from './layer/report.vue'; import resubmitReport from "./layer/report.vue";
import approvalTask from './layer/approvalTask.vue'; import approvalTask from "./layer/approvalTask.vue";
// 导入审批状态图标 // 导入审批状态图标
import shenpi1 from '@/assets/icon/svg/shenpi1.svg'; import shenpi1 from "@/assets/icon/svg/shenpi1.svg";
import shenpi2 from '@/assets/icon/svg/shenpi2.svg'; import shenpi2 from "@/assets/icon/svg/shenpi2.svg";
import shenpi3 from '@/assets/icon/svg/shenpi3.svg'; import shenpi3 from "@/assets/icon/svg/shenpi3.svg";
import shenpi4 from '@/assets/icon/svg/shenpi4.svg'; import shenpi4 from "@/assets/icon/svg/shenpi4.svg";
import shenpi5 from '@/assets/icon/svg/shenpi5.svg'; import shenpi5 from "@/assets/icon/svg/shenpi5.svg";
import noContent from '@/components/noContent.vue'; import noContent from "@/components/noContent.vue";
export default { export default {
name: 'report', name: "report",
computed: { computed: {
...mapState('game', ['accountSelect']), ...mapState("game", ["accountSelect"]),
...mapState('user', ['cser_id', 'cser_name']), ...mapState("user", ["cser_id", "cser_name"]),
}, },
watch: { watch: {
accountSelect(newVal, oldVal) { accountSelect(newVal, oldVal) {
if (newVal && newVal !== '' && newVal !== oldVal) { if (newVal && newVal !== "" && newVal !== oldVal) {
this.filterChange(); this.filterChange();
} }
}, },
...@@ -377,18 +377,18 @@ export default { ...@@ -377,18 +377,18 @@ export default {
shenpi4, shenpi4,
shenpi5, shenpi5,
reportForm: { reportForm: {
customer_id: '', customer_id: "",
member_id: '', member_id: "",
role_id: '', role_id: "",
username: '', username: "",
role_name: '', role_name: "",
register_type: 1, register_type: 1,
approval_status: '', approval_status: "",
}, },
isApproval: false, isApproval: false,
register_type_list: [ register_type_list: [
{ value: 2, label: '玩家登记' }, { value: 2, label: "玩家登记" },
{ value: 1, label: '客服登记' }, { value: 1, label: "客服登记" },
], ],
reportInfo: {}, reportInfo: {},
pageInfo: { pageInfo: {
...@@ -400,7 +400,7 @@ export default { ...@@ -400,7 +400,7 @@ export default {
isMoreRecord: false, isMoreRecord: false,
approvalList: [], approvalList: [],
dialogRemarkVisible: false, dialogRemarkVisible: false,
dialogRemake: '', dialogRemake: "",
formatNumber: formatNumber, formatNumber: formatNumber,
taskTypeList: [], taskTypeList: [],
}; };
...@@ -428,9 +428,9 @@ export default { ...@@ -428,9 +428,9 @@ export default {
}, },
async requstApprovalList() { async requstApprovalList() {
const data = { const data = {
type: 'dictionaries', type: "dictionaries",
table_name: 'zs_refund_request', table_name: "zs_refund_request",
field_name: 'approval_status', field_name: "approval_status",
}; };
const res = await searchcondition(data); const res = await searchcondition(data);
if (res.status_code === 1) { if (res.status_code === 1) {
...@@ -439,9 +439,9 @@ export default { ...@@ -439,9 +439,9 @@ export default {
}, },
async request_register_type() { async request_register_type() {
const data = { const data = {
type: 'dictionaries', type: "dictionaries",
table_name: 'zs_report_request', table_name: "zs_report_request",
field_name: 'register_type', field_name: "register_type",
}; };
const res = await searchcondition(data); const res = await searchcondition(data);
if (res.status_code === 1) { if (res.status_code === 1) {
...@@ -453,13 +453,13 @@ export default { ...@@ -453,13 +453,13 @@ export default {
this.dialogRemarkVisible = true; this.dialogRemarkVisible = true;
}, },
async reportProcess(item, index) { async reportProcess(item, index) {
console.log(item.current, 'item'); console.log(item.current, "item");
item.showStep = !item.showStep; item.showStep = !item.showStep;
if (item.reportProcessList.length === 0) { if (item.reportProcessList.length === 0) {
const res = await reportProcess({ id: item.id }); const res = await reportProcess({ id: item.id });
item.reportProcessList = res.data.data; item.reportProcessList = res.data.data;
res.data.data.map((items) => { res.data.data.map((items) => {
if (items.approval_result !== '0' && items.approval_result !== '2') { if (items.approval_result !== "0" && items.approval_result !== "2") {
item.current += 1; item.current += 1;
} }
}); });
...@@ -469,9 +469,9 @@ export default { ...@@ -469,9 +469,9 @@ export default {
this.$forceUpdate(); this.$forceUpdate();
}, },
paperScroll() { paperScroll() {
console.log('开始滚动了'); console.log("开始滚动了");
if (!this.isMoreRecord) { if (!this.isMoreRecord) {
console.log('没有更多数据了'); console.log("没有更多数据了");
return false; return false;
} }
this.requestNextPage(); this.requestNextPage();
...@@ -485,12 +485,12 @@ export default { ...@@ -485,12 +485,12 @@ export default {
}, },
switchStateTag(status) { switchStateTag(status) {
switch (status) { switch (status) {
case '0': case "0":
return 'unhandle'; return "unhandle";
case '1': case "1":
return 'handled'; return "handled";
case '2': case "2":
return 'sendFail'; return "sendFail";
} }
}, },
formatImg(html) { formatImg(html) {
...@@ -501,19 +501,19 @@ export default { ...@@ -501,19 +501,19 @@ export default {
}, },
switchStateText(status) { switchStateText(status) {
switch (status) { switch (status) {
case '0': case "0":
return '待审批'; return "待审批";
case '1': case "1":
return '通过'; return "通过";
case '2': case "2":
return '驳回'; return "驳回";
} }
}, },
handleReport(item) { handleReport(item) {
this.$confirm('确定要撤销该申请么?', '确认提示', { this.$confirm("确定要撤销该申请么?", "确认提示", {
confirmButtonText: '确定', confirmButtonText: "确定",
cancelButtonText: '取消', cancelButtonText: "取消",
type: 'warning', type: "warning",
}) })
.then(() => { .then(() => {
console.log(1231); console.log(1231);
...@@ -525,8 +525,8 @@ export default { ...@@ -525,8 +525,8 @@ export default {
reportCancel(data).then((res) => { reportCancel(data).then((res) => {
if (res.status_code === 1) { if (res.status_code === 1) {
this.$message({ this.$message({
type: 'success', type: "success",
message: '撤销成功!', message: "撤销成功!",
}); });
this.filterChange(); this.filterChange();
} }
...@@ -534,15 +534,15 @@ export default { ...@@ -534,15 +534,15 @@ export default {
}) })
.catch(() => { .catch(() => {
this.$message({ this.$message({
type: 'info', type: "info",
message: '已取消', message: "已取消",
}); });
}); });
}, },
// 举报列表 // 举报列表
async reportIndex() { async reportIndex() {
if (this.accountSelect === '') { if (this.accountSelect === "") {
this.$message.warning('暂无关联的账号,请先去关联账号!'); this.$message.warning("暂无关联的账号,请先去关联账号!");
return false; return false;
} }
if (this.pageInfo.page == 1) { if (this.pageInfo.page == 1) {
...@@ -551,7 +551,22 @@ export default { ...@@ -551,7 +551,22 @@ export default {
const { username, role_name, approval_status, register_type } = const { username, role_name, approval_status, register_type } =
this.reportForm; this.reportForm;
// const { id } = this.userInfo // const { id } = this.userInfo
const data = { const related_task_info = JSON.parse(
sessionStorage.getItem("related_task_info"),
);
let data;
if (related_task_info && related_task_info.related_task_type === 6) {
data = { ...this.pageInfo, id: related_task_info.related_task_id };
this.reportForm.register_type = "";
//展示一次后清除携带过来的id
this.$nextTick(() => {
setTimeout(() => {
sessionStorage.removeItem("related_task_info");
}, 200);
});
} else {
data = {
username, username,
role_name, role_name,
approval_status, approval_status,
...@@ -560,11 +575,12 @@ export default { ...@@ -560,11 +575,12 @@ export default {
register_type, register_type,
...this.pageInfo, ...this.pageInfo,
}; };
}
const res = await reportIndex(data); const res = await reportIndex(data);
if (this.pageInfo.page == 1) { if (this.pageInfo.page == 1) {
this.reportList = res.data.data; this.reportList = res.data.data;
} else { } else {
this.reportList = removeDp(this.reportList, res.data.data, 'id'); this.reportList = removeDp(this.reportList, res.data.data, "id");
} }
if (this.reportList.length > 0) { if (this.reportList.length > 0) {
this.reportList.map((item) => { this.reportList.map((item) => {
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
<el-collapse v-model="collapseActive"> <el-collapse v-model="collapseActive">
<div <div
v-for="(items, indexs) in roleList" v-for="(items, indexs) in roleList"
:key="indexs" :key="items.role_id"
class="contentItem" class="contentItem"
> >
<div class="title"></div> <div class="title"></div>
...@@ -170,12 +170,31 @@ ...@@ -170,12 +170,31 @@
</div> </div>
<div class="item rowFlex columnCenter spaceBetween"> <div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter"> <div class="rowFlex columnCenter">
<span class="label">主服开服天数:</span>
<p class="text" v-if="items.main_server_open_day">
{{ items?.main_server_open_day }}天
</p>
</div>
</div>
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">开/合服天数:</span> <span class="label">开/合服天数:</span>
<p class="text" v-if="items.server_day"> <p class="text" v-if="items.server_day">
{{ items?.server_day }}天 {{ items?.server_day }}天
</p> </p>
</div> </div>
</div> </div>
<!-- 带教记录 -->
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">带教次数:</span>
<el-button
type="text"
style="cursor: pointer;z-index:10;"
@click.stop="openMentorRecordDrawer(items)"
>{{ items.teach_num || 0 }}次</el-button>
</div>
</div>
</div> </div>
</el-collapse-item> </el-collapse-item>
</div> </div>
...@@ -196,24 +215,39 @@ ...@@ -196,24 +215,39 @@
:show.sync="showAppeal" :show.sync="showAppeal"
:appeal-info="appealInfo" :appeal-info="appealInfo"
/> />
<!-- 带教记录弹窗 -->
<el-drawer
:visible.sync="showMentorRecord"
v-if="showMentorRecord"
:title="`${currentRoleName}带教记录`"
size="300px"
:append-to-body="true"
>
<mentorRecord
:role-id="currentRoleId"
@refresh="handleMentorRecordRefresh"
/>
</el-drawer>
</div> </div>
</template> </template>
<script> <script>
import { mapState, mapMutations, mapActions } from "vuex"; import { mapState, mapMutations, mapActions } from "vuex";
import { getRoleHoLo, marketingRoleGrade, getServerDayApi } from "@/api/game"; import { getRoleHoLo, marketingRoleGrade, getServerDayApi,roleTeachingNum } from "@/api/game";
import noContent from "@/components/noContent.vue"; import noContent from "@/components/noContent.vue";
import appeal from "./layer/appeal.vue"; import appeal from "./layer/appeal.vue";
import watchMember from "@/mixins/watchMember"; import watchMember from "@/mixins/watchMember";
import { createDetails } from "@/views/popup/RecentActivitiesPopup/index.js"; import { createDetails } from "@/views/popup/RecentActivitiesPopup/index.js";
import { createRoleRecentActivityNotPushNum } from "@/views/hooks/useGetCount.js"; import { createRoleRecentActivityNotPushNum } from "@/views/hooks/useGetCount.js";
import vipLevel from "@/views/userInfo/components/gameInfo/vipLevel.vue"; import vipLevel from "@/views/userInfo/components/gameInfo/vipLevel.vue";
import mentorRecord from "@/views/userInfo/components/gameInfo/mentorRecord.vue";
export default { export default {
name: "roleInfo", name: "roleInfo",
components: { components: {
noContent, noContent,
appeal, appeal,
vipLevel, vipLevel,
mentorRecord,
}, },
data() { data() {
return { return {
...@@ -232,6 +266,9 @@ export default { ...@@ -232,6 +266,9 @@ export default {
recentActivitiesPopupInstance: null, //近期要开模块弹框 recentActivitiesPopupInstance: null, //近期要开模块弹框
roleRecentActivityNotPushNumInstance: null, //侧边栏计数弹框 roleRecentActivityNotPushNumInstance: null, //侧边栏计数弹框
numRoleIdList: [], numRoleIdList: [],
showMentorRecord: false, // 带教记录弹窗显示状态
currentRoleId: null, // 当前查看带教记录的角色ID
currentRoleName: '' // 当前查看带教记录的角色名称
}; };
}, },
computed: { computed: {
...@@ -240,7 +277,11 @@ export default { ...@@ -240,7 +277,11 @@ export default {
watch: { watch: {
collapseActive(newVal, oldVal) { collapseActive(newVal, oldVal) {
if (newVal.length > 0) { if (newVal.length > 0) {
this.handleChange(newVal.filter((item) => !oldVal.includes(item))); const newOpenedItems = newVal.filter(item => !oldVal.includes(item))
this.handleChange(newOpenedItems)
// 处理带教次数获取
this.handleChangeRoleTeachingNum(newOpenedItems)
} }
}, },
}, },
...@@ -295,7 +336,6 @@ export default { ...@@ -295,7 +336,6 @@ export default {
}); });
} }
}, },
async handleChange(v) { async handleChange(v) {
const index = this.roleList.findIndex( const index = this.roleList.findIndex(
(item) => v.includes(item.role_id) && !item.server_day (item) => v.includes(item.role_id) && !item.server_day
...@@ -305,6 +345,8 @@ export default { ...@@ -305,6 +345,8 @@ export default {
role_id: this.roleList[index].role_id, role_id: this.roleList[index].role_id,
}); });
this.roleList[index].server_day = res.data.data?.server_day; this.roleList[index].server_day = res.data.data?.server_day;
this.roleList[index].main_server_open_day =
res.data.data?.main_server_open_day;
this.roleList = [...this.roleList]; this.roleList = [...this.roleList];
} }
}, },
...@@ -344,6 +386,67 @@ export default { ...@@ -344,6 +386,67 @@ export default {
} }
); );
}, },
/**
* 打开带教记录弹窗
*/
openMentorRecordDrawer(roleItem) {
console.log(roleItem, 'roleItem')
this.currentRoleId = roleItem.role_id
this.currentRoleName = `${roleItem.role_name}-${roleItem.server_name}`
this.showMentorRecord = true
},
/**
* 带教记录刷新后,更新角色列表中的带教次数
*/
async handleMentorRecordRefresh(roleId,teachingListLength) {
// 重新获取角色列表,更新带教次数
const index = this.roleList.findIndex(item => item.role_id === roleId)
if (index !== -1) {
this.$set(this.roleList[index], 'teach_num', teachingListLength)
}
this.roleList = this.roleList.concat([])
},
/**
* 处理角色展开时获取带教次数
* @param {Array} openedRoleIds - 新展开的角色ID数组
*/
handleChangeRoleTeachingNum(openedRoleIds) {
if (!openedRoleIds || openedRoleIds.length === 0) {
return
}
// 遍历新展开的角色,获取带教次数
openedRoleIds.forEach(roleId => {
const roleItem = this.roleList.find(item => item.role_id === roleId)
if (roleItem) {
// 如果已经存在 teach_num 字段,则不请求接口
if (roleItem.teach_num === undefined || roleItem.teach_num === null) {
this.getRoleTeachingNum(roleId)
}
}
})
},
/**
* 获取角色带教次数
* @param {String|Number} roleId - 角色ID
*/
async getRoleTeachingNum(roleId) {
try {
const res = await roleTeachingNum({
role_id: roleId
})
console.log(res,'res')
if (res.status_code === 1) {
// 更新对应角色的 teach_num 字段
const index = this.roleList.findIndex(item => item.role_id === roleId)
if (index !== -1) {
this.$set(this.roleList[index], 'teach_num', res.data.data?.role_teaching_num || 0)
this.roleList = [...this.roleList]
}
}
} catch (error) {
console.error('获取带教次数失败:', error)
}
}
}, },
beforeDestroy() { beforeDestroy() {
this.recentActivitiesPopupInstance.destroy(); this.recentActivitiesPopupInstance.destroy();
......
...@@ -201,7 +201,6 @@ export default { ...@@ -201,7 +201,6 @@ export default {
this.requestGroup(); this.requestGroup();
}, },
methods: { methods: {
// ...mapMutations('common', ['set_sendSkillMessage', 'set_isEditSkill']),
sendMessage: debounce(function (item, id) { sendMessage: debounce(function (item, id) {
console.log(item, id, "sendMessage"); console.log(item, id, "sendMessage");
}, 500), }, 500),
...@@ -211,11 +210,6 @@ export default { ...@@ -211,11 +210,6 @@ export default {
// 复制内容到粘贴板 // 复制内容到粘贴板
if (item.msgtype == "text") { if (item.msgtype == "text") {
if (item && item.text && item.text.content) { if (item && item.text && item.text.content) {
// copyToClipboard(
// item.text.content,
// (message) => this.$message.success(message),
// (message) => this.$message.error(message)
// )
this.sendChatMessage(item.text.content); this.sendChatMessage(item.text.content);
} }
} else if (item.msgtype == "image" && item.image.picurl) { } else if (item.msgtype == "image" && item.image.picurl) {
...@@ -248,7 +242,7 @@ export default { ...@@ -248,7 +242,7 @@ export default {
fail: (err) => { fail: (err) => {
console.log(err, "发送图片链接失败"); console.log(err, "发送图片链接失败");
this.$message.error( this.$message.error(
"图片发送失败:" + (err.errMsg || err.message || "未知错误") "图片发送失败:" + (err.errMsg || err.message || "未知错误"),
); );
}, },
}); });
...@@ -408,7 +402,7 @@ export default { ...@@ -408,7 +402,7 @@ export default {
this.groupDataList = res.data.data; this.groupDataList = res.data.data;
this.groupDataList.map((item, index) => { this.groupDataList.map((item, index) => {
const text = item.message.attachments.find( const text = item.message.attachments.find(
(item) => item.msgtype === "text" (item) => item.msgtype === "text",
); );
if (text) { if (text) {
item.title = text.text.content; item.title = text.text.content;
......
<!--
* @Author: 金多虾 937667504@qq.com
* @Date: 2025-09-08 10:15:29
* @LastEditors: 金多虾 937667504@qq.com
* @LastEditTime: 2025-12-10 14:52:24
* @FilePath: /company_app/src/views/giftRecord.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template> <template>
<div class="gift-tab-container-apply-gift"> <div class="gift-tab-container-apply-gift">
<el-tabs v-model="activeTab"> <el-tabs v-model="activeTab">
...@@ -7,18 +15,23 @@ ...@@ -7,18 +15,23 @@
<el-tab-pane label="企微礼包" name="wx"> <el-tab-pane label="企微礼包" name="wx">
<wx-gift v-if="activeTab == 'wx'"></wx-gift> <wx-gift v-if="activeTab == 'wx'"></wx-gift>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="角色礼包" name="role">
<role-gift v-if="activeTab === 'role'"></role-gift>
</el-tab-pane>
</el-tabs> </el-tabs>
</div> </div>
</template> </template>
<script> <script>
import EmailGift from './components/giftRecord/emailGift.vue' import EmailGift from './components/giftRecord/emailGift.vue'
import WxGift from './components/giftRecord/wxGift.vue' import WxGift from './components/giftRecord/wxGift.vue'
import RoleGift from './components/giftRecord/roleGift.vue'
import { mapActions } from 'vuex' import { mapActions } from 'vuex'
export default { export default {
name: 'giftRecord', name: 'giftRecord',
components: { components: {
EmailGift, EmailGift,
WxGift WxGift,
RoleGift
}, },
created() { created() {
this.initializeWecom() this.initializeWecom()
......
<template>
<div class="flex flex-col h-full">
<div
class="py-[19px] px-[16px] text-[14px] text-[#86909C] space-x-[24px] border-b-[1px] border-solid border-[#F2F3F5]"
>
<span
v-for="value in tabList"
:key="value.value"
@click="handleTabClick(value.value)"
class="cursor-pointer"
:class="{ '!text-[#323335] font-medium': activeTab === value.value }"
>{{ value.name }}</span
>
</div>
<div class="flex-1 w-full overflow-y-auto" @scroll="handleScroll">
<div
class="p-[16px] space-y-[6px] border-b-[1px] border-solid border-[#F2F3F5]"
v-for="(value, index) in list"
:key="value.id || index"
>
<div class="flex space-x-[16px] text-[#323335] relative">
<div
class="w-[56px] text-[#86909C]"
:class="{ 'user-agency': value.status === 0 }"
>
<el-tag :type="['success', 'success', 'info'][value.status]">
{{ value.status_text }}
</el-tag>
</div>
<div
class="flex-1 w-full break-words text-wrap flex items-center text-[16px] font-medium"
:class="{ truncate: !value.showMore }"
style="display: -webkit-box"
>
{{ value.name }}
</div>
<div
class="bg-white h-[24px] text-[#86909C] cursor-pointer flex items-center text-[12px]"
@click="toggleShowMore(index)"
>
{{ value.showMore ? "折叠" : "展开" }}
<svg-icon
svgName="icon-zhankai"
class="w-[12px] h-[12px]"
:class="{ 'rotate-180': value.showMore }"
></svg-icon>
</div>
</div>
<div class="flex space-x-[16px] text-[#323335]">
<div class="w-[56px] text-[#86909C]">待办详情</div>
<div class="flex-1 relative" :ref="(el) => (detailRefs[index] = el)">
<div
class="text-[14px] break-words transition-all duration-300"
:class="{ 'max-h-[22px] overflow-hidden': !value.showMore }"
v-show="!value.showMore"
>
{{ value.detail }}
</div>
<div class="text-[14px] break-words" v-show="value.showMore">
{{ value.detail }}
</div>
</div>
</div>
<div class="flex space-x-[16px] text-[#323335]">
<div class="w-[56px] text-[#86909C]">创建时间</div>
<div class="flex-1 flex items-center text-[14px] break-words">
{{ value.created_at }}
</div>
</div>
<div class="flex space-x-[16px] text-[#323335]" v-if="value.showMore">
<div class="w-[56px] text-[#86909C]">归属客服</div>
<div class="flex-1 flex items-center text-[14px] break-words">
{{ value.cser_name }}
</div>
</div>
<div
class="flex space-x-[16px] text-[#323335]"
v-if="value.source_session.allot_time && value.showMore"
>
<div class="w-[56px] text-[#86909C]">来源会话</div>
<div class="flex-1 flex items-center text-[14px] break-words">
{{ value.source_session.allot_time }}{{
value.source_session.close_time
}}
</div>
</div>
<div class="flex space-x-[16px] text-[#323335]" v-if="value.showMore">
<div class="w-[56px] text-[#86909C]">关联工单</div>
<div class="flex-1 flex items-center text-[14px] break-words">
{{ related_task_type_text[value.related_task_type] }}
<el-button
v-if="value.related_task_id"
type="text"
class="!py-0 pl-[12px]"
@click="handleClick(value)"
>工单详情</el-button
>
</div>
</div>
<div
class="flex space-x-[16px] text-[#323335]"
v-if="value.category_name"
>
<div class="w-[56px] text-[#86909C]">待办类型</div>
<div
class="flex-1 flex items-center text-[14px] break-words flex-wrap gap-[6px]"
>
<div class="px-[6px] bg-[#F2F3F5] rounded-[4px] shrink-0">
{{ value.category_name }}
</div>
</div>
</div>
<div
class="flex space-x-[16px] text-[#323335]"
v-if="value.status !== 0 && value.showMore"
>
<div class="w-[56px] text-[#86909C]">完成会话</div>
<div
class="flex-1 flex items-center text-[14px] break-words flex-wrap gap-[6px]"
v-if="value.complete_session.allot_time"
>
{{ value.complete_session.allot_time }}{{
value.complete_session.close_time
}}
</div>
</div>
</div>
<div v-if="loading" class="relative flex justify-center py-[20px]">
<loading />
</div>
</div>
</div>
</template>
<script>
import { mapMutations, mapState } from "vuex";
import {
corpIntelligentTaskExternalList,
corpIntelligentTaskMineList,
} from "@/api/works";
import loading from "@/components/loading";
export default {
name: "UserAgency",
components: {
loading,
},
data() {
return {
activeTab: 0,
related_task_type_text: {
6: "举报申请",
12: "玩家误操作",
14: "转区申请",
13: "玩家转端",
},
tabList: [
{
name: "未完成",
value: 0,
},
{
name: "已完成",
value: 1,
},
{
name: "我的待办",
value: 2,
},
],
detailRefs: [],
show: false,
page_info: {
page: 1,
page_size: 10,
total: 0,
},
list: [],
loading: false,
};
},
computed: {
...mapState("game", ["chatUserInfo"]),
},
methods: {
handleClick(v) {
sessionStorage.setItem(
"related_task_info",
JSON.stringify({
related_task_id: v.related_task_id,
related_task_type: v.related_task_type,
}),
);
// 跳转到申请记录
this.$router.push({
path: "/applyRecord",
});
},
handleTabClick(value) {
if (this.activeTab === value) return;
this.activeTab = value;
this.page_info.page = 1;
this.list = [];
this.getList(value);
},
handleScroll(e) {
const { scrollTop, scrollHeight, clientHeight } = e.target;
// 当滚动到底部100px以内时加载更多
if (scrollHeight - scrollTop - clientHeight < 100 && !this.loading) {
// 检查是否还有更多数据可以加载
if (this.list.length < this.page_info.total) {
this.loadMore();
}
}
},
loadMore() {
this.page_info.page++;
this.getList(this.activeTab);
},
toggleShowMore(index) {
this.$set(this.list[index], "showMore", !this.list[index].showMore);
},
checkTextOverflow() {
this.$nextTick(() => {
this.detailRefs.forEach((ref, index) => {
if (ref) {
// 创建一个临时元素来测量文本高度
const tempEl = document.createElement("div");
tempEl.className = "text-[14px] break-words";
tempEl.style.position = "absolute";
tempEl.style.visibility = "hidden";
tempEl.style.width = "100%";
tempEl.style.whiteSpace = "normal";
tempEl.innerHTML = this.list[index].detail;
ref.appendChild(tempEl);
// 计算一行文字的高度(假设行高为1.5倍字体大小)
const lineHeight = parseInt(
window.getComputedStyle(tempEl).lineHeight,
);
const fontHeight = parseInt(
window.getComputedStyle(tempEl).fontSize,
);
const expectedLineHeight = lineHeight || fontHeight * 1.5;
// 测量文本总高度
const totalHeight = tempEl.offsetHeight;
// 如果内容高度大于一行高度,则显示展开收起按钮
const shouldShowMore = totalHeight > expectedLineHeight;
this.$set(this.list[index], "shouldShowMore", shouldShowMore);
// 移除临时元素
ref.removeChild(tempEl);
}
});
});
},
async getList(value = 0) {
// 如果正在加载或者已经是最后一页,则不发起请求
if (
this.loading ||
(this.list.length >= this.page_info.total && this.page_info.total > 0)
) {
return;
}
this.loading = true;
const params = {
status: value,
page: this.page_info.page,
page_size: this.page_info.page_size,
external_userid: this.chatUserInfo.external_userid,
};
let api;
try {
if (value !== 2) {
api = corpIntelligentTaskExternalList;
} else {
delete params.external_userid;
delete params.status;
api = corpIntelligentTaskMineList;
}
const res = await api(params);
const newList = res.data.data.map((item) => ({
...item,
showMore: false,
shouldShowMore: false,
}));
// 如果是第一页则替换列表,否则合并列表
if (this.page_info.page === 1) {
this.list = newList;
} else {
this.list = [...this.list, ...newList];
}
this.page_info.total = res.data.page_info.total;
// 检查文字是否溢出
this.checkTextOverflow();
} catch (error) {
console.error("获取数据失败:", error);
this.$message({
message: "获取数据失败",
type: "error",
});
} finally {
this.loading = false;
}
},
},
mounted() {
this.getList();
},
};
</script>
<style scoped lang="scss">
.user-agency {
.el-tag.el-tag--success {
color: #3491fa;
background-color: #e8f7ff;
border-color: #c3e7fe;
}
}
</style>
...@@ -381,7 +381,7 @@ export default { ...@@ -381,7 +381,7 @@ export default {
} }
this.$store.commit( this.$store.commit(
"user/set_client_online_status", "user/set_client_online_status",
statusRes.data.client_online_status statusRes.data.client_online_status,
); );
} }
...@@ -486,7 +486,7 @@ export default { ...@@ -486,7 +486,7 @@ export default {
if (res.status_code == 1) { if (res.status_code == 1) {
this.$message.success(res.msg); this.$message.success(res.msg);
const index = this.bindGameUserList.findIndex( const index = this.bindGameUserList.findIndex(
(item) => item.member_id == this.accountSelect (item) => item.member_id == this.accountSelect,
); );
this.bindGameUserList.splice(index, 1); this.bindGameUserList.splice(index, 1);
this.set_accountSelect(this.bindGameUserList[0].member_id); this.set_accountSelect(this.bindGameUserList[0].member_id);
...@@ -502,7 +502,7 @@ export default { ...@@ -502,7 +502,7 @@ export default {
confirmButtonText: "确定", confirmButtonText: "确定",
cancelButtonText: "取消", cancelButtonText: "取消",
type: "warning", type: "warning",
} },
) )
.then((res) => { .then((res) => {
const data = { const data = {
...@@ -529,7 +529,7 @@ export default { ...@@ -529,7 +529,7 @@ export default {
// 关联客服 // 关联客服
relationKfh() { relationKfh() {
const username = this.bindGameUserList.find( const username = this.bindGameUserList.find(
(item) => item.value == this.accountSelect (item) => item.value == this.accountSelect,
); );
const params = { const params = {
member_id: this.accountSelect, member_id: this.accountSelect,
......
...@@ -334,7 +334,14 @@ export default { ...@@ -334,7 +334,14 @@ export default {
}; };
}, },
computed: { computed: {
...mapState("game", ["accountSelect"]), ...mapState("game", ["accountSelect", "bindGameUserList"]),
bindGameUserInfo: {
get() {
return this.bindGameUserList.find(
(item) => item.member_id == this.accountSelect,
);
},
},
}, },
watch: { watch: {
accountSelect: { accountSelect: {
...@@ -362,16 +369,16 @@ export default { ...@@ -362,16 +369,16 @@ export default {
getMemberLabel(data).then((res) => { getMemberLabel(data).then((res) => {
if (res?.data?.data?.length > 0) { if (res?.data?.data?.length > 0) {
const change_user = res.data.data.find( const change_user = res.data.data.find(
(item) => item.label_type == 2 (item) => item.label_type == 2,
); );
const change_name = res.data.data.find( const change_name = res.data.data.find(
(item) => item.label_type == 3 (item) => item.label_type == 3,
); );
const change_risk = res.data.data.find( const change_risk = res.data.data.find(
(item) => item.label_type == 4 (item) => item.label_type == 4,
); // 风险用户 ); // 风险用户
const change_appraisal = res.data.data.find( const change_appraisal = res.data.data.find(
(item) => item.label_type == 6 (item) => item.label_type == 6,
); // 石锤用户 ); // 石锤用户
this.change_user = change_user.label_value; this.change_user = change_user.label_value;
this.change_name = change_name.label_value; this.change_name = change_name.label_value;
...@@ -387,6 +394,13 @@ export default { ...@@ -387,6 +394,13 @@ export default {
} }
}); });
}, },
show_game_name() {
if (process.env.NODE_ENV == "production") {
return this.bindGameUserInfo.main_game_id == 187;
} else {
return this.bindGameUserInfo.main_game_id == 174;
}
},
// 白名单 // 白名单
changeNameFn() { changeNameFn() {
const data = { const data = {
...@@ -456,7 +470,7 @@ export default { ...@@ -456,7 +470,7 @@ export default {
changeUserMobile() { changeUserMobile() {
if ( if (
!/^1((3[0-9])|(4[1579])|(5[0-9])|(6[6])|(7[0-9])|(8[0-9])|(9[0-9]))\d{8}$/.test( !/^1((3[0-9])|(4[1579])|(5[0-9])|(6[6])|(7[0-9])|(8[0-9])|(9[0-9]))\d{8}$/.test(
this.newMobileValue this.newMobileValue,
) )
) { ) {
this.$message.warning("请填写正确的手机号"); this.$message.warning("请填写正确的手机号");
...@@ -495,7 +509,7 @@ export default { ...@@ -495,7 +509,7 @@ export default {
this.$set( this.$set(
this.chatUserDetails, this.chatUserDetails,
"intelligence_tag_group", "intelligence_tag_group",
res.data.intel_tag res.data.intel_tag,
); );
} else { } else {
this.$message.warning("每个用户半个小时仅能更新一次"); this.$message.warning("每个用户半个小时仅能更新一次");
......
<!--
* @Author: 金多虾 937667504@qq.com
* @Date: 2025-12-11 11:01:15
* @LastEditors: 金多虾 937667504@qq.com
* @LastEditTime: 2025-12-20 11:25:56
* @FilePath: /company_wx_frontend/src/views/works/component/gameInfo/roleInfo/mentorRecord.vue
* @Description: 带教记录组件
-->
<template>
<div class="mentor-record-page">
<!-- 提示信息和添加按钮区域 -->
<div class="mentor-record-page__toolbar">
<el-button
v-if="teachingList.length < 5"
type="primary"
size="small"
@click="showAddForm = !showAddForm"
>添加记录</el-button>
</div>
<!-- 新增记录表单 -->
<div v-if="showAddForm && teachingList.length < 5" class="mentor-record-page__add-form">
<el-input
v-model="formData.content"
type="textarea"
:rows="3"
placeholder="请输入"
maxlength="500"
show-word-limit
class="mentor-record-page__add-form-input"
/>
<div class="mentor-record-page__add-form-buttons">
<el-button size="mini" @click="handleCancelAdd">取消</el-button>
<el-button type="primary" size="mini" :loading="submitLoading" @click="handleSubmitAdd">保存</el-button>
</div>
</div>
<!-- 带教记录列表 -->
<div class="mentor-record-page__list">
<div
v-for="(item, index) in teachingList"
:key="item.id || index"
class="mentor-record-page__list-item"
>
<p class="mentor-record-page__list-item-title">{{ item.teaching_num }}次带教</p>
<p class="mentor-record-page__list-item-content">{{ item.teaching_text }}</p>
<div class="mentor-record-page__list-item-footer">
<span class="mentor-record-page__list-item-creator">新增人:{{ item.update_user || '-' }}</span>
<span class="mentor-record-page__list-item-divider">|</span>
<span class="mentor-record-page__list-item-time">{{item.update_time }}</span>
</div>
</div>
<div v-if="teachingList.length === 0 && !loading" class="mentor-record-page__empty">
<svg-icon icon-class="noContent" />
<p>暂无带教记录</p>
</div>
</div>
</div>
</template>
<script>
import { roleTeachingList, roleTeachingAdd } from '@/api/game'
import { mapState } from 'vuex'
export default {
name: 'MentorRecord',
props: {
roleId: {
type: [String, Number],
required: true
},
},
data() {
return {
loading: false,
submitLoading: false,
showAddForm: false,
teachingList: [],
formData: {
content: ''
}
}
},
watch: {
roleId: {
immediate: true,
handler(newVal) {
if (newVal) {
this.getTeachingList()
}
}
}
},
computed: {
...mapState('user', ['userInfo'])
},
methods: {
/**
* 获取带教记录列表
*/
async getTeachingList() {
if (!this.roleId) {
return
}
try {
this.loading = true
const res = await roleTeachingList({
role_id: this.roleId
})
if (res.status_code === 1) {
this.teachingList = res.data.data || []
// 按teaching_num倒序排列
this.teachingList.sort((a, b) => {
return (b.teaching_num || 0) - (a.teaching_num || 0)
})
} else {
this.$message({
message: res.data.msg || '获取带教记录失败',
type: 'error'
})
}
} catch (error) {
console.error('获取带教记录失败:', error)
this.$message({
message: '获取带教记录失败,请稍后重试',
type: 'error'
})
} finally {
this.loading = false
}
},
/**
* 新增带教记录
*/
async handleSubmitAdd() {
if (!this.formData.content || !this.formData.content.trim()) {
this.$message({
message: '请输入带教记录内容',
type: 'warning'
})
return
}
try {
this.submitLoading = true
const res = await roleTeachingAdd({
role_id: this.roleId,
teaching_num: this.teachingList.length + 1,
teaching_text: this.formData.content.trim(),
create_user_id: this.userInfo.id,
create_user: this.userInfo.username
})
if (res.status_code === 1) {
this.$message({
message: res.data.msg || '添加成功',
type: 'success'
})
this.formData.content = ''
this.showAddForm = false
// 重新获取列表
await this.getTeachingList()
// 通知父组件更新带教次数
this.$emit('refresh',this.roleId,this.teachingList.length)
} else {
this.$message({
message: res.data.msg || '添加失败',
type: 'error'
})
}
} catch (error) {
console.error('新增带教记录失败:', error)
this.$message({
message: '添加失败,请稍后重试',
type: 'error'
})
} finally {
this.submitLoading = false
}
},
/**
* 取消新增
*/
handleCancelAdd() {
this.formData.content = ''
this.showAddForm = false
},
}
}
</script>
<style lang="scss" scoped>
.mentor-record-page {
width: 100%;
height: 100%;
padding: 12px;
padding-top: 0;
background: #fff;
border-right: 1px solid #ebedf0;
display: flex;
flex-direction: column;
overflow: hidden;
&__header {
display: flex;
align-items: center;
padding: 12px 0;
padding-top: 0;
border-bottom: 1px solid #ebedf0;
&-title {
font-family: PingFangSC-Medium, PingFang SC;
font-size: 14px;
font-weight: 500;
line-height: 22px;
color: #131920;
}
}
&__toolbar {
display: flex;
align-items: center;
justify-content: flex-end;
margin-bottom: 20px;
&-tip {
font-family: PingFangSC-Regular, PingFang SC;
font-size: 12px;
font-weight: 400;
line-height: 20px;
color: #909399;
}
}
&__add-form {
display: flex;
flex-direction: column;
gap: 8px;
margin-bottom: 12px;
&-input {
::v-deep .el-textarea__inner {
border: 1px solid #d6d9e0;
border-radius: 6px;
padding: 4px 6px;
font-size: 13px;
line-height: 22px;
color: #323335;
min-height: 60px;
resize: none;
&::placeholder {
color: #c9cdd4;
}
}
}
&-buttons {
display: flex;
gap: 8px;
justify-content: flex-end;
}
}
&__list {
flex: 1;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 12px;
&-item {
background: #fff;
border: 1px solid #ebedf0;
border-radius: 6px;
padding: 8px;
display: flex;
flex-direction: column;
gap: 4px;
&-title {
font-family: PingFangSC-Regular, PingFang SC;
font-size: 12px;
font-weight: 400;
line-height: 20px;
color: #6d7176;
}
&-content {
font-family: PingFangSC-Regular, PingFang SC;
font-size: 15px;
font-weight: 500;
line-height: 22px;
color: #131920;
word-break: break-all;
}
&-footer {
display: flex;
align-items: center;
gap: 4px;
}
&-creator,
&-time {
font-family: PingFangSC-Regular, PingFang SC;
font-size: 12px;
font-weight: 400;
line-height: 20px;
color: #b0b2b5;
}
&-divider {
color: #ebedf0;
font-size: 12px;
}
}
}
&__empty {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40px 0;
color: #909399;
font-size: 14px;
p {
margin-top: 12px;
}
}
}
</style>
...@@ -23,6 +23,15 @@ module.exports = { ...@@ -23,6 +23,15 @@ module.exports = {
plugins: [ plugins: [
function({ addUtilities }) { function({ addUtilities }) {
const newUtilities = { const newUtilities = {
'.truncate': {
display: '-webkit-box',
'-webkit-box-orient': 'vertical',
'-webkit-line-clamp': '1',
'overflow': 'hidden',
'text-overflow': 'ellipsis',
'word-wrap': 'break-word',
'word-break': 'break-word',
},
'.truncate-2': { '.truncate-2': {
display: '-webkit-box', display: '-webkit-box',
'-webkit-box-orient': 'vertical', '-webkit-box-orient': 'vertical',
......
const { defineConfig } = require('@vue/cli-service') const { defineConfig } = require('@vue/cli-service')
const path = require('path') const path = require('path')
const fs = require('fs')
// 构建前删除 company_app 文件夹
function removeOutputDir() {
const outputDir = path.join(__dirname, 'company_app')
if (fs.existsSync(outputDir)) {
fs.rmSync(outputDir, { recursive: true, force: true })
console.log('✅ 已删除 company_app 文件夹')
}
}
// 只在构建模式下删除
if (process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'staging') {
removeOutputDir()
}
function resolve(dir) { function resolve(dir) {
return path.join(__dirname, dir) return path.join(__dirname, dir)
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论