提交 69eb5f5c 作者: 施汉文

Merge branch '7.9.3' into release

--- ---
alwaysApply: true alwaysApply: true
scene: git_message
--- ---
必须简洁明了,一眼能看出完成或修改或优化的内容,不要写详细描述,不要超过50个字符。
必须简洁明了,一眼能看出完成或修改或优化的内容,不要写详细描述,不要超过两行。
...@@ -211,13 +211,13 @@ export default { ...@@ -211,13 +211,13 @@ export default {
// 页面刷新时从 Cookie 恢复 token 到 store // 页面刷新时从 Cookie 恢复 token 到 store
// Cookies.set( // Cookies.set(
// "token", // "token",
// "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOjQwOTAsImRhdGEiOnsiY3Nlcl9pZCI6NDA5MCwiY3Nlcl9uYW1lIjoi5q-b57uG5LqaIn0sImlhdCI6MTc2ODU0Mjk0MiwiZXhwIjoxNzcxMTM0OTQyLCJuYmYiOjE3Njg1NDI5NDIsInN1YiI6InRva2Vu6K6k6K-BIiwianRpIjoiMjU0Zjg3OGQ3NzMyNWUyMzMyNDAwZTEwZWJkMjFkY2YifQ.3hHc6iQP-Xkz9Q5rMIOFENDdh5P-NSaRs4Y4ffbJcMg" // ""
// ); // );
// Cookies.set("corp_id", "wweaefe716636df3d1"); // Cookies.set("corp_id", "wweaefe716636df3d1");
// Cookies.set("userid", "maoxiya"); // Cookies.set("userid", "ShanYi");
// Cookies.set("cser_name", "毛细亚"); // Cookies.set("cser_name", "张妍妍");
// Cookies.set("external_userid", "wm5rUgMgAAG_vfF4AHClsrS1S6MImVsQ"); // Cookies.set("external_userid", "wm5rUgMgAAj_YnkyHU1lVfYDT7QACqWg");
// Cookies.set("cser_id", 4090); // Cookies.set("cser_id", 12386);
// Cookies.set("weixin_blongs_id", 2862); // Cookies.set("weixin_blongs_id", 2862);
const cookieToken = Cookies.get("token"); const cookieToken = Cookies.get("token");
if (cookieToken && !this.token) { if (cookieToken && !this.token) {
......
...@@ -689,7 +689,20 @@ export function reportAdd(data) { ...@@ -689,7 +689,20 @@ export function reportAdd(data) {
}); });
}); });
} }
// 获取当前合服生态运营人员
export function currUserList(data) {
return new Promise((resolve, reject) => {
cross_systemRequest({
system: 'zhangyou',
api: '/api/server/currUserList',
params: data
}).then((res) => {
resolve(res)
}).catch((error) => {
reject(error)
})
})
}
// 申诉列表 // 申诉列表
export function appealList(data) { export function appealList(data) {
data.zw_user_id = getZwUserId(); data.zw_user_id = getZwUserId();
......
import Vue from 'vue'
import AsyncDialog from './index.vue'
let instance = null
let mountNode = null
function createInstance() {
if (instance && !instance._isDestroyed) {
return instance
}
const ComponentConstructor = Vue.extend(AsyncDialog)
mountNode = document.createElement('div')
document.body.appendChild(mountNode)
instance = new ComponentConstructor()
instance.$mount(mountNode)
return instance
}
export function getAsyncDialogInstance() {
return createInstance()
}
export function openAsyncDialog(options = {}) {
return createInstance().open(options)
}
export function closeAsyncDialog(action = 'close') {
if (!instance || instance._isDestroyed) {
return
}
instance.close(action)
}
export function destroyAsyncDialog() {
if (!instance) {
return
}
instance.$destroy()
if (instance.$el && instance.$el.parentNode) {
instance.$el.parentNode.removeChild(instance.$el)
}
if (mountNode && mountNode.parentNode) {
mountNode.parentNode.removeChild(mountNode)
}
instance = null
mountNode = null
}
export default openAsyncDialog
<template>
<el-drawer
:visible="visible"
:title="title"
:size="size"
:append-to-body="true"
@close="$emit('close')"
:show-close="false"
>
<template #title>
<div class="flex items-center">
<svg-icon
@click="$emit('close')"
svgName="icon-fanhui"
class="mr-[8px] w-[20px] text-[20px] cursor-pointer"
></svg-icon>
<span class="text-[13px] text-[#131920] leading-[13px]">{{
title
}}</span>
</div>
</template>
<slot></slot>
<span class="dialog-footer rowFlex">
<slot name="footer">
<el-button class="btn" size="small" @click="$emit('close')">
取 消
</el-button>
<el-button
class="btn"
type="primary"
size="small"
:disabled="okDisabled"
@click="$emit('ok')"
>
确 定
</el-button>
</slot>
</span>
</el-drawer>
</template>
<script>
export default {
name: "Ui-Drawer",
props: ["visible", "size", "title", "okDisabled"],
};
</script>
<style scoped>
::v-deep .el-drawer__header {
padding: 12px 0px;
margin: 0 12px;
}
.dialog-footer {
width: 100%;
position: absolute;
bottom: 0;
padding-top: 20px;
padding-bottom: 20px;
border-top: 0;
justify-content: flex-end;
background: #fff;
z-index: 10;
.btn {
width: 60px;
height: 32px;
border-radius: 6px;
}
}
</style>
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
<!-- 简单版的图文编辑器 可以上传 截图上传图片 能实现简单的图文编辑功能 --> <!-- 简单版的图文编辑器 可以上传 截图上传图片 能实现简单的图文编辑功能 -->
<div class="textEditor"> <div class="textEditor">
<div <div
v-if="showViewImage"
class="rowFlex columnCenter textEditorTitle" class="rowFlex columnCenter textEditorTitle"
@click.stop="watchImage" @click.stop="watchImage"
> >
...@@ -46,7 +47,24 @@ ...@@ -46,7 +47,24 @@
import { base64toFile } from '@/utils/index' import { base64toFile } from '@/utils/index'
export default { export default {
name: 'textEditor', name: 'textEditor',
props: ['remark', 'contenteditable', 'domid'], // remark 原来的图文内容 contenteditable 是否可编辑 domid 编辑器的 DomId resultReamrk 方法吐出最后的编辑好的内容 props: {
remark: {
type: String,
default: ''
},
contenteditable: {
type: Boolean,
default: false
},
domid: {
type: String,
default: ''
},
showViewImage: {
type: Boolean,
default: true
}
}, // remark 原来的图文内容 contenteditable 是否可编辑 domid 编辑器的 DomId resultReamrk 方法吐出最后的编辑好的内容
data() { data() {
return { return {
srcList: [], srcList: [],
...@@ -59,7 +77,9 @@ ...@@ -59,7 +77,9 @@
mounted() { mounted() {
this.$nextTick(() => { this.$nextTick(() => {
this.chatMessage = document.getElementById(`${this.domid}`) this.chatMessage = document.getElementById(`${this.domid}`)
this.remark && this.remark.length > 0 && this.contenteditable ? this.chatMessage.innerHTML = this.remark : '' if (this.remark && this.remark.length > 0 && this.contenteditable && this.chatMessage) {
this.chatMessage.innerHTML = this.remark
}
}) })
}, },
methods: { methods: {
...@@ -71,9 +91,17 @@ ...@@ -71,9 +91,17 @@
}, },
async watchImage() { async watchImage() {
if (this.remark.trim().length > 0) { if (this.remark.trim().length > 0) {
this.chatMessage.innerHTML = this.remark if (!this.chatMessage) {
this.chatMessage = document.getElementById(`${this.domid}`)
}
if (this.chatMessage) {
this.chatMessage.innerHTML = this.remark
}
this.srcList = [] this.srcList = []
const imgList = this.chatMessage.querySelectorAll('img') // 使用临时 div 来解析图片,而不依赖 DOM 元素
const tempDiv = document.createElement('div')
tempDiv.innerHTML = this.remark
const imgList = tempDiv.querySelectorAll('img')
if (imgList && imgList.length > 0) { if (imgList && imgList.length > 0) {
for (let index = 0; index < imgList.length; index++) { for (let index = 0; index < imgList.length; index++) {
this.srcList.push(imgList[index].src) this.srcList.push(imgList[index].src)
......
<template> <template>
<div class="violationRecord"> <div class="violationRecord">
<el-form v-loading="loading" class="violationRecordContent" label-width="90px"> <el-form v-loading="loading" class="violationRecordContent" label-width="90px">
<div class="flex justify-end">
<el-button type="primary" size="small" @click="reportPopupShow = true">举报</el-button>
</div>
<div v-if="violationList.length > 0"> <div v-if="violationList.length > 0">
<div v-for="(item, index) in violationList" :key="index" class="contentItem"> <div v-for="(item, index) in violationList" :key="index" class="contentItem">
<el-form-item label="违规时间:"> <el-form-item label="违规时间:">
...@@ -96,6 +99,7 @@ ...@@ -96,6 +99,7 @@
<el-dialog title="查看大图" :visible.sync="imageLayer" width="320px" center append-to-body @close="imageLayer = false"> <el-dialog title="查看大图" :visible.sync="imageLayer" width="320px" center append-to-body @close="imageLayer = false">
<div v-html="imageSrc" class="layerImage"></div> <div v-html="imageSrc" class="layerImage"></div>
</el-dialog> </el-dialog>
<reportPopup :show.sync="reportPopupShow" />
</div> </div>
</template> </template>
...@@ -105,11 +109,12 @@ import { violationList } from "@/api/game"; ...@@ -105,11 +109,12 @@ import { violationList } from "@/api/game";
import noContent from "@/components/noContent.vue"; import noContent from "@/components/noContent.vue";
import { debounce } from '@/utils' import { debounce } from '@/utils'
import watchMember from '@/mixins/watchMember' import watchMember from '@/mixins/watchMember'
import reportPopup from '@/views/popup/reportPopup/index.vue'
export default { export default {
name: 'ViolationRecord', name: 'ViolationRecord',
components: { components: {
noContent, noContent,
reportPopup,
}, },
mixins: [watchMember], mixins: [watchMember],
data() { data() {
...@@ -118,6 +123,7 @@ export default { ...@@ -118,6 +123,7 @@ export default {
violationList: [], violationList: [],
loading: false, loading: false,
imageLayer: false, imageLayer: false,
reportPopupShow: false,
}; };
}, },
computed: { computed: {
...@@ -202,7 +208,7 @@ export default { ...@@ -202,7 +208,7 @@ export default {
.violationRecordContent { .violationRecordContent {
width: 100%; width: 100%;
padding: 20px; // padding: 0 20px;
height: auto; height: auto;
} }
......
...@@ -463,6 +463,7 @@ import { ...@@ -463,6 +463,7 @@ import {
getLandingPageConfig, getLandingPageConfig,
getMemberTransStatus, getMemberTransStatus,
memberRegGameCloneLink, memberRegGameCloneLink,
getMemberLabel,
} from '@/api/game'; } from '@/api/game';
import { import {
getRecentSendLog, getRecentSendLog,
...@@ -483,6 +484,7 @@ import sendSelectChannel from './sendGame/sendSelectChannel.vue'; ...@@ -483,6 +484,7 @@ import sendSelectChannel from './sendGame/sendSelectChannel.vue';
import gameLogMixin from '@/mixins/gameLogMixin'; import gameLogMixin from '@/mixins/gameLogMixin';
import { sendChatMessage } from '@/utils/index'; import { sendChatMessage } from '@/utils/index';
import QrcodeVue from 'qrcode.vue'; import QrcodeVue from 'qrcode.vue';
import { openAsyncDialog } from '@/components/AsyncDialog';
export default { export default {
name: 'sendGame', name: 'sendGame',
mixins: [gameLogMixin], mixins: [gameLogMixin],
...@@ -532,6 +534,11 @@ export default { ...@@ -532,6 +534,11 @@ export default {
h5CloneGameInfo: {}, h5CloneGameInfo: {},
qrCodeValue: '', // 二维码内容 qrCodeValue: '', // 二维码内容
qrCodeSize: 200, // 二维码大小 qrCodeSize: 200, // 二维码大小
transRiskMemberId: '',
transRiskInfo: {
isHighRisk: false,
isPhishing: false,
},
}; };
}, },
mounted() { mounted() {
...@@ -553,6 +560,11 @@ export default { ...@@ -553,6 +560,11 @@ export default {
accountSelect(newVal, oldVal) { accountSelect(newVal, oldVal) {
// 切换 w 账号的时候清空 conversionGameList 数据 // 切换 w 账号的时候清空 conversionGameList 数据
this.conversionGameList = []; this.conversionGameList = [];
this.transRiskMemberId = '';
this.transRiskInfo = {
isHighRisk: false,
isPhishing: false,
};
this.getMemberTransStatus(); this.getMemberTransStatus();
if (newVal && newVal !== '' && this.bindGameUserList.length > 0) { if (newVal && newVal !== '' && this.bindGameUserList.length > 0) {
this.disabled = false; this.disabled = false;
...@@ -1050,11 +1062,102 @@ export default { ...@@ -1050,11 +1062,102 @@ export default {
return false; return false;
} }
}, },
sendLink: throttle(function (item, type) { isTruthyFlag(value) {
return value === true || value === 1 || value === '1';
},
async getTransRiskInfo() {
const localRiskInfo = {
isHighRisk:
Boolean(this.gameUserInfo && this.gameUserInfo.exp_ip) ||
this.isTruthyFlag(this.gameUserInfo && this.gameUserInfo.change_risk),
isPhishing:
this.isTruthyFlag(
this.chatUserInfo && this.chatUserInfo.is_phishing_account,
) ||
this.isTruthyFlag(
this.chatUserInfo && this.chatUserInfo.change_appraisal,
) ||
this.isTruthyFlag(
this.gameUserInfo && this.gameUserInfo.change_appraisal,
),
};
if (!this.accountSelect) {
return localRiskInfo;
}
if (this.transRiskMemberId === this.accountSelect) {
return {
isHighRisk:
localRiskInfo.isHighRisk || this.transRiskInfo.isHighRisk,
isPhishing:
localRiskInfo.isPhishing || this.transRiskInfo.isPhishing,
};
}
try {
const res = await getMemberLabel({
member_id: this.accountSelect,
label_type: [4, 6],
});
const memberLabelList = res?.data?.data || [];
const riskLabel = memberLabelList.find(
(item) => item.label_type == 4,
);
const phishingLabel = memberLabelList.find(
(item) => item.label_type == 6,
);
this.transRiskMemberId = this.accountSelect;
this.transRiskInfo = {
isHighRisk: this.isTruthyFlag(riskLabel && riskLabel.label_value),
isPhishing: this.isTruthyFlag(
phishingLabel && phishingLabel.label_value,
),
};
} catch (error) {
console.log(error);
this.transRiskMemberId = this.accountSelect;
this.transRiskInfo = {
isHighRisk: false,
isPhishing: false,
};
}
return {
isHighRisk: localRiskInfo.isHighRisk || this.transRiskInfo.isHighRisk,
isPhishing: localRiskInfo.isPhishing || this.transRiskInfo.isPhishing,
};
},
async confirmTransRiskBeforeSend() {
const riskInfo = await this.getTransRiskInfo();
if (!riskInfo.isHighRisk && !riskInfo.isPhishing) {
return true;
}
try {
await openAsyncDialog({
title: '确认发送',
message:
'当前用户为钓鱼号/高风险用户,请与组长确认是否发送转端链接',
countdown: 3,
confirmText: '确 定',
cancelText: '取 消',
});
return true;
} catch (error) {
return false;
}
},
sendLink: throttle(async function (item, type) {
if (!this.transMemberStatus) { if (!this.transMemberStatus) {
this.$message.warning('当前w账号不满足转端要求,请联系组长处理'); this.$message.warning('当前w账号不满足转端要求,请联系组长处理');
return; return;
} }
if (!(await this.confirmTransRiskBeforeSend())) {
return;
}
console.log(item, '转端发送仅发送链接'); console.log(item, '转端发送仅发送链接');
const result = this.handleAccount(); const result = this.handleAccount();
if (!result) { if (!result) {
...@@ -1078,11 +1181,14 @@ export default { ...@@ -1078,11 +1181,14 @@ export default {
item.type = 1; item.type = 1;
this.sendGameLog(item); this.sendGameLog(item);
}, 500), }, 500),
sendPassword: throttle(function (item, type) { sendPassword: throttle(async function (item, type) {
if (!this.transMemberStatus) { if (!this.transMemberStatus) {
this.$message.warning('当前w账号不满足转端要求,请联系组长处理'); this.$message.warning('当前w账号不满足转端要求,请联系组长处理');
return; return;
} }
if (!(await this.confirmTransRiskBeforeSend())) {
return;
}
console.log(item, '转端仅发送账号密码'); console.log(item, '转端仅发送账号密码');
const result = this.handleAccount(); const result = this.handleAccount();
if (!result) { if (!result) {
...@@ -1111,11 +1217,14 @@ export default { ...@@ -1111,11 +1217,14 @@ export default {
console.log(err); console.log(err);
}); });
}, 500), }, 500),
sendMessage: throttle(function (item, type) { sendMessage: throttle(async function (item, type) {
if (!this.transMemberStatus) { if (!this.transMemberStatus) {
this.$message.warning('当前w账号不满足转端要求,请联系组长处理'); this.$message.warning('当前w账号不满足转端要求,请联系组长处理');
return; return;
} }
if (!(await this.confirmTransRiskBeforeSend())) {
return;
}
const result = this.handleAccount(); const result = this.handleAccount();
if (!result) { if (!result) {
this.$message.warning('请稍后再试'); this.$message.warning('请稍后再试');
...@@ -1171,11 +1280,14 @@ export default { ...@@ -1171,11 +1280,14 @@ export default {
this.getMediaId(value, 'image'); this.getMediaId(value, 'image');
}, },
// 转端发送落地页面 // 转端发送落地页面
sendDownLoadPage: throttleStart(function (items, type, index) { sendDownLoadPage: throttleStart(async function (items, type, index) {
if (!this.transMemberStatus) { if (!this.transMemberStatus) {
this.$message.warning('当前w账号不满足转端要求,请联系组长处理'); this.$message.warning('当前w账号不满足转端要求,请联系组长处理');
return; return;
} }
if (!(await this.confirmTransRiskBeforeSend())) {
return;
}
this.$set( this.$set(
this.conversionGameList[index], this.conversionGameList[index],
'send_trans_page_id', 'send_trans_page_id',
...@@ -1185,6 +1297,13 @@ export default { ...@@ -1185,6 +1297,13 @@ export default {
}, 500), }, 500),
// 转端发送游戏分身包 h5 安卓游戏 IOS游戏 发送分身包 // 转端发送游戏分身包 h5 安卓游戏 IOS游戏 发送分身包
async sendTransferCloneGame(type, items) { async sendTransferCloneGame(type, items) {
if (!this.transMemberStatus) {
this.$message.warning('当前w账号不满足转端要求,请联系组长处理');
return;
}
if (!(await this.confirmTransRiskBeforeSend())) {
return;
}
if (!this.h5CloneGameInfo?.data?.h5_download_url) { if (!this.h5CloneGameInfo?.data?.h5_download_url) {
this.h5CloneGameInfo = this.h5CloneGameInfo =
(await memberRegGameCloneLink({ (await memberRegGameCloneLink({
...@@ -1240,6 +1359,9 @@ export default { ...@@ -1240,6 +1359,9 @@ export default {
this.$message.warning('当前w账号不满足转端要求,请联系组长处理'); this.$message.warning('当前w账号不满足转端要求,请联系组长处理');
return; return;
} }
if (!(await this.confirmTransRiskBeforeSend())) {
return;
}
const result = this.handleAccount(); const result = this.handleAccount();
if (!result) { if (!result) {
this.$message.warning('请稍后再试'); this.$message.warning('请稍后再试');
......
...@@ -68,30 +68,69 @@ export default { ...@@ -68,30 +68,69 @@ export default {
height: 100%; height: 100%;
.el-tabs__header { .el-tabs__header {
margin: 0; // margin: 0px 15px 10px 15px !important;
padding: 0 15px; padding: 2px !important;
background: #F5F6F7 !important;
border-radius: 4px !important;
box-sizing: border-box !important;
height: auto !important;
overflow: visible !important;
border: none !important;
}
.el-tabs__nav-wrap {
overflow: visible !important;
height: auto !important;
padding: 0 !important;
margin: 0 !important;
&::after {
display: none !important;
}
}
.el-tabs__nav {
width: 100% !important;
display: flex !important;
border: none !important;
height: auto !important;
margin: 0 !important;
padding: 0 !important;
gap: 2px !important;
} }
.el-tabs__item { .el-tabs__item {
height: 40px; flex: 1 !important;
line-height: 40px; height: 22px !important;
font-size: 16px; line-height: 22px !important;
color: #333333; padding: 0 !important;
margin: 0 !important;
font-family: 'PingFang SC', sans-serif !important;
font-size: 13px !important;
font-weight: 400 !important;
color: #6D7176 !important;
text-align: center !important;
border-radius: 2px !important;
border: none !important;
transition: all 0.2s !important;
white-space: nowrap !important;
overflow: visible !important;
text-overflow: unset !important;
&.is-active { &.is-active {
color: #3491fa; background: #FFFFFF !important;
color: #131920 !important;
box-shadow: 0px 2px 8px 0px rgba(0, 0, 0, 0.05) !important;
} }
}
.el-tabs__active-bar { &:first-child,
background-color: #3491fa; &:last-child {
height: 3px; margin: 0 !important;
border-radius: 1.5px; }
} }
.el-tabs__nav-wrap::after { .el-tabs__active-bar {
height: 1px; display: none !important;
background-color: #e4e7ed;
} }
.el-tab-pane { .el-tab-pane {
...@@ -100,8 +139,8 @@ export default { ...@@ -100,8 +139,8 @@ export default {
} }
.el-tabs__content { .el-tabs__content {
height: calc(100% - 40px); height: calc(100% - 46px);
padding: 0 5px 5px; padding: 0;
} }
} }
} }
......
...@@ -96,7 +96,7 @@ export default { ...@@ -96,7 +96,7 @@ export default {
::v-deep .el-tabs__header { ::v-deep .el-tabs__header {
margin-bottom: 15px; margin-bottom: 15px;
padding: 0 10px; padding: 0;
} }
::v-deep .el-tabs__nav-wrap::after { ::v-deep .el-tabs__nav-wrap::after {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论