提交 ae154c5a 作者: 毛细亚

开始调试发送游戏

上级 22a18be7
......@@ -20,11 +20,13 @@
"cos-js-sdk-v5": "^1.10.1",
"dingtalk-jsapi": "^3.1.0",
"element-ui": "^2.15.14",
"html2canvas": "^1.4.1",
"js-cookie": "^3.0.5",
"lib-flexible": "^0.3.2",
"lodash": "^4.17.21",
"moment": "^2.29.1",
"postcss-plugin-px2rem": "^0.8.1",
"qrcode.vue": "^3.6.0",
"sass": "^1.89.0",
"sass-loader": "^16.0.5",
"vconsole": "^3.15.1",
......
......@@ -41,6 +41,9 @@ importers:
element-ui:
specifier: ^2.15.14
version: 2.15.14(vue@2.7.16)
html2canvas:
specifier: ^1.4.1
version: 1.4.1
js-cookie:
specifier: ^3.0.5
version: 3.0.5
......@@ -56,6 +59,9 @@ importers:
postcss-plugin-px2rem:
specifier: ^0.8.1
version: 0.8.1
qrcode.vue:
specifier: ^3.6.0
version: 3.6.0(vue@2.7.16)
sass:
specifier: ^1.89.0
version: 1.89.0
......@@ -1336,6 +1342,10 @@ packages:
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
base64-arraybuffer@1.0.2:
resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==}
engines: {node: '>= 0.6.0'}
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
......@@ -1883,6 +1893,9 @@ packages:
peerDependencies:
postcss: ^8.0.9
css-line-break@2.1.0:
resolution: {integrity: sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==}
css-loader@6.11.0:
resolution: {integrity: sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==}
engines: {node: '>= 12.13.0'}
......@@ -2820,6 +2833,10 @@ packages:
webpack:
optional: true
html2canvas@1.4.1:
resolution: {integrity: sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==}
engines: {node: '>=8.0.0'}
htmlparser2@6.1.0:
resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==}
......@@ -4248,6 +4265,11 @@ packages:
(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)
qrcode.vue@3.6.0:
resolution: {integrity: sha512-vQcl2fyHYHMjDO1GguCldJxepq2izQjBkDEEu9NENgfVKP6mv/e2SU62WbqYHGwTgWXLhxZ1NCD1dAZKHQq1fg==}
peerDependencies:
vue: ^3.0.0
qs@6.13.0:
resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==}
engines: {node: '>=0.6'}
......@@ -4899,6 +4921,9 @@ packages:
engines: {node: '>=10'}
hasBin: true
text-segmentation@1.0.3:
resolution: {integrity: sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==}
thenify-all@1.6.0:
resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
engines: {node: '>=0.8'}
......@@ -5098,6 +5123,9 @@ packages:
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
engines: {node: '>= 0.4.0'}
utrie@1.0.2:
resolution: {integrity: sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==}
uuid@3.4.0:
resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==}
deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.
......@@ -7135,6 +7163,8 @@ snapshots:
balanced-match@1.0.2: {}
base64-arraybuffer@1.0.2: {}
base64-js@1.5.1: {}
batch@0.6.1: {}
......@@ -7643,6 +7673,10 @@ snapshots:
dependencies:
postcss: 8.5.3
css-line-break@2.1.0:
dependencies:
utrie: 1.0.2
css-loader@6.11.0(webpack@5.99.8):
dependencies:
icss-utils: 5.1.0(postcss@8.5.3)
......@@ -8835,6 +8869,11 @@ snapshots:
optionalDependencies:
webpack: 5.99.8
html2canvas@1.4.1:
dependencies:
css-line-break: 2.1.0
text-segmentation: 1.0.3
htmlparser2@6.1.0:
dependencies:
domelementtype: 2.3.0
......@@ -10317,6 +10356,10 @@ snapshots:
q@1.5.1:
optional: true
qrcode.vue@3.6.0(vue@2.7.16):
dependencies:
vue: 2.7.16
qs@6.13.0:
dependencies:
side-channel: 1.1.0
......@@ -11143,6 +11186,10 @@ snapshots:
commander: 2.20.3
source-map-support: 0.5.21
text-segmentation@1.0.3:
dependencies:
utrie: 1.0.2
thenify-all@1.6.0:
dependencies:
thenify: 3.3.1
......@@ -11364,6 +11411,10 @@ snapshots:
utils-merge@1.0.1: {}
utrie@1.0.2:
dependencies:
base64-arraybuffer: 1.0.2
uuid@3.4.0:
optional: true
......
......@@ -91,12 +91,12 @@ export default {
},
{
label: '通讯录',
path: '/mailList'
path: '/addressBook'
},
{
label: '快捷发送',
path: '/quickSendGame'
},
// {
// label: '快捷发送',
// path: '/quickSend'
// },
// {
// label: '通讯录',
// path: '/addressBook'
......@@ -311,7 +311,7 @@ export default {
/* 收起状态:只显示第一行 */
.mobile-el-menu.collapsed {
max-height: 50px;
max-height: 35px;
overflow: hidden;
}
......@@ -335,7 +335,7 @@ export default {
.menu-toggle-btn {
position: absolute;
right: 10px;
top: 25px;
top: 18px;
transform: translateY(-50%);
display: flex;
align-items: center;
......@@ -362,8 +362,8 @@ export default {
}
.el-menu--horizontal>.el-menu-item {
height: 50px;
line-height: 50px;
height: 35px;
line-height: 35px;
}
body {
......
......@@ -150,3 +150,61 @@ export function remarkSearchSelect(data) {
data
})
}
// 礼包可发送礼包
export function giftCodeList(data) {
return request({
url: returnApi('/corp_gift_package_list/getCanSendPackage'),
method: 'post',
data
})
}
// 礼包码发送
export function sendGiftCode(data) {
return request({
url: returnApi('/corp_gift_package_list/sendGiftCode'),
method: 'post',
data
})
}
// 获取举报授权链接地址
export function getZyouAuthLink(data) {
return request({
url: returnApi('/corp_zyou_bind/getZyouAuthLink'),
method: 'post',
data
})
}
// 转游最近发送的记录 5 条
export function getRecentSendLog(data) {
return request({
url: returnApi('/corp_zyou_game_send_log/getRecentSendLog'),
method: 'post',
data
})
}
// 标记转端
export function markTransScene(data) {
return request({
url: returnApi('/external_user/markTransScene'),
method: 'post',
data
})
}
// 根据用户 id 获取掌权分组
export function getZqCserGroup(data) {
return request({
url: returnApi('/common/getZqCserGroup'),
method: 'post',
data
})
}
// 根据用户 id 获取掌权项目
export function getZqCserWxBelong(data) {
return request({
url: returnApi('/common/getZqCserWxBelong'),
method: 'post',
data
})
}
\ No newline at end of file
<svg t="1718879942311" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4563" width="200" height="200"><path d="M256 960a128 128 0 0 1-128-128V466.645333A85.376 85.376 0 0 1 64 384v-106.666667a85.333333 85.333333 0 0 1 85.333333-85.333333h290.901334l-68.629334-68.629333a8.533333 8.533333 0 0 1 0-12.074667l33.194667-33.173333a8.533333 8.533333 0 0 1 12.053333 0l84.48 84.48 84.48-84.48a8.533333 8.533333 0 0 1 12.053334 0l33.194666 33.173333a8.533333 8.533333 0 0 1 0 12.074667l-68.650666 68.608L874.666667 192a85.333333 85.333333 0 0 1 85.333333 85.333333v106.666667a85.376 85.376 0 0 1-64 82.645333V832a128 128 0 0 1-128 128H256z m213.333333-490.666667H192v362.666667a64 64 0 0 0 60.245333 63.893333L256 896h213.333333V469.333333z m362.666667 0H533.333333v426.666667h234.666667a64 64 0 0 0 63.893333-60.245333L832 832V469.333333zM469.333333 256H149.333333a21.333333 21.333333 0 0 0-21.184 18.837333L128 277.333333v106.666667a21.333333 21.333333 0 0 0 18.837333 21.184L149.333333 405.333333h320v-149.333333z m405.333334 0H533.333333v149.333333h341.333334a21.333333 21.333333 0 0 0 21.184-18.837333L896 384v-106.666667a21.333333 21.333333 0 0 0-18.837333-21.184L874.666667 256z" fill="#8CA4BA" p-id="4564"></path></svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>VIP自助工具</title>
<g id="游戏" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="游戏-违规记录" transform="translate(-564, -468)" fill-rule="nonzero">
<g id="4.数据展示/10.Popover气泡卡片/上左⬇️" transform="translate(552, 452)">
<g id="VIP自助工具" transform="translate(12, 16)">
<rect id="矩形" fill="#000000" opacity="0" x="0" y="0" width="16" height="16"></rect>
<path d="M7.99821895,14.321585 C7.56391795,14.321585 7.15856419,14.1264531 6.85937495,13.7875521 L1.12654628,7.17392176 C0.595742151,6.55774355 0.576419359,5.61294483 1.09759904,4.97622538 L3.26912253,2.31640027 C3.55866885,1.95695807 3.98330845,1.75156533 4.43691378,1.75156533 L11.5884714,1.75156533 C12.0324338,1.75156533 12.4570734,1.95697773 12.7466197,2.31640027 L14.9277861,4.97622538 C15.4489658,5.61294483 15.4393044,6.55774355 14.8988389,7.17392176 L9.12742004,13.7875521 C8.83787372,14.1264531 8.42285856,14.321585 7.99821895,14.321585 Z M7.41909807,13.0918286 C7.55918834,13.2618573 7.75534332,13.351868 7.9701627,13.351868 C8.17564989,13.351868 8.37178699,13.2618573 8.52124521,13.0918286 L14.1160422,6.65100913 C14.3775584,6.35097981 14.3868906,5.89091444 14.1347066,5.58087331 L12.0051415,2.99054812 C11.8650333,2.82051939 11.659564,2.72051599 11.4447268,2.72051599 L4.5142988,2.72051599 C4.29947942,2.72051599 4.09399224,2.82051939 3.95388409,2.99054812 L1.85231552,5.58087331 C1.60013158,5.89091444 1.60946378,6.35097981 1.8709978,6.65100913 L7.41908019,13.0918286 L7.41909807,13.0918286 Z M7.681625,9.94284375 L4.49796875,6.6775625 C4.37553125,6.54695312 4.37553125,6.342875 4.50614063,6.21225 C4.63675,6.0898125 4.84082813,6.0898125 4.97145313,6.22042187 L7.92654688,9.249 L11.03675,6.21226562 C11.167375,6.0898125 11.3714375,6.0898125 11.5020625,6.22042187 C11.6245,6.35104687 11.6245,6.55510937 11.4938906,6.68573437 L8.14695313,9.95104687 C8.08164063,10.0081719 8.00001563,10.0408281 7.91839063,10.0408281 C7.83673438,10.0408281 7.7469375,10.0081562 7.681625,9.94284375 Z" id="形状" fill="#889FB5"></path>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
......@@ -48,11 +48,11 @@
</template>
<script>
import { remarkSearchSelect } from '@/api/user'
import { remarkSearchSelect } from '@/api/works'
import { mapState } from 'vuex'
export default {
name: 'SearchSelectUser',
props: ['placeholder', 'label', 'isResize', 'userid', 'disabled', 'width'],
props: ['placeholder','corp_id', 'label', 'isResize', 'userid', 'disabled', 'width'],
// End of Selection
data() {
return {
......@@ -100,6 +100,7 @@
const data = {
remark: this.resulte.trim(),
...this.pageInfo,
corp_id: [this.corp_id]|| [],
userid: this.userid || '',
}
remarkSearchSelect(data).then((res) => {
......
......@@ -4,12 +4,13 @@ import userInfo from '../views/userInfo/userInfo.vue'
import quickReply from '../views/quickReply.vue'
import giftRecord from '../views/giftRecord.vue'
import applyRecord from '../views/applyRecord.vue'
import addressBook from '../views/addressBook.vue'
import addressBook from '../views/mailList.vue'
import orderList from '../views/orderList.vue'
import roleInfo from '../views/roleInfo.vue'
import violationRecord from '../views/ViolationRecord.vue'
import taskRecord from '../views/taskRecord.vue'
import mailList from '@/views/mailList.vue'
import quickSendGame from '@/views/quickSendGame.vue'
import Cookies from 'js-cookie'
import store from '@/store'
Vue.use(VueRouter)
......@@ -69,9 +70,9 @@ const routes = [
component: taskRecord
},
{
path: '/mailList',
name: 'mailList',
component: mailList
path: '/quickSendGame',
name: 'quickSendGame',
component: quickSendGame
},
{
path: '/login',
......
<template>
<div class="sendGameContent">
<div
v-if="!disabled && bindGameUserList.length > 0"
class="btnRelease"
>
<div class="btntab">
<div
class="btn rowFlex allCenter"
:class="activeName == '1' ? 'btnActive' : ''"
:type="activeName == '1' ? 'primary' : ''"
@click="activeName = '1'"
>
转端
</div>
<div
class="btn rowFlex allCenter"
:class="activeName == '3' ? 'btnActive' : ''"
:type="activeName == '3' ? 'primary' : ''"
@click="recallTabChange"
>
召回
</div>
<div
class="btn rowFlex allCenter"
:class="activeName == '2' ? 'btnActive' : ''"
:type="activeName == '2' ? 'primary' : ''"
@click="requestRegGameList"
>
转游
</div>
</div>
<div
v-loading="contentLoading"
class="gameList"
>
<!-- 转端 -->
<el-collapse
v-if="activeName == '1' && conversionGameList.length > 0"
:disabled="disabled"
@change="conversionChangeOld"
>
<el-collapse-item
v-for="(item,index) in conversionGameList"
:key="index"
:title="item.game_text"
:name="item.game_type"
>
<div v-if="item.children && item.children.length > 0">
<div
v-for="(items, indexs) in item.children"
:key="indexs"
class="gameListItem rowFlex columnCenter spaceBetween"
>
<p>{{ items.game_name +'/'+items.game_id }}</p>
<el-popover
placement="top"
width="160"
trigger="hover"
>
<div>
<p
class="sendLink"
@click="sendLink(items,item.game_type)"
>
仅发送链接
</p>
<p
class="sendLink"
@click="sendPassword(items,item.game_type)"
>
仅发送账号密码
</p>
<p
class="sendLink"
@click="sendMessage(items,item.game_type)"
>
发送链接和账号密码
</p>
<p
class="sendLink"
@click="sendDownLoadPage(items,item.game_type,index)"
>
发送落地页
</p>
</div>
<el-button
slot="reference"
size="mini"
:disabled="accountSelect == ''"
>发送</el-button>
</el-popover>
</div>
</div>
<div
v-else-if="gameLoding"
class="channelLoading rowFlex allCenter"
>
<i class="el-icon-loading"></i>
<el-button type="text">加载中</el-button>
</div>
<div
v-else
class="rowFlex allCenter"
>暂无游戏</div>
</el-collapse-item>
</el-collapse>
<!-- 召回 -->
<div
v-else-if="activeName == '3' && recallGameList.length > 0"
class="collapseContent"
>
<!-- v-if="chatUser.task_type && chatUser.task_type == 7"-->
<el-button
v-if='false'
type="primary"
style="margin-left:50px;"
:loading="sendLoading"
@click="sendTaskChannel"
>根据任务一键发送链接</el-button>
<el-collapse
:disabled="disabled"
@change="recallChange"
>
<el-collapse-item
v-for="(item,index) in recallGameList"
:key="index"
:title="item.game_text"
:name="item.game_type"
>
<div v-if="item.children && item.children.length > 0">
<div
v-for="(items, indexs) in item.children"
:key="indexs"
class="gameListItem rowFlex columnCenter spaceBetween"
>
<p>{{ items.game_name +'/'+items.game_id }}</p>
<el-button
slot="reference"
size="mini"
:disabled="accountSelect == ''"
@click="sendChannel(items)"
>发送</el-button>
</div>
</div>
<div
v-else-if="gameLoding"
class="channelLoading rowFlex allCenter"
>
<i class="el-icon-loading"></i>
<el-button type="text">加载中</el-button>
</div>
<div
v-else
class="rowFlex allCenter"
>暂无游戏</div>
</el-collapse-item>
<!-- 新建渠道链接 -->
</el-collapse>
<div class="createChannel rowFlex allCenter">
<span class="label">找不到对应游戏的链接点此</span>
<el-button
type="text"
size="medium"
@click="showCreateChannel=true"
>新建渠道链接</el-button>
</div>
</div>
<!--
转游
1.转游 h5 游戏走之前的逻辑发送链接和账号密码
2.小游戏 发送的时候 先判断有没有模版的配置消息 如果没有 走之前的逻辑 如果有 获取掌游的背景图和二位那 合成新的图片 发送合成的图片
3.安卓或者 IOS 点击发送的时候 先判断是否有配置落地页 如果没有 走之前的发送逻辑 如果有 加入到发送的暂存列表中 加入时 需要判断和列表中已有的游戏是否时同一个项目和主游戏下 如果不是 提示错误 如果是 加入到暂存列表中 获取当前游戏下的渠道 选择渠道信息 发送给掌游后端 安卓或者 IOS 游戏 只能选择一个单选
-->
<div v-else-if="activeName == '2'">
<el-collapse
:disabled="disabled"
>
<el-input
v-model="filterGameText"
placeholder="请输入游戏名 按回车搜索"
style="margin-top: 10px"
@keydown.enter.native="changeGameText"
@blur="changeGameText"
>
<i
slot="prefix"
class="el-input__icon el-icon-search"
></i>
</el-input>
<el-collapse-item
v-for="(item, index) in regGameList"
:key="index"
:title="item.label"
>
<div v-if="regGameList.length > 0">
<div
v-for="(items, indexs) in item.children"
:key="indexs"
class="gameListItem rowFlex columnCenter spaceBetween"
>
<p>{{ items.label + "/" + items.id }}</p>
<!--game_type: 1 微信小游戏 2 H5 游戏 3 安卓游戏 4 IOS 游戏 5 抖音小游戏 -->
<!-- 微信小游戏 安卓游戏 IOS游戏 处理逻辑 -->
<el-popover
v-if="items.game_type == 1 || items.game_type == 3 || 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>
<el-button
slot="reference"
size="mini"
:disabled="accountSelect == ''"
>发送</el-button>
</el-popover>
<el-button
v-else
size="mini"
:disabled="accountSelect == ''"
@click="noH5AndroidIOSGame(items,item)"
>发送</el-button>
</div>
</div>
<!-- <div
class="channelLoading rowFlex allCenter"
v-else-if="gameLoding && false"
>
<i class="el-icon-loading"></i>
<el-button type="text">加载中</el-button>
</div> -->
<div
v-else
class="rowFlex allCenter"
>暂无游戏</div>
</el-collapse-item>
</el-collapse>
<div class="createChannel rowFlex allCenter">
<span class="label">找不到对应游戏的链接点此</span>
<el-button
type="text"
size="medium"
@click="showCreateChannel=true"
>新建渠道链接</el-button>
</div>
</div>
</div>
</div>
<div v-else>
<p>暂未绑定关联账号,请先去绑定账号</p>
</div>
<!-- 新建渠道链接 -->
<createChannel
v-if="showCreateChannel"
:type="activeName"
:show="showCreateChannel"
:game-user-info="gameUserInfo"
@close="showCreateChannel = false"
/>
<sendPage v-if="showSendPage" :show.sync="showSendPage" :game-list="conversionGameList" @confirm="startSendPage" />
<!-- 小游戏转游判断 -->
<SendTransWxGame
v-if="showWxGameDrawer"
:show.sync="showWxGameDrawer"
:game-list="selectedWxGameList"
:chat-user-info="chatUserInfo"
@close="SendTransWxGameClose"
@confirm="handleWxGameConfirm"
/>
<SendTransAppGame
v-if="showAppGameDrawer"
:show.sync="showAppGameDrawer"
:game-list="selectedAppGameList"
:chat-user-info="chatUserInfo"
@close="SendTransAppGameClose"
@confirm="handleAppGameConfirm"
/>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
import {
memberExtensionGameList,
passwardEncryption,
channelList,
selectSearch,
getTransferRecallGameList,
getGameConfig,
quickRecallChannelLink,
recallChannelSeq,
getLandingPageMemberLink,
getLandingPageConfig,
getMemberTransStatus
} from '@/api/game'
import { getRecentSendLog, markTransScene,getZqCserGroup,getZqCserWxBelong } from '@/api/works'
import { companyviewConfig } from '@/api/user'
import { throttle, throttleStart } from '@/utils/index'
import createChannel from './sendGame/createChannel'
import sendPage from './sendGame/SendTransPage.vue'
import SendTransWxGame from './sendGame/SendTransWxGame.vue'
import SendTransAppGame from './sendGame/SendTransAppGame.vue'
export default {
components: {
createChannel,
sendPage,
SendTransWxGame,
SendTransAppGame
},
data() {
return {
disabled: true,
showLayer: false,
showSendPage: false,
contentLoading: false,
gameLoding: false,
isReqeustData: false,
recallGameList: [], // 召回游戏列表
conversionGameList: [], // 转端游戏列表
weixin_blongs_id: [],
regGameList: [],
allRegGameList: [],
filterGameText: '',
channelselectList: [],
webForm: {
channel_id: ''
},
sendLoading: false,
belongList: [], // 项目列表
activeName: '1', // 转端 1 转游 2 召回 3
sendType: '', // 1 进发送链接 2 仅发送账号密码 3 发送链接和账号密码
showCreateChannel: false,
showImageComposer: false,
showWxGameDrawer: false,
showAppGameDrawer: false,
selectedWxGameList: [], // 微信小程序的选择的游戏
selectedAppGameList: [], // 安卓或者 Ios 选择的游戏
sendGameInfoSave: {},
imageInfo: {},
transMemberStatus: true
}
},
mounted() {
this.sendGameInfo()
},
computed: {
...mapState('game', ['accountSelect', 'bindGameUserList','chatUserInfo','gameUserInfo']),
...mapState('user', ['userInfo'])
},
// props: [ 'chatUserInfo', 'chatUser'],
watch: {
accountSelect(newVal, oldVal) {
// 切换 w 账号的时候清空 conversionGameList 数据
this.conversionGameList = []
this.getMemberTransStatus()
if (newVal && newVal !== '' && this.bindGameUserList.length > 0) {
this.disabled = false
} else {
this.disabled = true
}
},
activeName(newVal, oldVal) {
if (newVal) {
}
}
},
methods: {
...mapMutations('common', ['set_sendSkillMessage']),
// ...mapMutations('game', ['set_send_game_log']),
requestConfig() {
return new Promise((resolve, reject) => {
companyviewConfig().then((res) => {
this.weixin_blongs_id = res.data.weixin_blongs_id
resolve()
})
})
},
// 请求当前 W 账号是否符合转端条件 如果不符合 提示 当前w账号不满足转端要求,请联系组长处理
async getMemberTransStatus() {
if (this.accountSelect && this.accountSelect !== '') {
const res = await getMemberTransStatus({ member_id: this.accountSelect })
if (res.status_code == 1) {
this.transMemberStatus = res.data.data.allow_trans || false
}
} else {
this.transMemberStatus = false
}
},
recallTabChange() {
this.activeName = '3'
this.sendGameRecallList()
},
async requestGameSendLog() {
this.filterGameText = ''
const res = await getRecentSendLog()
if (res.status_code == 1) {
if (res.status_code == 1 && res.data.length > 0) {
res.data.map((item) => {
item.label = item.game_name
item.id = item.game_id
})
}
this.regGameList.unshift({
label: '最近发送',
children: res.data
})
}
},
async sendGameInfo() {
this.activeName = '1'
this.conversionGameList = []
this.recallGameList = []
this.getMemberTransStatus()
await this.requestConfig()
this.sendGameList()
},
requestRegGameList() {
this.activeName = '2'
if (this.gameUserInfo.main_game_id || this.gameUserInfo.main_game_id == 0) {
this.contentLoading = true
const data = {
type: 'gameListWithType',
value: '',
use_type: 2,
game_id: this.gameUserInfo.main_game_id,
use_user_id: this.userInfo.id,
weixin_blongs_id: this.weixin_blongs_id
}
selectSearch(data).then((res) => {
this.contentLoading = false
if (res.status_code == 1) {
// 暂时隐藏快手小游戏
const ksGameIndex = res.data.data.findIndex(item => item.label === '快手小游戏')
if (ksGameIndex !== -1) {
res.data.data.splice(ksGameIndex, 1)
}
this.regGameList = res.data.data
this.allRegGameList = this.regGameList
}
this.requestGameSendLog()
setTimeout(() => {
this.contentLoading = false
}, 2000)
})
} else {
}
},
onConfirm() { },
// 召回发送渠道
sendChannel(items, type) {
items.type = 3
type ? this.sendType = type : ''
this.channelList(items)
},
// 转游发送渠道
sendChannelGame(items, item, type) {
console.log(items, 'items', item)
type ? this.sendType = type : ''
const gameInfo = this.$clone(items)
gameInfo.type = 2
this.channelList(gameInfo)
},
changeGameText() {
console.log(this.filterGameText)
if (this.filterGameText.trim() === '') {
this.regGameList = this.allRegGameList
} else {
const list = JSON.parse(JSON.stringify(this.allRegGameList))
list.map((item, index) => {
item.children = item.children.filter(
(items) => items.label.indexOf(this.filterGameText) !== -1
)
})
this.regGameList = list
}
},
// 获取渠道列表
channelList(items) {
console.log(items, 'items')
const data = {
game_id: items.game_id || items.id,
page_size: 200,
page: 1,
zq_user_id: this.userInfo.id,
weixin_blongs_id: items.weixin_blongs_id ? [items.weixin_blongs_id] : this.weixin_blongs_id,
request_system: 'company_wx',
member_id: this.accountSelect,
use_type: this.activeName
}
channelList(data).then((res) => {
if (res?.data?.data?.data?.length > 0) {
// 只有一个的时候自动发送渠道链接
this.$emit('channelInfo', {
game_id: items.game_id,
use_type: this.activeName,
sendType: this.sendType,
channelList: res.data.data.data
})
this.sendGameLog(items)
} else {
this.$message.warning('请到掌游创建运营渠道')
}
})
},
showSendGameLayer() {
this.showLayer = true
},
async sendGameList() {
if (this.conversionGameList.length == 0) {
this.contentLoading = true
// 获取召回转端的游戏列表 user_type: 1 转端 3 召回
const res = await getGameConfig({ use_type: 1 })
this.contentLoading = false
if (res.status_code === 1 && res.data.data.length > 0) {
const ksGameIndex = res.data.data.findIndex(item => item.game_type == 6)
if (ksGameIndex != -1) {
res.data.data.splice(ksGameIndex, 1)
this.conversionGameList = res.data.data
} else {
this.conversionGameList = res.data.data
}
}
setTimeout(() => {
this.contentLoading = false
}, 2000)
}
},
async conversionChangeOld(value) {
console.log('请求数据', this.conversionGameList)
if (this.isReqeustData) {
return
}
try {
this.isReqeustData = true
this.gameLoding = true
// 使用 Promise.all 并发请求游戏列表数据
const promiseList = this.conversionGameList.map(async (item, index) => {
// 如果已有子项数据则跳过
if (this.conversionGameList[index].children?.length > 0) {
return
}
try {
const params = {
member_id: this.accountSelect,
type: item.game_type
}
const reslist = await memberExtensionGameList(params)
if (reslist.status_code === 1) {
// 使用解构赋值简化数据设置
const updates = {
children: reslist.data?.length > 0 ? reslist.data : [],
send_trans_page_id: '', // 转端要发送的游戏 ID
isReqeustData: true
}
Object.entries(updates).forEach(([key, value]) => {
this.$set(this.conversionGameList[index], key, value)
})
}
} catch (error) {
console.error(`Failed to fetch game list for index ${index}:`, error)
// 设置空数组作为默认值
this.$set(this.conversionGameList[index], 'children', [])
}
})
await Promise.all(promiseList)
this.handleConversionGameList()
} catch (error) {
console.error('Failed to fetch conversion game lists:', error)
} finally {
this.gameLoding = false
this.isReqeustData = false
}
},
// 处理转端数据 之前王鑫和冯渊说要隐藏破日开天游戏 至于什么时候放开 没说
handleConversionGameList() {
if (this.conversionGameList.length > 0) {
this.conversionGameList.forEach((item, index) => {
// 隐藏安卓游戏 安卓游戏 game_type: 3
if (item.game_type === 3 && item.children && item.children.length > 0) {
// 过滤掉 game_name 为"破日开天"的数据
const filteredChildren = item.children.filter(child => {
return child.game_name !== '破日开天' && child.game_name !== '英雄霸业'
})
this.$set(this.conversionGameList[index], 'children', filteredChildren)
}
// 隐藏 IOS 游戏 雄霸天下 有两个包 1 个是 691 一个是 819 王鑫说 暂时先隐藏 691 的功能
if (item.game_type === 4 && item.children && item.children.length > 0) {
const filteredChildren = item.children.filter(child => {
return Number(child.game_id) !== 691
})
this.$set(this.conversionGameList[index], 'children', filteredChildren)
}
})
console.log(this.conversionGameList, 'conversionGameList')
}
},
// 转端展开
async conversionChange(value) {
if (value && value.length > 0) {
const gameType = value[value.length - 1]
const gameIndex = this.conversionGameList.findIndex(item => item.game_type === gameType)
if (!this.conversionGameList[gameIndex].children || this.conversionGameList[gameIndex].children.length == 0) {
this.gameLoding = true
const params = {
page_size: 200,
page: 1,
zq_user_id: this.userInfo.id,
weixin_blongs_id: this.weixin_blongs_id,
use_type: 1,
member_id: this.accountSelect,
type: this.conversionGameList[gameIndex].game_type
}
const reslist = await getTransferRecallGameList(params)
this.gameLoding = false
if (reslist.status_code === 1 && reslist.data.data.length > 0) {
this.$set(this.conversionGameList[gameIndex], 'children', reslist.data.data)
} else {
this.$set(this.conversionGameList[gameIndex], 'children', [])
}
setTimeout(() => {
this.gameLoding = false
}, 2000)
} else {
}
}
},
// 召回的游戏列表
async sendGameRecallList() {
if (this.recallGameList.length == 0) {
this.contentLoading = true
const res = await getGameConfig({ use_type: 3 })
this.contentLoading = false
if (res.status_code === 1 && res.data.data.length > 0) {
const ksGameIndex = res.data.data.findIndex(item => item.game_type == 6)
if (ksGameIndex !== -1) {
res.data.data.splice(ksGameIndex, 1)
this.recallGameList = res.data.data
} else {
this.recallGameList = res.data.data
}
}
setTimeout(() => {
this.contentLoading = false
}, 2000)
}
},
// 召回展开
async recallChange(value) {
if (value && value.length > 0) {
const gameType = value[value.length - 1]
const gameIndex = this.recallGameList.findIndex(item => item.game_type === gameType)
if (!this.recallGameList[gameIndex].children || this.recallGameList[gameIndex].children.length == 0) {
this.gameLoding = true
const params = {
// type: 2,
page_size: 200,
page: 1,
zq_user_id: this.userInfo.id,
weixin_blongs_id: this.weixin_blongs_id,
use_type: 3,
member_id: this.accountSelect,
type: this.recallGameList[gameIndex].game_type
}
const reslist = await getTransferRecallGameList(params)
this.gameLoding = false
if (reslist.status_code === 1 && reslist.data.data.length > 0) {
this.$set(this.recallGameList[gameIndex], 'children', reslist.data.data)
} else {
this.$set(this.recallGameList[gameIndex], 'children', [])
}
setTimeout(() => {
this.gameLoding = false
}, 2000)
} else {
console.log('之前请求过了')
}
}
},
showPopover() {
this.showCreateChannel = false
this.isReqeustData = false
},
handlePopover() {
this.showCreateChannel = false
},
handleAccount() {
if (this.bindGameUserList.length > 0) {
const account = this.bindGameUserList.find(
(item) => item.member_id == this.accountSelect
)
if (account) {
return true
} else {
return false
}
} else {
return false
}
},
sendLink: throttle(function (item, type) {
if (!this.transMemberStatus) {
this.$message.warning('当前w账号不满足转端要求,请联系组长处理')
return
}
console.log(item, '转端发送仅发送链接')
const result = this.handleAccount()
if (!result) {
this.$message.warning('请稍后再试')
return false
}
let str = ''
if (type == 2) {
str = '网页游戏链接:'
} else if (type == 3) {
str = '安卓游戏链接:'
} else if (type == 4) {
str = 'IOS游戏链接:'
} else {
}
const list = [
{ msgtype: 'text', text: { content: `${str}${item.url}` }}
]
this.set_sendSkillMessage(list)
this.markTransScene(type)
item.type = 1
this.sendGameLog(item)
}, 500),
sendPassword: throttle(function (item, type) {
if (!this.transMemberStatus) {
this.$message.warning('当前w账号不满足转端要求,请联系组长处理')
return
}
console.log(item, '转端仅发送账号密码')
const result = this.handleAccount()
if (!result) {
this.$message.warning('请稍后再试')
return false
}
const username = this.bindGameUserList.find(
(items) => items.member_id == this.accountSelect
).username
passwardEncryption({ member_id: this.accountSelect })
.then((res) => {
const list = [
{
msgtype: 'text',
text: { content: `账号:${username} \n密码:${res.data.encryptPassword}`, key: res.data.key, iv: res.data.iv }
}
]
this.set_sendSkillMessage(list)
this.markTransScene(type)
this.sendGameLog(item)
})
.catch((err) => {
const list = [
{ msgtype: 'text', text: { content: `账号:${username}` }}
]
this.set_sendSkillMessage(list)
item.type = 1
this.sendGameLog(item)
console.log(err)
})
}, 500),
sendMessage: throttle(function (item, type) {
if (!this.transMemberStatus) {
this.$message.warning('当前w账号不满足转端要求,请联系组长处理')
return
}
const result = this.handleAccount()
if (!result) {
this.$message.warning('请稍后再试')
return false
}
let str = ''
if (type == 2) {
str = '网页游戏链接:'
} else if (type == 3) {
str = '安卓游戏链接:'
} else if (type == 4) {
str = 'IOS游戏链接:'
} else {
}
const username = this.bindGameUserList.find(
(items) => items.member_id == this.accountSelect
).username
passwardEncryption({ member_id: this.accountSelect })
.then((res) => {
const list = [
{
msgtype: 'text',
text: {
content: `${str}${item.url} \n账号:${username} \n密码:${res.data.encryptPassword}`,
key: res.data.key, iv: res.data.iv
}
}
]
this.set_sendSkillMessage(list)
this.markTransScene(type)
item.type = 1
this.sendGameLog(item)
})
.catch((err) => {
const list = [
{
msgtype: 'text',
text: { content: `${str}${item.url} \n账号:${username}` }
}
]
this.set_sendSkillMessage(list)
this.sendGameLog(item)
console.log(err)
})
}, 500),
// 发送游戏落地页
startSendPage(value) {
console.log(value, 'value')
const list = [
{
msgtype: 'image',
image: {
picurl: value
}
}
]
this.set_sendSkillMessage(list)
},
// 转端发送落地页面
sendDownLoadPage: throttleStart(function(items, type, index) {
if (!this.transMemberStatus) {
this.$message.warning('当前w账号不满足转端要求,请联系组长处理')
return
}
this.$set(this.conversionGameList[index], 'send_trans_page_id', items.game_id)
this.showSendPage = true
}, 500),
// 转端标记
async markTransScene(type) {
const data = {
external_userid: this.chatUserInfo.external_userid,
trans_scene: type
}
const res = await markTransScene(data)
if (res.status_code == 1) {
console.log('标记转端成功')
if (this.chatUserInfo.trans_scene && this.chatUserInfo.trans_scene !== '' && this.chatUserInfo.trans_scene != type) {
this.chatUserInfo.trans_scene = type
}
}
},
getZqCserWxBelong() {
return new Promise(async (resolve, reject) => {
const data = {
zq_user_id: Number(this.userInfo.id)
}
const res = await getZqCserWxBelong(data)
if (res.status_code === 1 && res.data.data) {
this.belongList = res.data.data.map(item => {
return {
value: item.value,
label: item.label && item.label.split('-')[0] ? item.label.split('-')[0] : ''
}
})
resolve(this.belongList)
} else {
this.$message.warning('暂无绑定项目,请先绑定项目')
reject(null)
}
})
},
// 一键发送任务链接
async sendTaskChannel() {
let groupItem = {}
let belonsList = {}
const group = await getZqCserGroup({ zq_user_id: Number(this.userInfo.id) })
belonsList = await this.getZqCserWxBelong()
if (group.status_code == 1 && group.data.data.length > 0 && belonsList && belonsList.length > 0) {
groupItem = group.data.data[0]
const group_name_list = groupItem.label.split('-')
const data = {
blongs_name: belonsList[0].label,
member_id: this.accountSelect,
use_user_id: this.userInfo.id,
use_user_name: this.userInfo.username,
group_id: groupItem.value,
group_name: group_name_list[group_name_list.length - 1],
game_type: this.chatUserInfo.trans_scene || ''
}
this.sendLoading = true
try {
setTimeout(() => {
this.sendLoading = false
}, 3000)
const res = await quickRecallChannelLink(data)
this.sendLoading = false
if (res.status_code == 1) {
this.sendGameInfoSave = res.data.data
this.handleSendType(res.data.data)
this.$message.success(res.msg)
}
} catch (error) {
this.$message.error('获取召回链接失败,请重新再试')
this.sendLoading = false
}
} else {
this.$message.error('获取分组失败,请到掌权添加分组')
return
}
},
sendGameLog(item) {
item && item.game_id && item.game_name ? this.set_send_game_log({ game_id: item.game_id, game_name: item.game_name, game_type: item.game_type || '', main_game_id: item.main_game_id, weixin_blongs_id: item.weixin_blongs_id, type: item.type || '' }) : ''
},
handleSendType(data) {
console.log(data, '获取一键发送的信息')
// 转端发送优先逻辑 不需要了 现在发送当前会话框选中的账号对应的注册游戏
data?.game_data?.game_type ? this.chatUserInfo.trans_scene = data.game_data.game_type : ''
if (this.chatUserInfo.trans_scene && this.chatUserInfo.trans_scene != 1) {
this.sendCreateChannel(data.game_data, data.game_data.game_type)
} else {
// 没有转端标记过,发送小程序链接 判断标题和封面是否存在 存在发小程序卡片 不存在发二维码
if (data.share_data.share_title && data.share_data.share_img) {
const list = [
{
msgtype: 'miniprogram',
miniprogram: {
appid: data.share_data.app_id,
rawid: data.share_data.raw_id,
channle_id: data.share_data.channel_key,
channle_name: data.share_data.channel_name,
title: data.share_data.share_title,
platform: 27,
page: data.share_data.page,
picurl: data.share_data.share_img
}
}
]
this.set_sendSkillMessage(list)
const game_data = this.$clone(data.game_data)
game_data.type = 3
console.log(game_data, 'data----------')
this.sendGameLog(game_data)
} else {
const list = [
{
msgtype: 'image',
image: {
picurl: data.game_data.game_url
}
}
]
this.set_sendSkillMessage(list)
this.sendGameLog(data.game_data)
}
}
this.recallChannelSeq(data)
},
// 召回染色
async recallChannelSeq(data) {
const param = {
game_id: data.game_data.game_id,
member_id: this.accountSelect,
key: data.game_data.channel_key || data.share_data.channel_key
}
const res = await recallChannelSeq(param)
},
sendCreateChannel: throttle(function (item, type) {
const result = this.handleAccount()
if (!result) {
this.$message.warning('请稍后再试')
return false
}
let str = ''
if (type == 2) {
str = '网页游戏链接:'
} else if (type == 3) {
str = '安卓游戏链接:'
} else if (type == 4) {
str = 'IOS游戏链接:'
} else {
}
const username = this.bindGameUserList.find(
(items) => items.member_id == this.accountSelect
).username
passwardEncryption({ member_id: this.accountSelect })
.then((res) => {
const list = [
{
msgtype: 'text',
// 一键发送渠道任务相关的参数
taskInfo: {
task_id: this.chatUser.task_id,
game_id: item.game_id,
member_id: this.accountSelect,
channel_key: item.channel_key
},
text: {
content: `${str}${item.game_url} \n账号:${username} \n密码:${res.data.encryptPassword}`,
key: res.data.key, iv: res.data.iv
}
}
]
this.set_sendSkillMessage(list)
item.type = 3
this.sendGameLog(item)
})
}, 500),
async getLandingPageConfig(items, item) {
try {
const params = {
main_game_id: items.main_game_id,
weixin_blongs_id: items.weixin_blongs_id,
type: items.game_type == 1 ? 2 : items.game_type == 3 || items.game_type == 4 ? 1 : ''
}
const res = await getLandingPageConfig(params)
if (res.status_code === 1 && res.data) {
return {
data: res.data,
game_type: items.game_type
}
} else {
return null
}
} catch (error) {
}
},
// 处理微信小程序游戏
handleWechatMiniGame(items, item, index) {
try {
this.selectedWxGameList = []
// 直接替换微信小游戏列表(单选)
this.selectedWxGameList = [item]
this.selectedWxGameList[0].send_trans_game_id = items.id
this.selectedWxGameList[0].send_trans_game_info = items
this.showWxGameDrawer = true
return true
} catch (error) {
console.error('处理微信小游戏失败:', error)
return false
}
},
// 过滤游戏列表的公共方法
filterGameList(sourceGame, targetList) {
if (!sourceGame || !targetList?.length) return []
return targetList.filter(game =>
game.weixin_blongs_id === sourceGame.weixin_blongs_id &&
game.main_game_id === sourceGame.main_game_id
)
},
handleAndroidList(items, item) {
const androidGameList = this.regGameList.find(item => item.label.includes('安卓'))
if (androidGameList && androidGameList.children && androidGameList.children.length > 0) {
androidGameList.children = this.filterGameList(items, androidGameList.children)
} else {
androidGameList.children = []
}
androidGameList.game_type = 3
if (items.game_type == 3) {
androidGameList.android_game_id = items.id
androidGameList.android_game_info = items
}
return androidGameList
},
handleIosList(items, item) {
const IOSGameList = this.regGameList.find(item => item.label.includes('IOS' || 'ios'))
IOSGameList.game_type = 4
if (IOSGameList && IOSGameList.children && IOSGameList.children.length > 0) {
IOSGameList.children = this.filterGameList(items, IOSGameList.children)
} else {
IOSGameList.children = []
}
if (items.game_type == 4) {
IOSGameList.ios_game_id = items.id
IOSGameList.ios_game_info = items
}
return IOSGameList
},
// 处理安卓 IOS 游戏
handleAppGameList(items, item, index) {
this.showAppGameDrawer = true
const androidGameList = this.handleAndroidList(items, item)
const IOSGameList = this.handleIosList(items, item)
androidGameList ? this.selectedAppGameList.push(androidGameList) : ''
IOSGameList ? this.selectedAppGameList.push(IOSGameList) : ''
console.log(this.selectedAppGameList, 'selectedAppGameList')
},
// 主方法
async handleGameType(items, item, type, index) {
if ((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)
if (result && result.data?.data?.tag) {
if (items.game_type == 1) {
// 处理微信小程序游戏
this.handleWechatMiniGame(items, item, index)
} else {
// 处理安卓/iOS游戏
this.handleAppGameList(items, item, index)
}
} else {
this.sendChannelGame(items, item)
}
} else {
this.sendChannelGame(items, item)
}
},
// 不是小游戏 安卓 IOS 游戏处理
noH5AndroidIOSGame(items, item) {
this.sendChannelGame(items, item)
},
// 小游戏游戏确认
async handleWxGameConfirm(value) {
console.log(value, 'value')
const list = [
{
msgtype: 'image',
image: {
picurl: value
}
}
]
this.set_sendSkillMessage(list)
},
SendTransAppGameClose() {
this.selectedAppGameList = []
},
SendTransWxGameClose() {
this.selectedWxGameList = []
},
// 安卓或者 IOS 游戏处理
handleAppGameConfirm(data) {
this.selectedAppGameList = []
const list = [
{
msgtype: 'text',
text: {
content: `游戏地址:${data.landing_page_url} \n账号:${data.username} \n密码:${data.password}`
}
}
]
this.set_sendSkillMessage(list)
}
}
}
</script>
<style lang="scss" scoped>
.sendGameContent{
.sendLink {
width: 150px;
height: 25px;
cursor: pointer;
}
.createChannel {
font-size: 14px;
.label {
color: #878787;
font-size: 12px;
margin-right: 5px;
}
}
.channelLoading {
color: #00bf8a;
font-size: 16px;
text-align: center;
}
.sendLink:hover {
color: #00bf8a;
}
.btnRelease {
position: relative;
padding-top: 40px;
// ::v-deep .el-collapse-item__header {
// border-bottom: none;
// background: #f7f8fa;
// }
}
.btntab {
width: 100%;
display: flex;
height: 36px;
position: absolute;
left: 0;
top: 0;
.btn {
flex: 1;
display: flex;
cursor: pointer;
}
.btnActive {
background: #00bf8a;
color: #fff;
}
}
.gameList {
width: 100%;
height: 300px;
overflow: auto;
::v-deep .el-tabs__item {
width: 70px;
}
.gameListItem {
width: 100%;
height: 40px;
background: #f7f8fa;
padding: 0 10px;
p {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
}
.icon {
font-size: 14px;
cursor: pointer;
}
}
::v-deep .el-collapse {
border-top: none;
border-bottom: none;
}
::v-deep .el-collapse-item__header {
border-bottom: none;
}
::v-deep .el-collapse-item__wrap {
border-bottom: none;
}
::v-deep .el-collapse {
border-top: none;
border-bottom: none;
}
::v-deep .el-collapse-item {
border-radius: 4px;
background: #f7f8fa;
}
::v-deep .el-collapse-item__content {
padding: 5px;
}
::v-deep .el-collapse-item__wrap {
border-bottom: none;
}
}
}
</style>
\ No newline at end of file
<template>
<!-- 转端发送游戏 -->
<el-drawer
title="选择游戏"
:visible="show"
width="400px"
@close="close"
>
<el-form
ref="appGameForm"
:model="appGameForm"
label-position="top"
class="game-select-container"
>
<!-- 安卓游戏 -->
<div v-if="filtered_android_games.length>0">
<el-form-item label="">
<template slot="label">
<p class="formLabel">安卓游戏</p>
</template>
<el-select
v-model="appGameForm.android_game_id"
placeholder="请选择安卓游戏"
style="width: 100%"
:clearable="true"
@change="handleAndroidGameChange"
>
<el-option
v-for="(item,index) in filtered_android_games[0].children"
:key="index"
:label="item.full_label || item.label || item.label"
:value="item.id || ''"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="">
<el-select
v-model="appGameForm.android_channel_id"
placeholder="请选择渠道"
style="width: 100%"
@change="androidChannelChange"
>
<el-option
v-for="(item,index) in androidChannelList"
:key="index"
:label="item.name"
:value="item.key"
>
</el-option>
</el-select>
</el-form-item>
</div>
<!-- IOS 游戏 -->
<div v-if="filtered_ios_games.length>0">
<el-form-item label="">
<template slot="label">
<p class="formLabel">IOS游戏</p>
</template>
<el-select
v-model="appGameForm.ios_game_id"
placeholder="请选择IOS游戏"
style="width: 100%"
:clearable="true"
@change="handleIosGameChange"
>
<el-option
v-for="(item,index) in filtered_ios_games[0].children"
:key="index"
:label="item.full_label || item.label || item.label"
:value="item.id || ''"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="">
<el-select
v-model="appGameForm.ios_channel_id"
placeholder="请选择渠道"
style="width: 100%"
:clearable="true"
@change="iosChannelChange"
>
<el-option
v-for="(item,index) in iosChannelList"
:key="index"
:label="item.name"
:value="item.key"
>
</el-option>
</el-select>
</el-form-item>
</div>
</el-form>
<span class="dialog-footer rowFlex">
<el-button
class="btn"
@click="close"
>取消</el-button>
<el-button
class="btn"
:loading="loading"
type="primary"
@click="handleConfirm"
>确认</el-button>
</span>
</el-drawer>
</template>
<script>
import { channelList, getLandingPageMemberLink } from '@/api/game'
import { mapState, mapMutations } from 'vuex'
export default {
name: 'SendTransAppGame',
components: {
},
props: {
show: {
default: false,
type: Boolean,
required: true
},
gameList: {
default: () => [],
type: Array,
validator: (value) => {
return Array.isArray(value) && value.every(item => typeof item === 'object')
}
},
chatUserInfo: {
default: () => ({}),
type: Object,
required: true
}
},
computed: {
...mapState('game', ['accountSelect', 'bindGameUserList']),
...mapState('user', ['userInfo'])
},
data() {
return {
loading: false,
appGameForm: {
android_game_id: '',
android_game_info: '',
android_channel_id: '',
android_channel_info: {},
ios_game_id: '',
ios_game_info: {},
ios_channel_id: '',
ios_channel_info: {}
},
androidChannelList: [], // 安卓游戏渠道列表
iosChannelList: [], // iOS游戏渠道列表
android_game_list: [],
ios_game_list: [],
filtered_android_games: [],
filtered_ios_games: []
}
},
async mounted() {
this.android_game_list = this.gameList.filter(item => item.game_type === 3)
this.ios_game_list = this.gameList.filter(item => item.game_type === 4)
// 初始化过滤后的列表
this.filtered_android_games = JSON.parse(JSON.stringify(this.android_game_list))
this.filtered_ios_games = JSON.parse(JSON.stringify(this.ios_game_list))
if (this.android_game_list.length > 0) {
this.appGameForm.android_game_id = this.android_game_list[0].android_game_id || ''
this.appGameForm.android_game_info = this.android_game_list[0].android_game_info || {}
// 如果有安卓游戏信息,过滤iOS游戏列表
if (this.appGameForm.android_game_info && this.appGameForm.android_game_info.id) {
if (this.ios_game_list[0]?.children) {
const filteredChildren = this.filterGameList(
this.appGameForm.android_game_info,
this.ios_game_list[0].children
)
this.filtered_ios_games = [{
...this.ios_game_list[0],
children: filteredChildren
}]
}
await this.channelList(this.appGameForm.android_game_info, 'android')
}
}
if (this.ios_game_list.length > 0) {
this.appGameForm.ios_game_id = this.ios_game_list[0].ios_game_id || ''
this.appGameForm.ios_game_info = this.ios_game_list[0].ios_game_info || {}
// 如果有iOS游戏信息,过滤安卓游戏列表
if (this.appGameForm.ios_game_info && this.appGameForm.ios_game_info.id) {
if (this.android_game_list[0]?.children) {
const filteredChildren = this.filterGameList(
this.appGameForm.ios_game_info,
this.android_game_list[0].children
)
this.filtered_android_games = [{
...this.android_game_list[0],
children: filteredChildren
}]
}
await this.channelList(this.appGameForm.ios_game_info, 'ios')
}
}
/**
* 当 this.appGameForm.android_game_info 中有值的时候 过滤 this.ios_game_list[0].children 中 weixin_blongs_id 和main_game_id 等于 this.appGameForm.android_game_info中的weixin_blongs_id 和 main_game_id 的数组 同样在选择安卓游戏的时候也进行此逻辑
同样当 this.appGameForm.ios_game_info 中有值的时候 过滤 this.android_game_list[0].children 中 weixin_blongs_id 和main_game_id 等于 this.appGameForm.ios_game_info中的weixin_blongs_id 和 main_game_id 的数组 同样在选择IOS游戏的时候也进行此逻辑 并且把过滤的方法抽离为一个公用的方法
*/
},
beforeDestroy() {
// 清理可能的副作用
this.androidChannelList = []
this.iosChannelList = []
},
methods: {
...mapMutations('game', ['set_send_game_log']),
// 获取渠道列表的方法
async channelList(items, type) {
try {
const data = {
game_id: items.id,
page_size: 200,
page: 1,
zq_user_id: this.userInfo.id,
weixin_blongs_id: items.weixin_blongs_id ? [items.weixin_blongs_id] : items.weixin_blongs_id,
request_system: 'company_wx',
member_id: this.accountSelect,
use_type: 2 // 固定为2,因为是转端
}
const res = await channelList(data)
if (res?.data?.data?.data?.length > 0) {
// 根据类型存储到不同的渠道列表
if (type === 'android') {
this.androidChannelList = res.data.data.data
} else if (type === 'ios') {
this.iosChannelList = res.data.data.data
}
} else {
if (type === 'android') {
this.androidChannelList = []
} else if (type === 'ios') {
this.iosChannelList = []
}
this.$message.warning('请到掌游创建运营渠道')
}
} catch (error) {
console.error('获取渠道列表失败:', error)
this.$message.error('获取渠道列表失败')
if (type === 'android') {
this.androidChannelList = []
} else if (type === 'ios') {
this.iosChannelList = []
}
}
},
sendGameLog(item) {
item && item.game_id && item.game_name ? this.set_send_game_log({ game_id: item.game_id, game_name: item.game_name, game_type: item.game_type || '', main_game_id: item.main_game_id, weixin_blongs_id: item.weixin_blongs_id, type: item.type || '' }) : ''
},
handleConfirm() {
this.handleWxGameChannel()
},
async handleWxGameChannel() {
this.loading = true
try {
// 检查是否选择了游戏和渠道
if (!this.appGameForm.android_game_id && !this.appGameForm.ios_game_id) {
this.$message.warning('请选选择游戏')
return
}
if (this.appGameForm.android_game_id && !this.appGameForm.android_channel_id) {
this.$message.warning('请选择安卓游戏渠道')
return
}
if (this.appGameForm.ios_game_id && !this.appGameForm.ios_channel_id) {
this.$message.warning('请选择IOS游戏渠道')
return
}
const channelList = []
if (this.appGameForm.android_channel_info && this.appGameForm.android_channel_info.key) {
const { game_id, key, game_type } = this.appGameForm.android_channel_info
channelList.push({
game_id,
channel_key: key,
game_type
})
this.sendGameLog(this.appGameForm.android_channel_info)
}
if (this.appGameForm.ios_channel_info && this.appGameForm.ios_channel_info.key) {
const { game_id, key, game_type } = this.appGameForm.ios_channel_info
channelList.push({
game_id,
channel_key: key,
game_type
})
this.sendGameLog(this.appGameForm.ios_channel_info)
}
const params = {
member_id: this.accountSelect,
zq_user_id: this.userInfo.id,
zq_user_name: this.userInfo.username,
use_type: 2,
corp_id: this.chatUserInfo.corp_id,
external_user_id: this.chatUserInfo.external_userid,
userid: this.chatUserInfo.userid,
// weixin_blongs_id: this.appGameForm.android_game_info.weixin_blongs_id || this.appGameForm.ios_game_info.weixin_blongs_id,
// main_game_id: this.appGameForm.android_game_info.main_game_id || this.appGameForm.ios_game_info.main_game_id,
game: channelList
}
if (this.appGameForm.android_game_info && this.appGameForm.android_game_info.weixin_blongs_id) {
params.weixin_blongs_id = this.appGameForm.android_game_info.weixin_blongs_id
params.main_game_id = this.appGameForm.android_game_info.main_game_id
} else if
(this.appGameForm.ios_game_info && this.appGameForm.ios_game_info.weixin_blongs_id) {
params.weixin_blongs_id = this.appGameForm.ios_game_info.weixin_blongs_id
params.main_game_id = this.appGameForm.ios_game_info.main_game_id
}
const res = await getLandingPageMemberLink(params)
if (res && res.data.data) {
this.loading = false
this.close()
this.$emit('confirm', res.data.data)
this.$message.success('发送成功')
}
} catch (error) {
this.loading = false
console.error('获取链接失败:', error)
this.$message.error(error.message || '获取链接失败,请重试')
} finally {
this.loading = false
}
setTimeout(() => {
this.loading = false
}, 4000)
},
close() {
this.$emit('close')
this.$emit('update:show', false)
},
// 过滤游戏列表的公共方法
filterGameList(sourceGame, targetList) {
if (!sourceGame || !targetList?.length) return []
return targetList.filter(game =>
game.weixin_blongs_id === sourceGame.weixin_blongs_id &&
game.main_game_id === sourceGame.main_game_id
)
},
// 安卓渠道选择
androidChannelChange(value) {
if (value) {
this.appGameForm.android_channel_info = this.androidChannelList.find(item => item.key === value)
}
},
iosChannelChange(value) {
if (value) {
this.appGameForm.ios_channel_info = this.iosChannelList.find(item => item.key === value)
}
},
// 监听安卓游戏选择变化
async handleAndroidGameChange(gameId) {
this.appGameForm.android_channel_id = '' // 清空渠道选择
this.appGameForm.android_channel_info = {} // 清空渠道选择
this.androidChannelList = []
if (!gameId) {
this.appGameForm.android_game_info = null
this.androidChannelList = [] // 清空安卓渠道列表
// 重置iOS过滤列表为原始列表
this.filtered_ios_games = JSON.parse(JSON.stringify(this.ios_game_list))
return
}
// 获取选中的安卓游戏信息
const selectedGame = this.android_game_list[0]?.children?.find(game => game.id === gameId)
if (selectedGame) {
this.appGameForm.android_game_info = selectedGame
// 获取安卓游戏渠道列表
await this.channelList(selectedGame, 'android')
// 过滤 iOS 游戏列表并保存到过滤后的列表中
if (this.ios_game_list[0]?.children) {
const filteredChildren = this.filterGameList(
selectedGame,
this.ios_game_list[0].children
)
// 创建新的过滤后的iOS游戏列表
this.filtered_ios_games = [{
...this.ios_game_list[0],
children: filteredChildren
}]
}
}
},
// 监听 iOS 游戏选择变化
async handleIosGameChange(gameId) {
this.appGameForm.ios_channel_id = '' // 清空渠道选择
this.appGameForm.ios_channel_info = {} // 清空渠道选择
this.iosChannelList = []
if (!gameId) {
this.appGameForm.ios_game_info = null
this.iosChannelList = [] // 清空iOS渠道列表
// 重置安卓过滤列表为原始列表
this.filtered_android_games = JSON.parse(JSON.stringify(this.android_game_list))
return
}
// 获取选中的 iOS 游戏信息
const selectedGame = this.ios_game_list[0]?.children?.find(game => game.id === gameId)
if (selectedGame) {
this.appGameForm.ios_game_info = selectedGame
// 获取iOS游戏渠道列表
await this.channelList(selectedGame, 'ios')
// 过滤安卓游戏列表并保存到过滤后的列表中
if (this.android_game_list[0]?.children) {
const filteredChildren = this.filterGameList(
selectedGame,
this.android_game_list[0].children
)
// 创建新的过滤后的安卓游戏列表
this.filtered_android_games = [{
...this.android_game_list[0],
children: filteredChildren
}]
}
}
}
}
}
</script>
<style scoped lang="scss">
.formLabel {
font-size: 16px;
font-weight: 500;
}
.dialog-footer {
width: calc(100%);
height: auto;
position: absolute;
padding-top: 20px;
padding-bottom: 20px;
bottom: 0;
right: 0;
justify-content: flex-end;
border-top: 1px solid rgba(0, 0, 0, 0.06);
background: #fff;
.btn {
width: 84px;
height: 32px;
}
}
.game-select-container {
padding: 0 20px;
::v-deep .el-icon-circle-close{
color: #C0C4CC !important;
}
::v-deep .el-form-item__label{
line-height: 32px;
padding: 3px;
}
}
.compose-container {
position: fixed;
left: -9999px;
top: -9999px;
overflow: hidden;
z-index: -1;
}
.image-wrapper {
position: relative;
display: none;
font-size: 0;
max-width: 750px;
width: 100%;
}
.background-img {
display: block;
width: 100%;
height: auto;
object-fit: contain;
}
</style>
\ No newline at end of file
<template>
<!-- 转端发送游戏 -->
<el-drawer
title="选择游戏"
:visible="show"
width="400px"
@close="close"
>
<el-form label-position="top" class="game-select-container">
<div v-for="(item,index) in gameList" :key="index">
<el-form-item :label="gameTypeLabel(item.game_type)">
<el-select
v-model="item.send_trans_page_id"
placeholder="请选择游戏"
style="width: 100%"
:clearable="true"
>
<el-option
v-for="(item,index) in item.children"
:key="index"
:label="item.game_name + ' / ' + item.game_id || ''"
:value="item.game_id || ''"
>
</el-option>
</el-select>
</el-form-item>
</div>
</el-form>
<div v-show="false" class="createImage">
<qrcode-vue ref="qrcode" :value="sendPageUrl" :size="size" level="H"></qrcode-vue>
</div>
<span class="dialog-footer rowFlex">
<el-button class="btn" @click="close">取消</el-button>
<el-button class="btn" type="primary" :loading="loading" @click="handleConfirm">确认</el-button>
</span>
</el-drawer>
</template>
<script>
import { getLandingPageTransfer } from '@/api/game'
import { mapState, mapMutations } from 'vuex'
import QrcodeVue from 'qrcode.vue'
export default {
name: 'SendTransPage',
components: {
QrcodeVue
},
props: {
show: {
default: false,
type: Boolean
},
gameList: {
default: () => [],
type: Array
}
},
computed: {
...mapState('game', ['accountSelect', 'bindGameUserList']),
...mapState('user', ['userInfo'])
},
data() {
return {
loading: false,
sendPageUrl: '',
size: 200,
gameInfoLog: []
}
},
mounted() {
},
methods: {
...mapMutations('game', ['set_send_game_log']),
async getQRCodeBlob() {
const canvas = this.$refs.qrcode.$el.querySelector('canvas')
try {
const blob = await new Promise(resolve => {
canvas.toBlob(blob => {
resolve(blob)
}, 'image/png')
})
blob.name = 'sendPageImage.png'
// 如果需要预览,可以创建一个临时 URL
// const blobUrl = URL.createObjectURL(blob)
this.uploadCos(blob)
} catch (error) {
this.loading = false
console.error('获取 Blob 失败:', error)
}
},
async uploadCos(File) {
const uploadConfig = {
dir: '/company_wx/service/avatars/'
}
const result = await this.uploading(File, uploadConfig)
if (result.data) {
this.loading = false
this.$emit('confirm', result.data)
this.close()
} else {
this.loading = false
this.$message.warning('二维码上传失败,请重新生成')
}
setTimeout(() => {
this.loading = false
}, 2000)
},
gameTypeLabel(game_type) {
switch (game_type) {
case 2:
return 'H5游戏'
case 3:
return '安卓游戏'
case 4:
return 'IOS游戏'
default:
return ''
}
},
async handleConfirm() {
const sendGameList = this.gameList.filter(item => item.send_trans_page_id).map(item => {
return {
game_type: item.game_type,
game_id: item.send_trans_page_id
}
})
this.gameInfoLog = this.gameList.map(item => {
if (item.send_trans_page_id && item.send_trans_page_id !== '') {
const gameInfo = item.children.find(items => items.game_id == item.send_trans_page_id)
return gameInfo
} else {
return null
}
})
this.gameInfoLog = this.gameInfoLog.filter(item => item)
// if (this.gameInfoLog && this.gameInfoLog.length > 0) {
// this.gameInfoLog.map(item => {
// setTimeout(() => {
// this.set_send_game_log({ game_id: item.game_id, game_name: item.game_name })
// }, 500)
// })
// }
this.loading = true
try {
const account = this.bindGameUserList.find(
(item) => item.member_id == this.accountSelect
)
const data = {
zq_user_id: this.userInfo.id,
zq_user_name: this.userInfo.username,
username: account.username,
member_id: this.accountSelect,
game: sendGameList
}
const res = await getLandingPageTransfer(data)
if (res.status_code === 1 && res.data?.data?.landing_page_url) {
this.sendPageUrl = res.data.data.landing_page_url
await this.$nextTick()
setTimeout(() => {
this.getQRCodeBlob()
}, 300)
} else {
this.$message.warning('获取落地页地址失败')
}
} catch (error) {
this.loading = false
} finally {
this.loading = false
}
},
close() {
this.$emit('update:show', false)
}
}
}
</script>
<style scoped lang="scss">
.dialog-footer{
width: calc(100%);
height: auto;
position: absolute;
padding-top: 20px;
padding-bottom: 20px;
bottom: 0;
right: 0;
justify-content: flex-end;
border-top: 1px solid rgba(0, 0, 0, 0.06);
background: #fff;
.btn{
width:84px ;
height: 32px;
}
}
.game-select-container {
padding: 0 20px;
::v-deep .el-icon-circle-close{
color: #C0C4CC !important;
}
::v-deep .el-form-item__label{
line-height: 32px;
padding: 0;
}
}
</style>
\ No newline at end of file
<template>
<!-- 转端发送游戏 -->
<el-drawer
title="选择游戏"
:visible="show"
width="400px"
@close="close"
>
<el-form ref="wxGameForm" :model="wxGameForm" :rules="wxGameRules" label-position="top" class="game-select-container">
<!-- 微信小游戏 -->
<el-form-item label="">
<template slot="label">
<p class="formLabel">微信小游戏</p>
</template>
<el-select
v-model="wxGameForm.wx_game_send_id"
placeholder="请选择微信小游戏"
style="width: 100%"
disabled
>
<el-option
v-for="(item,index) in gameList[0].children"
:key="index"
:label="item.full_label || item.label || item.label"
:value="item.id || ''"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="">
<el-select
v-model="wxGameForm.wx_game_channel"
placeholder="请选择渠道"
style="width: 100%"
:clearable="true"
>
<el-option
v-for="(item,index) in wxGameChannelList"
:key="index"
:label="item.name"
:value="item.key"
>
</el-option>
</el-select>
</el-form-item>
</el-form>
<span class="dialog-footer rowFlex">
<el-button class="btn" @click="close">取消</el-button>
<el-button class="btn" :loading="loading" type="primary" @click="handleConfirm">确认</el-button>
</span>
<div ref="composeContainer" class="compose-container">
<div ref="imageWrapper" class="image-wrapper">
<img
ref="bgImg"
:src="imageInfo.background_img"
class="background-img"
crossorigin="anonymous"
:style="{
width: '750px',
height: 'auto'
}"
>
<img
ref="qrImg"
:src="imageInfo.channel_qrcode"
class="qr-code"
crossorigin="anonymous"
:style="{
position: 'absolute',
left: `${imageInfo['x-coordinate']}px`,
top: `${imageInfo['y-coordinate']}px`,
width: '180px',
height: '180px'
}"
>
</div>
</div>
</el-drawer>
</template>
<script>
import { channelList, getLandingPageMemberLink } from '@/api/game'
import { mapState, mapMutations } from 'vuex'
import { throttleStart } from '@/utils/index'
import html2canvas from 'html2canvas'
export default {
name: 'SendTransWxGame',
components: {
},
props: {
show: {
default: false,
type: Boolean
},
gameList: {
default: () => [],
type: Array
},
chatUserInfo: {
default: () => {},
type: Object
}
},
computed: {
...mapState('game', ['accountSelect', 'bindGameUserList']),
...mapState('user', ['userInfo']),
hasWxGameChannels() {
return this.wxGameChannelList && this.wxGameChannelList.length > 0
}
},
data() {
return {
imageInfo: {},
resultImage: '',
loading: false,
wxGameForm: {
wx_game_send_id: '',
wx_game_send_info: {},
wx_game_channel: ''
},
messageInfo: null,
handleConfirmWithDebounce: {},
wxGameChannelList: [],
wxGameRules: {
wx_game_send_id: [
{ required: true, message: '请选择微信小游戏', trigger: 'change' }
],
wx_game_channel: [
{ required: true, message: '请选择渠道', trigger: 'change' }
]
}
}
},
created() {
this.handleConfirmWithDebounce = throttleStart(this.handleConfirm, 300)
},
mounted() {
this.wxGameForm.wx_game_send_info = this.gameList[0].send_trans_game_info
this.wxGameForm.wx_game_send_id = this.gameList[0].send_trans_game_id
this.channelList(this.gameList[0].send_trans_game_info)
},
beforeDestroy() {
// 清理可能的副作用
this.wxGameForm = {
wx_game_send_id: '',
wx_game_send_info: {},
wx_game_channel: ''
}
this.wxGameChannelList = []
this.closeMessage()
this.loading = false
// 清理图片资源
if (this.$refs.bgImg) this.$refs.bgImg.src = ''
if (this.$refs.qrImg) this.$refs.qrImg.src = ''
},
methods: {
...mapMutations('game', ['set_send_game_log']),
closeMessage() {
this.messageInfo ? this.messageInfo.close() : ''
this.loading = false
},
async composeImage(retryCount = 3) {
for (let i = 0; i < retryCount; i++) {
try {
this.loading = true
this.messageInfo = this.$message({
message: '正在生成海报,请稍等一会',
type: 'warning',
duration: 0
})
// 1. 预加载图片并转换为 base64
const loadImage = (url) => {
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
reject(new Error('图片加载超时'))
}, 60000) // 60秒超时
const img = new Image()
img.crossOrigin = 'anonymous'
img.onload = () => {
clearTimeout(timeout)
// 创建canvas转换为base64
const canvas = document.createElement('canvas')
canvas.width = img.width
canvas.height = img.height
const ctx = canvas.getContext('2d')
ctx.drawImage(img, 0, 0)
resolve(canvas.toDataURL('image/png'))
}
img.onerror = () => {
clearTimeout(timeout)
reject(new Error(`图片加载失败: ${url}`))
}
img.src = url + '?t=' + new Date().getTime()
})
}
// 2. 转换背景图和二维码为base64
try {
const [bgBase64, qrBase64] = await Promise.all([
loadImage(this.imageInfo.background_img),
loadImage(this.imageInfo.channel_qrcode)
])
// 3. 更新图片源为base64
const bgImg = this.$refs.bgImg
const qrImg = this.$refs.qrImg
bgImg.src = bgBase64
qrImg.src = qrBase64
// 4. 等待DOM更新
await this.$nextTick()
const element = this.$refs.imageWrapper
if (!element) {
throw new Error('合成容器不存在')
}
// 设置容器尺寸
const width = 750
const height = (bgImg.naturalHeight / bgImg.naturalWidth) * width
// 设置样式
element.style.visibility = 'visible'
element.style.display = 'block'
element.style.width = `${width}px`
element.style.height = `${height}px`
// 使用 html2canvas 合成
const canvas = await html2canvas(element, {
useCORS: true,
allowTaint: true,
backgroundColor: null,
scale: window.devicePixelRatio || 2,
width,
height,
imageTimeout: 0,
logging: process.env.NODE_ENV !== 'production',
onclone: (doc) => {
const clonedWrapper = doc.querySelector('.image-wrapper')
if (clonedWrapper) {
clonedWrapper.style.visibility = 'visible'
clonedWrapper.style.display = 'block'
clonedWrapper.style.width = `${width}px`
clonedWrapper.style.height = `${height}px`
}
}
})
// 恢复元素状态
element.style.visibility = 'hidden'
element.style.display = 'none'
element.style.width = ''
element.style.height = ''
if (!canvas || canvas.width === 0 || canvas.height === 0) {
this.closeMessage()
throw new Error('Canvas 生成失败')
}
// 检查canvas是否有内容
const ctx = canvas.getContext('2d')
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
const hasContent = imageData.data.some(pixel => pixel !== 0)
if (!hasContent) {
this.closeMessage()
throw new Error('Canvas 生成的图片为空')
}
// 转换为blob
const blob = await new Promise((resolve, reject) => {
canvas.toBlob(
blob => {
if (blob && blob.size > 0) {
console.log('Blob 生成成功,大小:', blob.size)
resolve(blob)
} else {
this.closeMessage()
reject(new Error('生成的Blob为空'))
}
},
'image/png',
1.0
)
})
const timer = new Date().getTime()
blob.name = `sendGameComposer${timer}.png`
await this.uploadCos(blob)
break
} catch (error) {
throw new Error(`图片预处理失败: ${error.message}`)
}
} catch (error) {
if (i === retryCount - 1) throw error
console.warn(`第${i + 1}次尝试失败,准备重试...`)
await new Promise(resolve => setTimeout(resolve, 1000))
}
}
},
// 获取渠道列表
channelList(items) {
const data = {
game_id: items.game_id || items.id,
page_size: 200,
page: 1,
zq_user_id: this.userInfo.id,
weixin_blongs_id: items.weixin_blongs_id ? [items.weixin_blongs_id] : items.weixin_blongs_id,
request_system: 'company_wx',
member_id: this.accountSelect,
use_type: 2
}
channelList(data).then((res) => {
if (res?.data?.data?.data?.length > 0) {
// 只有一个的时候自动发送渠道链接
this.wxGameChannelList = res.data.data.data || []
} else {
this.wxGameChannelList = []
this.$message.warning('请到掌游创建运营渠道')
}
})
},
async uploadCos(File) {
const uploadConfig = {
dir: '/company_wx/service/avatars/'
}
const result = await this.uploading(File, uploadConfig)
if (result.data) {
this.closeMessage()
this.resultImage = result.data
this.$message.success('海报生成完成')
this.$emit('confirm', result.data)
this.close()
} else {
this.$message.warning('二维码上传失败,请重新生成')
}
},
handleConfirm() {
this.handleWxGameChannel()
},
sendGameLog(item) {
item && item.game_id && item.game_name ? this.set_send_game_log({ game_id: item.game_id, game_name: item.game_name, game_type: item.game_type || '', main_game_id: item.main_game_id, weixin_blongs_id: item.weixin_blongs_id, type: item.type || '' }) : ''
},
// 保存微信小游戏的信息
async handleWxGameChannel() {
if (!this.wxGameForm.wx_game_channel) {
this.$message.warning('请选择渠道')
return
}
const channelInfo = this.wxGameChannelList.find(item => item.key === this.wxGameForm.wx_game_channel)
if (!channelInfo) {
this.$message.error('渠道信息获取失败')
return
}
this.sendGameLog(channelInfo)
this.loading = true
try {
const { game_id, key, game_type } = channelInfo
const params = {
member_id: this.accountSelect,
zq_user_id: this.userInfo.id,
zq_user_name: this.userInfo.username,
use_type: 2,
corp_id: this.chatUserInfo.corp_id,
external_user_id: this.chatUserInfo.external_userid,
userid: this.chatUserInfo.userid,
weixin_blongs_id: this.wxGameForm.wx_game_send_info.weixin_blongs_id,
main_game_id: this.wxGameForm.wx_game_send_info.main_game_id,
game: [{
game_id,
channel_key: key,
game_type
}]
}
// const errInfo = {
// background_img: 'https://zyouapk.zwnet.cn/zhangsheng/production/android/front_cover/3Ce3A6zw7yrxibk61737354350385.jpg',
// channel_qrcode: 'https://zyouapk.zwnet.cn/zhangsheng/production/zy_main/qr_code_link/104159.png',
// 'x-coordinate': 524,
// 'y-coordinate': 668
// }
// const trueInfo = {
// background_img: 'https://zyouapk.zwnet.cn/zhangsheng/production/android/front_cover/3Ce3A6zw7yrxibk61737354350385.jpg',
// channel_qrcode: 'https://zyouapk.zwnet.cn/zhangsheng/production/zy_main/qr_code_link/104208.png',
// 'x-coordinate': 524,
// 'y-coordinate': 668
// }
console.log('请求参数:', params)
const linkRes = await getLandingPageMemberLink(params)
console.log('获取到的落地页数据:', linkRes)
if (linkRes?.data?.data) {
// 检查返回的数据结构
console.log('设置前的imageInfo:', this.imageInfo)
this.imageInfo = linkRes.data.data
console.log('设置后的imageInfo:', this.imageInfo)
await this.composeImage()
} else {
throw new Error('获取落地页数据失败')
}
} catch (error) {
this.loading = false
console.error('获取落地页链接失败:', error)
this.$message.error(error.message || '获取链接失败,请重试')
} finally {
this.loading = false
}
},
close() {
this.closeMessage()
this.$emit('close')
this.$emit('update:show', false)
}
}
}
</script>
<style scoped lang="scss">
.formLabel{
font-size: 16px;
font-weight: 500;
}
.dialog-footer{
width: calc(100%);
height: auto;
position: absolute;
padding-top: 20px;
padding-bottom: 20px;
bottom: 0;
right: 0;
justify-content: flex-end;
border-top: 1px solid rgba(0, 0, 0, 0.06);
background: #fff;
.btn{
width:84px ;
height: 32px;
}
}
.game-select-container {
padding: 0 20px;
::v-deep .el-icon-circle-close{
color: #C0C4CC !important;
}
::v-deep .el-form-item__label{
line-height: 32px;
padding: 3px;
}
}
.compose-container {
position: fixed;
left: -9999px;
top: -9999px;
overflow: hidden;
z-index: -1;
}
.image-wrapper {
position: relative;
display: none;
font-size: 0;
width: 750px; /* 固定容器宽度 */
}
.background-img {
display: block;
width: 750px !important; /* 固定宽度 */
height: auto !important; /* 高度自适应 */
object-fit: contain;
}
.qr-code {
position: absolute;
display: block;
width: 180px !important;
height: 180px !important;
object-fit: contain;
pointer-events: none;
}
</style>
\ No newline at end of file
<template>
<el-dialog
title="新建渠道链接"
:visible="show"
@close='close'
width="500px"
>
<div class="channelContent">
<el-form
:model="formData"
:rules="rules"
ref="formData"
label-width="100px"
>
<el-form-item
label="使用人"
prop="use_user_id"
>
<el-input
v-model="formData.use_user_name"
disabled
></el-input>
</el-form-item>
<el-form-item
label="小组"
prop="group_id"
>
<el-select
v-model="formData.group_id"
size="small"
placeholder="请选择小组"
filterable
style='width:100%;'
@change="groupChange"
>
<el-option
v-for="item in optionsList.groupList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item
label="马甲包"
prop="game_id"
>
<mainGameSelect
:defaultValue="formData.game_id"
style="width:100%;"
@result="changeGame"
/>
</el-form-item>
<el-form-item
v-if="loginButton"
label="登录类型"
prop="login_type"
>
<el-checkbox-group v-model="formData.login_type">
<el-checkbox label="1">验证码登录</el-checkbox>
<el-checkbox label="2">账号密码</el-checkbox>
<el-checkbox label="3">快捷登录 </el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item
label="分销方"
prop="distributor_id"
>
<el-select
v-model="formData.distributor_id"
size="small"
placeholder="请先选择游戏"
filterable
style='width:100%;'
@change="onDistributorChange"
>
<el-option
v-for="item in optionsList.distributor"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item
label="渠道名称"
prop="name"
>
<el-input
v-model="formData.name"
></el-input>
</el-form-item>
<el-form-item
label="用途"
prop="use_type"
>
<el-select
v-model="formData.use_type"
filterable
remote
style='width:100%;'
reserve-keyword
clearable
@change="use_type_change"
placeholder="请选择"
>
<el-option
v-for="(item, index) in optionsList.use_type"
:key="'use_type_' + index"
:label="item.label"
:value="item.value"
> </el-option>
</el-select>
</el-form-item>
</el-form>
</div>
<span
slot="footer"
class="dialog-footer"
style="padding-top: 0;padding-bottom:0;"
>
<el-button @click="close()">取 消</el-button>
<el-button
type="primary"
:loading='btnLoading'
@click="submit"
>确 定</el-button>
</span>
</el-dialog>
</template>
<script>
import { searchcondition, getGameInfo ,addChannel} from '@/api/game'
import { mapState, mapMutations } from "vuex";
import { getZqCserGroup,getZqCserWxBelong } from '@/api/works'
import mainGameSelect from './mainGame.vue'
export default {
components: {
mainGameSelect
},
data() {
return {
optionsList: {
gs_user: [],
advertiser: [],
belongList:[],
groupList:[],
use_type:[
{
"value": 3,
"label": "召回",
},
{
"value": 2,
"label": "转游",
},
// {
// "value": 1,
// "label": "转端",
// }
],
},
loginButton: false,
btnLoading:false,
formData: {
use_user_id: '',
use_user_name: '',
type: 2,
group_id: '',
group_name: '',
game_id: '',
game_name:'',
login_type: '',
distributor_id: '',
login_type: '',
use_type:3,
name: ''
},
rules: {
use_user_id: [{ required: true, message: '请选择', trigger: 'blur' }],
group_id: [{ required: true, message: '请选择', trigger: 'blur' }],
game_id: [{ required: true, message: '请选择', trigger: 'blur' }],
use_type: [{ required: true, message: '请输入', trigger: 'blur' }],
name: [{ required: true, message: '请输入', trigger: 'blur' }],
channel_name: [{ required: true, message: '请输入', trigger: 'blur' }],
login_type: [{ required: true, message: '请选择', trigger: 'blur' }],
pos_type: [{ required: true, message: '请选择', trigger: 'blur' }],
distributor_id: [{ required: true, message: '请选择', trigger: 'blur' }]
},
}
},
computed: {
...mapState("user", ["userInfo"]),
},
props: ['show', 'gameUserInfo','type'],
mounted() {
this.formData.use_user_id = this.userInfo.id
this.formData.use_user_name = this.userInfo.username
this.changeGame(this.gameUserInfo.reg_game_id.toString(),this.gameUserInfo.reg_game_name)
this.formData.use_type = Number(this.type)
this.getZqCserGroup()
this.getZqCserWxBelong()
},
beforeDestroy() {
this.close()
},
destroyed(){
this.close()
},
methods: {
async getZqCserGroup() {
const res = await getZqCserGroup({ zq_user_id: Number(this.userInfo.id) })
if (res.status_code == 1 && res.data.data.length > 0) {
this.optionsList.groupList = res.data.data
this.formData.group_id = res.data.data[0].value
this.formData.group_name = res.data.data[0].label
} else {
this.$message.error('获取分组失败,请到掌权添加分组')
}
},
async getZqCserWxBelong() {
const data = {
zq_user_id: Number(this.userInfo.id)
}
const res = await getZqCserWxBelong(data)
if (res.status_code === 1 && res.data.data) {
this.optionsList.belongList = res.data.data.map(item=>{
return {
value:item.value,
label:item.label && item.label.split('-')[0]?item.label.split('-')[0]:''
}
})
this.formData.name = this.returnName()
}
},
async getGameInfo(game_id) {
this.loginButton = false
this.formData.login_type = []
const res = await getGameInfo({ game_id: game_id })
if (res.status_code === 1) {
this.loginButton = res.data.data.login_button
}
},
onDistributorChange() {
this.optionsList.advertiser = []
this.formData.name = this.returnName()
},
returnName(){
const group_name_list = this.formData.group_name.split('-')
let name = ''
if(this.optionsList.belongList[0]){
name+= this.optionsList.belongList[0].label+'-'+ group_name_list[group_name_list.length-1]+'-'+this.formData.use_user_name
}
if(this.formData.game_name){
const use_type_name = this.optionsList.use_type.find(item=>item.value == this.formData.use_type).label
name+='-'+this.formData.game_name+'-'+use_type_name
}
return name
},
async distributorSearchAsync(value) {
const data = {
type:'channel_distributor',
name:'',
game_id:value,
}
const res = await searchcondition(data)
this.$set(this.optionsList,'distributor',res.data.data)
},
async changeGame(value, label) {
this.formData.distributor_id = ''
if (value) {
this.formData.game_id = value
this.formData.game_name = label
this.getGameInfo(value)
this.distributorSearchAsync(value)
this.formData.name = this.returnName()
}
},
groupChange(value){
const item = this.optionsList.groupList.find(item=>item.value == value)
this.formData.group_name = item.label
this.formData.name = this.returnName()
},
use_type_change(){
this.formData.name = this.returnName()
},
close() {
this.$emit('close', false)
},
submit() {
this.$refs.formData.validate((valid) => {
if (valid) {
this.btnLoading = true
this.addChannel()
} else {
console.log('error submit!!');
return false;
}
});
},
//新建渠道
async addChannel(){
setTimeout(() => {
this.btnLoading = false
}, 3000);
const res = await addChannel(this.formData)
this.btnLoading = false
if(res.status_code === 1){
this.$message.success(res.msg)
this.close()
}
},
}
}
</script>
<style>
</style>
\ No newline at end of file
<template>
<el-cascader
v-model="reg_game_id"
:options="regGameList"
:props="{expandTrigger: 'hover',label:'full_label',emitPath:false }"
collapse-tags
clearable
multiple
filterable
:show-all-levels="true"
:style="{'width':width || ''}"
@change="returnGameId"
>
<template slot-scope="{ data }">
<span>{{ data.label }}</span>
</template>
</el-cascader>
</template>
<script>
import { selectSearch } from '@/api/game'
export default {
props: ['defaultValue', 'width', 'label'],
data() {
return {
loading: false,
reg_game_id: '',
regGameList: []
}
},
watch: {
defaultValue(newVal) {
if (newVal) {
this.reg_game_id = this.defaultValue
} else {
}
}
},
mounted() {
this.reg_game_id = this.defaultValue
this.requestRegGameList()
},
methods: {
requestRegGameList() {
const data = {
type: 'gameListWithType',
value: '',
weixin_blong_id: ''
}
selectSearch(data).then(res => {
this.loading = false
if (res.status_code == 1) {
this.regGameList = res.data.data
}
})
},
returnGameId() {
let label = ''
let list = []
this.regGameList.map(item => {
list = list.concat(item.children)
})
list.map(items => {
if (items.value === this.reg_game_id) {
label = items.label
}
})
this.$emit('result', this.reg_game_id, label)
}
}
}
</script>
<style lang="scss" scoped>
</style>
\ No newline at end of file
<template>
<div class="vipToolsContent">
<div class="gameList">
<!-- VIP 自助工具 -->
<div class="gameListItem rowFlex columnCenter spaceBetween">
<p class="rowFlex columnCenter">
<img src="@/assets/icon/vipIcon.svg" alt="vipIcon" style="width: 16px;height: 16px;margin-right: 5px;">
VIP自助工具</p>
<el-button
size="mini"
:disabled="accountSelect==''"
@click="sendVipGift"
>发送</el-button>
</div>
<!-- -->
<div class="gameListItem rowFlex columnCenter spaceBetween">
<p class="rowFlex columnCenter">
<i class="el-icon-s-operation" style="font-size:16px;margin-right:5px;"></i>
自助链接(举报、申诉、礼包申请)</p>
<el-button
size="mini"
:disabled="accountSelect==''"
@click="sendReportLink"
>发送</el-button>
</div>
<div
class="rowFlex columnCenter spaceBetween gameCodeTitle"
@click="showGameCode = !showGameCode"
>
<p class="rowFlex columnCenter spaceBetween">
<img src="@/assets/icon/gift.svg" alt="gift" style="width: 16px;height: 16px;margin-right: 5px;margin-top: -2px;">
<span class="giftCode">礼包码</span>
</p>
<i :class="showGameCode?'el-icon-arrow-right':'el-icon-arrow-down'"></i>
</div>
<el-collapse-transition>
<el-collapse
v-show="showGameCode"
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-for="(items,indexs) in item.children"
:key="indexs"
class="gameListItem rowFlex columnCenter spaceBetween gameListItemAc"
>
<p class="rowFlex columnCenter spaceBetween">
<el-popover
placement="top"
width="300"
trigger="hover"
>
<div>{{ items.name }}</div>
<div slot="reference" class="gameName">{{ items.name }}</div>
</el-popover>
<el-popover
placement="top"
trigger="hover"
>
<div
class="contentPopover"
v-html="items.content"
>
</div>
<el-button
slot="reference"
type="text"
size="medium"
>礼包内容</el-button>
</el-popover>
</p>
<el-button
size="mini"
@click="sendGameCode(items)"
>发送礼包码</el-button>
</div>
</div>
<div
v-else
class="rowFlex allCenter"
>
暂无游戏
</div>
</el-collapse-item>
</el-collapse>
</el-collapse-transition>
</div>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
import { passwardEncryption,createVipUrl } from '@/api/game'
import { giftCodeList, sendGiftCode, getZyouAuthLink } from '@/api/works'
export default {
data() {
return {
disabled: true,
showGameCode: false,
giftCodeGame: []
}
},
mounted() {
this.requestGiftCode()
},
computed: {
...mapState('game', ['accountSelect', 'bindGameUserList','chatUserInfo']),
...mapState('user', ['userid']),
},
props: {
},
watch: {
accountSelect(newVal, oldVal) {
if (newVal && newVal !== '' && this.bindGameUserList.length > 0) {
this.disabled = false
} else {
this.disabled = true
}
}
},
methods: {
sendVipGift() {
if (this.bindGameUserList.length > 0) {
createVipUrl({ member_id: this.accountSelect }).then(res => {
if (res.data.url && res.data.url != '') {
this.sendChatMessage(res.data.url,'text')
} else {
this.$message.warning('暂无vip链接')
}
})
} else {
this.$message.warning('请先关联游戏账号')
}
},
sendChatMessage(content,type){
let message = {}
if(type == 'text'){
message = {
msgtype: 'text',
text: {
content: content
},
success: (res) => {
console.log(res, '发送文本成功')
},
fail: (err) => {
console.log(err, '发送文本失败')
}
}
}else if(type == 'link'){
message = {
msgtype: 'news',
news: content,
success: (res) => {
console.log(res, '发送 news 成功')
},
fail: (err) => {
console.log(err, '发送 news 失败')
}
}
}else if(type == 'image'){
message = {
msgtype: 'image',
image: {
mediaid: content
},
success: (res) => {
console.log(res, '发送 image 成功')
},
fail: (err) => {
console.log(err, '发送 image 失败')
}
}
}
console.log(message,'1231')
this.$ww.sendChatMessage(message)
},
// 发送举报申诉自助链接
async sendReportLink() {
const res = await getZyouAuthLink()
if (res.status_code == 1) {
const link = {
title: '服务中心',
imgUrl: 'https://companywxcdn.zwnet.cn/company_wx/service/avatars/20250308/t3zztJ5FMMSnSXRtG3K8X5HaxsZMdk8W1741420608159.jpg',
desc: '点击此处提交申请',
link: res.data.url
}
this.sendChatMessage(link,'link')
} else {
this.$message.warning('暂无申诉自助链接')
}
},
async requestGiftCode() {
this.giftCodeGame = []
// 1 企微 2 微信
const data = {
userid: this.userid,
user_type:1
}
const res = await giftCodeList(data)
if (res.status_code == 1 && res.data.length > 0) {
// this.giftCodeGame = res.data
this.handleChildren(res.data)
this.giftCodeGame = res.data
} else {
this.giftCodeGame = {
label: '礼包码',
children: []
}
}
},
handleChildren(list) {
list.map(item => {
item.label = item.main_game_name + '/' + item.main_game_id
item.value = item.main_game_id
item.children = item.gift_package_list
})
},
// 发送渠道
async sendGameCode(items) {
const data = {
userid: this.chatUserInfo.userid,
external_userid: this.chatUserInfo.external_userid,
member_id: this.accountSelect,
gift_package_id: items.id,
user_type: 1
}
const res = await sendGiftCode(data)
if (res.status_code === 1) {
this.$message.success('发送成功')
this.sendChatMessage(res.data,'text')
} else {
this.$message.error('发送失败')
}
},
handleAccount() {
if (this.bindGameUserList.length > 0) {
const account = this.bindGameUserList.find(item => item.member_id == this.accountSelect)
if (account) {
return true
} else {
return false
}
} else {
return false
}
},
sendMessage(item, type) {
const result = this.handleAccount()
if (!result) {
this.$message.warning('请稍后再试')
return false
}
let str = ''
if (type == 2) {
str = '网页游戏链接:'
} else if (type == 3) {
str = '安卓游戏链接:'
} else if (type == 4) {
str = 'IOS游戏链接:'
} else {
}
const username = this.bindGameUserList.find(item => item.member_id == this.accountSelect).username
passwardEncryption({ member_id: this.accountSelect }).then(res => {
this.sendChatMessage(`${str}${item.url} \n账号:${username} \n密码:${res.data.encryptPassword}`, 'text')
}).catch(err => {
this.sendChatMessage(`${str}${item.url} \n账号:${username}`, 'text')
console.log(err)
})
},
showPopover() {
}
}
}
</script>
<style lang="scss" scoped>
.vipToolsContent{
.sendLink {
width: 150px;
height: 25px;
cursor: pointer;
}
.sendLink:hover {
color: #00bf8a;
}
.giftGameCollapse {
width: 100%;
height: auto;
}
.btntab {
width: 100%;
display: flex;
height: 36px;
border-bottom: 1px solid #ccc;
position: absolute;
left: 0;
top: 0;
.btn {
flex: 1;
display: flex;
cursor: pointer;
}
.btn:first-child {
border-right: 1px solid #ccc;
}
.btnActive {
background: #00bf8a;
color: #fff;
}
}
.gameList {
width: 100%;
height: 350px;
overflow: auto;
::v-deep .el-tabs__item {
width: 70px;
}
.giftCode {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
}
.gameCodeTitle {
cursor: pointer;
margin: 10px 0 10px 0;
}
.gameListItem {
width: 100%;
height: 40px;
.gameName{
max-width: 120px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: 5px;
}
p {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
}
.icon {
font-size: 14px;
cursor: pointer;
}
}
.gameListItemAc {
background: #f7f8fa;
}
::v-deep .el-collapse {
border-top: none;
border-bottom: none;
}
::v-deep .el-collapse-item {
border-radius: 4px;
}
::v-deep .el-collapse-item__header {
border-bottom: none;
background: #f7f8fa;
padding-left: 20px;
}
::v-deep .el-collapse-item__wrap {
border-bottom: none;
}
}
}
</style>
<style>
.contentPopover {
max-width: 400px;
word-wrap: break-word;
word-break: break-all;
}
.contentPopover img {
max-width: 250px;
}
</style>
\ No newline at end of file
......@@ -24,6 +24,7 @@
<searchSelectUser
v-if="searchType === 'remark'"
class="search-input"
:corp_id="corp_id"
:userid="userid"
width="100%"
placeholder="请输入"
......@@ -175,7 +176,7 @@ export default {
},
computed: {
...mapState('game', ['chatUserInfo']),
...mapState('user', ['userid']),
...mapState('user', ['userid','corp_id']),
},
data() {
return {
......@@ -246,8 +247,8 @@ export default {
// 用户选择结果处理
onUserSelect(external_userid, userid) {
this.searchParams = {
external_userid,
userid
external_userid:external_userid || '',
userid:this.userid
}
this.resetAndReload()
},
......
......@@ -51,6 +51,7 @@
import skillCompany from './components/skill/skillCompany.vue'
import skillPersonal from './components/skill/skillPersonal.vue'
import skillLibrary from './components/skill/skillLibrary.vue'
import { mapActions } from 'vuex'
export default {
components: {
skillCompany,
......@@ -64,12 +65,21 @@ export default {
}
},
created() {
},
mounted() {
this.initializeWecom()
},
mounted() { },
methods: {
...mapActions('user', ['initWecom']),
async initializeWecom() {
try {
console.log('🚀 开始初始化企业微信 SDK')
const result = await this.initWecom()
console.log('✅ 企业微信 SDK 初始化成功', result)
} catch (error) {
console.error('❌ 企业微信 SDK 初始化失败:', error)
}
},
}
}
</script>
......
<template>
<div class="quickSendGame columnFlex">
<div class="content search-form">
<el-tabs v-model="activeName">
<el-tab-pane
label="自助工具"
name="tools"
>
<vipTools v-if="activeName === 'tools'"/>
</el-tab-pane>
<el-tab-pane
label="发送游戏"
name="sendGame"
>
<sendGame v-if="activeName === 'sendGame'"/>
</el-tab-pane>
</el-tabs>
</div>
</div>
</template>
<script>
import vipTools from './components/quickSendGame/vipTools.vue'
import sendGame from './components/quickSendGame/sendGame.vue'
import { mapActions } from 'vuex'
export default {
components: {
vipTools,
sendGame,
},
data() {
return {
activeName: 'tools'
}
},
created() {
},
mounted() {
this.initializeWecom()
},
methods: {
...mapActions('user', ['initWecom']),
async initializeWecom() {
try {
console.log('🚀 开始初始化企业微信 SDK')
const result = await this.initWecom()
console.log('✅ 企业微信 SDK 初始化成功', result)
} catch (error) {
console.error('❌ 企业微信 SDK 初始化失败:', error)
}
},
}
}
</script>
<style lang="scss" scoped>
.quickSendGame {
::v-deep .el-tabs__nav-next,::v-deep .el-tabs__nav-prev{
line-height: 50px;
}
width: 100%;
height: 100%;
background: #fff;
::v-deep .el-tabs__item {
padding: 0 15px;
}
.detailsTitle {
width: 100%;
padding: 0 vw(20);
height: 60px;
font-size: 18px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
border-bottom: 1px solid #ebeef5;
border-left: 1px solid #ebeef5;
p {
color: #333333;
}
}
.content {
width: 100%;
height: calc(100% - 10px);
::v-deep .el-tabs__header {
margin: 0 0 20px;
}
}
::v-deep .el-collapse-item {
margin-bottom: 20px;
}
::v-deep .el-collapse-item__content {
padding-bottom: 10px;
}
::v-deep .el-collapse {
border: none;
}
::v-deep .el-tabs--border-card .is-active {
border: none !important;
}
::v-deep .el-collapse-item__header {
width: 100%;
height: 44px;
background: #f9faff;
color: #333333;
padding-left: 35px;
font-size: 14px;
font-weight: 400;
// cursor: move;
}
::v-deep .is-active {
border: none;
}
.inputContent {
width: 100%;
::v-deep .el-input {
width: 80%;
}
}
::v-deep .el-tabs,
.el-tabs__content,
.el-tab-pane {
width: 100%;
height: 100%;
}
::v-deep .el-tabs__content {
width: 100%;
height: calc(100% - 50px);
}
::v-deep .el-tab-pane {
width: 100%;
height: 100%;
}
.scrollList {
width: 100%;
height: calc(100% - 40px);
overflow: auto;
}
.draggable {
position: relative;
transition: all 0.3s;
.icon {
position: absolute;
left: 10px;
top: 15px;
z-index: 10;
}
}
::v-deep .el-icon-circle-close {
color: #fff;
}
.bate {
width: 42px;
height: 20px;
background: linear-gradient(135deg, #6ee7e9 0%, #9ff2cd 47%, #e3fdb2 100%);
border-radius: 10px;
padding: 0px 10px 3px 10px;
}
}
</style>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论