提交 7c63f26a 作者: 毛细亚

保存代码

上级 199d2c9a
import request from "@/utils/request";
// 游戏业务所属的接口信息
// 所属分组下拉
export function cross_systemRequest(data) {
data.api = "/api" + data.api;
data.params
? (data.params.corp_id = window.localStorage.getItem("corp_id") || "")
: "";
return request({
url: "/admin/cross_system/request",
method: "post",
data,
});
}
// 搜索下拉
export function searchcondition(data) {
return new Promise((resovle, reject) => {
cross_systemRequest({
system: "pigeon",
api: "/api/searchcondition/index",
params: data,
}).then((res) => {
resovle(res);
});
});
}
\ No newline at end of file
<template>
<div class="search-item">
<div class="item-label">{{ label }}</div>
<div class="item-content">
<el-select v-model.trim="main_game_id" filterable remote clearable :style="{ 'width': width || '' }"
reserve-keyword placeholder="请输入主游戏名" :remote-method="remoteMethod" :loading="loading" :disabled='disabled'
@change="returnSelectResult" @focus="gameNameList = optionsList">
<el-option v-for="item in gameNameList" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
</div>
</div>
</template>
<script>
import { selectSearch } from '@/api/game'
import { searchcondition } from '@/api/pigeon'
export default {
// gameType:存在的时候取信鸽的游戏列表接口 gameDefaultList 编辑的时候 如果没有当前的游戏 id 主动加上去
props: ['defaultValue', 'width', 'label', 'disabled','gameType','gameDefaultList','isResize'],
data() {
return {
loading: false,
main_game_id: '',
gameNameList: [],
optionsList: []
}
},
watch: {
defaultValue(newVal) {
if (newVal) {
this.gameType?this.main_game_id = newVal:this.main_game_id = Number(newVal)
} else {
return ''
}
},
isResize(newVal, oldVal) {
if (newVal) {
this.main_game_id = ''
this.$emit('result', this.main_game_id, '')
}
},
},
mounted() {
this.defaultValue && this.gameType ? this.main_game_id = Number(this.defaultValue) : this.main_game_id = this.defaultValue
this.switchGameList()
},
methods: {
switchGameList() {
if(this.gameType){
this.requestPigeonGameList()
}else{
this.requestGameList()
}
},
requestGameList() {
const data = {
type: 'mainGameList',
value: '',
weixin_blong_id: ''
}
selectSearch(data).then(res => {
this.loading = false
if (res.status_code == 1) {
this.gameNameList = this.optionsList = res.data.data
}
})
},
requestPigeonGameList() {
const data = {
corp_gift_package_main_games:1,
}
searchcondition(data).then(res => {
this.loading = false
if (res.status_code == 1 && res.data.corp_gift_package_main_games?.length > 0) {
this.gameNameList = this.optionsList = res.data.corp_gift_package_main_games
if(this.gameDefaultList.length > 0){
const gameItem = this.gameNameList.find(item=>item.value === this.gameDefaultList[0].value)
if(!gameItem){
this.gameNameList = this.optionsList = this.gameNameList.concat(this.gameDefaultList)
}
}
}
})
},
remoteMethod(query) {
if (query !== '') {
this.gameNameList = this.optionsList.filter(item => {
return item.label.toLowerCase()
.indexOf(query.toLowerCase()) > -1
})
} else {
this.gameNameList = []
}
},
returnSelectResult(value) {
const label = this.gameNameList.find(item => item.value == this.main_game_id)
label ? this.$emit('result', this.main_game_id, label.label) : this.$emit('result', this.main_game_id, '')
}
}
}
</script>
<style lang="scss" scoped>
.newPage {
width: 100%;
height: 100%;
.el-select {
width: 100%;
}
}
</style>
\ No newline at end of file
<template>
<div class="no-content-container">
<div class="no-content-box">
<!-- 自定义 SVG 图标 -->
<div class="icon-wrapper">
<svg class="no-data-icon" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
<!-- 文件夹图标 -->
<path
d="M40 60h35l10-15h75c8.28 0 15 6.72 15 15v90c0 8.28-6.72 15-15 15H40c-8.28 0-15-6.72-15-15V75c0-8.28 6.72-15 15-15z"
fill="url(#gradient1)"
stroke="url(#gradient2)"
stroke-width="2"
/>
<!-- 虚线效果 -->
<circle cx="100" cy="120" r="25" fill="none" stroke="currentColor" stroke-width="2" stroke-dasharray="4 4" opacity="0.3"/>
<circle cx="100" cy="120" r="35" fill="none" stroke="currentColor" stroke-width="1.5" stroke-dasharray="6 6" opacity="0.2"/>
<!-- 渐变定义 -->
<defs>
<linearGradient id="gradient1" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#f8f9fa;stop-opacity:1" />
<stop offset="100%" style="stop-color:#e9ecef;stop-opacity:1" />
</linearGradient>
<linearGradient id="gradient2" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#dee2e6;stop-opacity:1" />
<stop offset="100%" style="stop-color:#ced4da;stop-opacity:1" />
</linearGradient>
</defs>
</svg>
<!-- 装饰圆点 -->
<div class="decorative-dots">
<span class="dot dot-1"></span>
<span class="dot dot-2"></span>
<span class="dot dot-3"></span>
</div>
</div>
<!-- 文字内容 -->
<div class="content">
<h3 class="title">{{ title }}</h3>
<p class="description">{{ description }}</p>
<div class="action-area" v-if="showAction">
<slot name="action">
<el-button type="primary" @click="handleRefresh" v-if="showRefresh">
<i class="el-icon-refresh"></i>
刷新数据
</el-button>
</slot>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'NoContent',
props: {
// 主标题
title: {
type: String,
default: '暂无数据'
},
// 描述文字
description: {
type: String,
default: '当前没有任何数据,请稍后再试或联系管理员'
},
// 是否显示操作区域
showAction: {
type: Boolean,
default: false
},
// 是否显示刷新按钮
showRefresh: {
type: Boolean,
default: false
},
// 图标颜色主题
iconTheme: {
type: String,
default: 'default', // default, primary, success, warning, danger
validator: (value) => ['default', 'primary', 'success', 'warning', 'danger'].includes(value)
}
},
methods: {
handleRefresh() {
this.$emit('refresh');
}
}
}
</script>
<style lang="scss" scoped>
.no-content-container {
display: flex;
align-items: center;
justify-content: center;
min-height: 300px;
padding: 40px 20px;
background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
border-radius: 12px;
position: relative;
overflow: hidden;
// 背景装饰
&::before {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: radial-gradient(circle, rgba(0, 191, 138, 0.05) 0%, transparent 50%);
pointer-events: none;
}
}
.no-content-box {
text-align: center;
max-width: 400px;
position: relative;
z-index: 1;
}
.icon-wrapper {
position: relative;
margin-bottom: 32px;
display: inline-block;
}
.no-data-icon {
width: 120px;
height: 120px;
color: #6c757d;
filter: drop-shadow(0 8px 16px rgba(0, 0, 0, 0.1));
animation: float 3s ease-in-out infinite;
}
// 图标主题色
.no-content-container[data-theme="primary"] .no-data-icon {
color: #00BF8A;
}
.no-content-container[data-theme="success"] .no-data-icon {
color: #67c23a;
}
.no-content-container[data-theme="warning"] .no-data-icon {
color: #e6a23c;
}
.no-content-container[data-theme="danger"] .no-data-icon {
color: #f56c6c;
}
// 装饰圆点
.decorative-dots {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
pointer-events: none;
}
.dot {
position: absolute;
width: 6px;
height: 6px;
background: #00BF8A;
border-radius: 50%;
opacity: 0.6;
}
.dot-1 {
top: 20%;
left: 15%;
animation: pulse 2s ease-in-out infinite;
}
.dot-2 {
top: 30%;
right: 20%;
animation: pulse 2s ease-in-out infinite 0.5s;
}
.dot-3 {
bottom: 25%;
left: 25%;
animation: pulse 2s ease-in-out infinite 1s;
}
// 文字内容
.content {
.title {
font-size: 24px;
font-weight: 600;
color: #2c3e50;
margin: 0 0 12px 0;
line-height: 1.3;
}
.description {
font-size: 14px;
color: #6c757d;
line-height: 1.6;
margin: 0 0 24px 0;
max-width: 300px;
margin-left: auto;
margin-right: auto;
}
}
.action-area {
margin-top: 32px;
.el-button {
padding: 12px 24px;
border-radius: 6px;
font-weight: 500;
box-shadow: 0 4px 12px rgba(0, 191, 138, 0.3);
transition: all 0.3s ease;
&:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(0, 191, 138, 0.4);
}
i {
margin-right: 6px;
}
}
}
// 动画效果
@keyframes float {
0%, 100% {
transform: translateY(0px);
}
50% {
transform: translateY(-10px);
}
}
@keyframes pulse {
0%, 100% {
opacity: 0.6;
transform: scale(1);
}
50% {
opacity: 1;
transform: scale(1.2);
}
}
// 响应式设计
@media (max-width: 768px) {
.no-content-container {
min-height: 250px;
padding: 30px 15px;
}
.no-data-icon {
width: 80px;
height: 80px;
}
.content {
.title {
font-size: 20px;
}
.description {
font-size: 13px;
}
}
.action-area {
margin-top: 24px;
.el-button {
padding: 10px 20px;
font-size: 14px;
}
}
}
// 暗色主题支持
@media (prefers-color-scheme: dark) {
.no-content-container {
background: linear-gradient(135deg, #2c3e50 0%, #34495e 100%);
&::before {
background: radial-gradient(circle, rgba(0, 191, 138, 0.1) 0%, transparent 50%);
}
}
.content {
.title {
color: #ecf0f1;
}
.description {
color: #bdc3c7;
}
}
}
</style>
\ No newline at end of file
<template>
<!-- 简单版的图文编辑器 可以上传 截图上传图片 能实现简单的图文编辑功能 -->
<div class="textEditor">
<div
class="rowFlex columnCenter textEditorTitle"
@click.stop="watchImage"
>
<el-image
class="watchImage"
src="https://wanxiaomeng-1255977238.cos.ap-shanghai.myqcloud.com/mxy/web/eye.png"
> </el-image>
<p class="watchImageText">查看大图</p>
</div>
<!-- 只展示不编辑 -->
<div
v-if="!contenteditable"
:id="domid"
class="qualityRemark noActive"
>
<div v-html="remark"></div>
</div>
<!-- 可以编辑 -->
<div
v-else
:id="domid"
class="qualityRemark"
:class="contenteditable ? 'active' : 'noActive'"
:contenteditable="contenteditable"
@blur.stop="handleBlurEvent"
@input="handleInputEvent"
></div>
<!-- 查看大图 -->
<el-dialog
title="查看大图"
append-to-body
center
:visible.sync="showScoleImage"
>
<div class="showScoleImageContent columnFlex allCenter" v-html="remark"></div>
</el-dialog>
</div>
</template>
<script>
import { base64toFile } from '@/utils/index'
export default {
props: ['remark', 'contenteditable', 'domid'], // remark 原来的图文内容 contenteditable 是否可编辑 domid 编辑器的 DomId resultReamrk 方法吐出最后的编辑好的内容
data() {
return {
srcList: [],
chatMessage: {},
imgList: [],
htmlContent: '',
showScoleImage: false
}
},
mounted() {
this.$nextTick(() => {
this.chatMessage = document.getElementById(`${this.domid}`)
this.remark && this.remark.length > 0 && this.contenteditable ? this.chatMessage.innerHTML = this.remark : ''
})
},
methods: {
handleBlurEvent() {
// this.handleImage()
},
handleInputEvent() {
this.handleImage()
},
async watchImage() {
if (this.remark.trim().length > 0) {
this.chatMessage.innerHTML = this.remark
this.srcList = []
const imgList = this.chatMessage.querySelectorAll('img')
if (imgList && imgList.length > 0) {
for (let index = 0; index < imgList.length; index++) {
this.srcList.push(imgList[index].src)
}
}
this.showScoleImage = true
} else {
this.$message.warning('内容为空')
}
},
async handleImage() {
this.srcList = []
const imgListElement = this.chatMessage.querySelectorAll('img')
let imgList = []
if (imgListElement.length > 0) {
for (let i = 0; i < imgListElement.length; i++) {
const nodeItem = imgListElement[i]
if (nodeItem.src.indexOf('data:image') !== -1) {
imgList.push(nodeItem)
}
}
} else {
imgList = []
}
if (imgList && imgList.length > 0) {
for (let index = 0; index < imgList.length; index++) {
if (imgList[index].src.indexOf('http:') !== -1) {
this.srcList.push(imgList[index].src)
} else {
const img = base64toFile(imgList[index].src)
const uploadConfig = {
dir: '/company_wx/service/avatars/'
}
this.srcList.push(imgList[index].src)
const result = await this.uploading(img, uploadConfig)
imgList[index].src = result.data
}
}
this.$emit('resultReamrk', this.chatMessage.innerHTML)
this.$emit('update:remark', this.chatMessage.innerHTML)
} else {
this.$emit('resultReamrk', this.chatMessage.innerHTML)
this.$emit('update:remark', this.chatMessage.innerHTML)
}
}
}
}
</script>
<style lang="scss" scoped>
.watchImage {
width: 20px;
height: 20px;
margin-right: 5px;
cursor: pointer;
}
.textEditorTitle{
width: 100px;
}
.watchImageText{
color: #00bf8a;
cursor: pointer;
}
.noActive {
background: #f5f7fa;
color: #c0c4cc;
}
.active {
background: #fff;
color: #333;
}
.showScoleImageContent{
width: 100%;
line-height: 16px;
margin-top: 30px;
img{
max-width: 80%;
}
}
</style>
<style>
.qualityRemark {
width: 100%;
height: 150px;
border: 1px solid #dcdfe6;
border-radius: 4px;
padding: 10px;
overflow: auto;
line-height: 20px;
}
.qualityRemark img {
width: 80px !important;
height: auto !important;
margin-right: 5px;
margin-top:10px;
margin-right: 10px;
}
.showScoleImageContent{
width: 100%;
overflow: auto;
line-height: 16px;
}
.showScoleImageContent img{
max-width: 100%;
margin-bottom: 20px;
}
</style>
\ No newline at end of file
...@@ -2,22 +2,41 @@ import Vue from 'vue' ...@@ -2,22 +2,41 @@ import Vue from 'vue'
import App from './App.vue' import App from './App.vue'
import router from './router' import router from './router'
import store from './store' import store from './store'
import ElementUI from 'element-ui'; // import ElementUI from 'element-ui';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import _ from 'lodash'; import _ from 'lodash';
import 'lib-flexible/flexible.js' import 'lib-flexible/flexible.js'
Vue.use(ElementUI); // Vue.use(ElementUI);
import '@/styles/element-theme-colors.css'; import '@/styles/element-theme-colors.css';
import '@/styles/index.scss'; import '@/styles/index.scss';
Vue.config.productionTip = false import moment from 'moment'
import VConsole from 'vconsole'; import VConsole from 'vconsole';
new VConsole(); import 'bi-element-ui/lib/bi-element-ui.css'
import Element from 'bi-eleme'
import 'bi-eleme/lib/theme-chalk/index.css'
import BiElementUi from 'bi-element-ui'
import 'bi-element-ui/lib/bi-element-ui.css'
if(process.env.NODE_ENV !== 'production'){
new VConsole();
}
Vue.use(BiElementUi, {
dev: process.env.NODE_ENV !== 'production',
env: process.env.NODE_ENV,
system: null
})
Vue.use(Element, {
size: Cookies.get('size') || 'small' // set element-ui default size
// locale: enLang, // 如果使用中文,无需设置,请删除
})
new Vue({ new Vue({
router, router,
store, store,
render: h => h(App) render: h => h(App)
}).$mount('#app') }).$mount('#app')
Vue.config.productionTip = false
Vue.prototype.$cookies = Cookies; Vue.prototype.$cookies = Cookies;
Vue.prototype.$lodash = _; Vue.prototype.$lodash = _;
Vue.prototype.$moment = moment;
...@@ -6,6 +6,7 @@ const state = { ...@@ -6,6 +6,7 @@ const state = {
accountSelect: '', // 当前选中的用户的member_id accountSelect: '', // 当前选中的用户的member_id
bindGameUserList: [], // 用户绑定的游戏角色 bindGameUserList: [], // 用户绑定的游戏角色
changeSelectWindow: false, // 切换客服窗口的时候 下发通知 changeSelectWindow: false, // 切换客服窗口的时候 下发通知
gameUserInfo:{},
chatUserInfo: {}, // 当前选中的用户的详情 chatUserInfo: {}, // 当前选中的用户的详情
} }
const mutations = { const mutations = {
...@@ -17,6 +18,9 @@ const mutations = { ...@@ -17,6 +18,9 @@ const mutations = {
}, },
set_chatUserInfo(state, data) { set_chatUserInfo(state, data) {
state.chatUserInfo = data state.chatUserInfo = data
},
set_gameUserInfo(state, data) {
state.gameUserInfo = data
} }
} }
......
import Cookies from 'js-cookie'
const state = { const state = {
userInfo: { userInfo: {
"userid": "JinDuoXia", "userid": "JinDuoXia",
...@@ -8,7 +9,7 @@ const state = { ...@@ -8,7 +9,7 @@ const state = {
"time": 1747726636, "time": 1747726636,
external_userid:'' external_userid:''
}, },
userid:'JinDuoXia', userid:Cookies.get('userid'),
corp_id:'', corp_id:'',
external_userid:'', external_userid:'',
token:'', token:'',
...@@ -16,13 +17,15 @@ const state = { ...@@ -16,13 +17,15 @@ const state = {
cser_id:'', cser_id:'',
cser_name:'' cser_name:''
}, },
cser_id:'',
cser_name:'',
signData:{ signData:{
corp_id:'', corp_id:'',
agent_signature:'', agent_signature:'',
corp_signature:'', corp_signature:'',
time:'' time:''
}, },
external_userid:'wm5rUgMgAAjqjOcqp8i3lEhFZDQieWug' external_userid:Cookies.get('external_userid')
// 六子的 用户id wm5rUgMgAAjqjOcqp8i3lEhFZDQieWug // 六子的 用户id wm5rUgMgAAjqjOcqp8i3lEhFZDQieWug
// 我的 userid JinDuoXia cser_id 4090 corp_id wweaefe716636df3d1 cser_id 4090 token token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJpc3MiOjQwOTAsImlhdCI6MTc0NzgxMjMxMiwiZXhwIjoxNzQ4NDE3MTEyLCJuYmYiOjE3NDc4MTIzMTIsInN1YiI6InRva2Vu6K6k6K-BIiwianRpIjoiMjBkOTY3MDZiYzI1MDdmY2MxOWI2MjU1YTM0YWQ3M2YifQ.yX7E7QHV7x2ubpa8iK3Avy794EiHNCaW2CtB4A4UQWo // 我的 userid JinDuoXia cser_id 4090 corp_id wweaefe716636df3d1 cser_id 4090 token token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJpc3MiOjQwOTAsImlhdCI6MTc0NzgxMjMxMiwiZXhwIjoxNzQ4NDE3MTEyLCJuYmYiOjE3NDc4MTIzMTIsInN1YiI6InRva2Vu6K6k6K-BIiwianRpIjoiMjBkOTY3MDZiYzI1MDdmY2MxOWI2MjU1YTM0YWQ3M2YifQ.yX7E7QHV7x2ubpa8iK3Avy794EiHNCaW2CtB4A4UQWo
} }
...@@ -49,6 +52,12 @@ const mutations = { ...@@ -49,6 +52,12 @@ const mutations = {
set_signData(state,signData){ set_signData(state,signData){
state.signData = signData state.signData = signData
}, },
set_cser_id(state,cser_id){
state.cser_id = cser_id
},
set_cser_name(state,cser_name){
state.cser_name = cser_name
}
} }
const actions = { const actions = {
......
...@@ -102,39 +102,6 @@ ...@@ -102,39 +102,6 @@
z-index: 99999 !important; /* 最高层级,确保不被任何元素遮挡 */ z-index: 99999 !important; /* 最高层级,确保不被任何元素遮挡 */
} }
/* 其他需要高层级的组件 */
.el-notification {
z-index: 99998 !important; /* 通知组件 */
}
.el-loading-mask {
z-index: 99997 !important; /* 加载遮罩 */
}
.el-dialog__wrapper {
z-index: 99996 !important; /* 对话框 */
}
.el-drawer__wrapper {
z-index: 99995 !important; /* 抽屉 */
}
.el-popover.el-popper {
z-index: 99994 !important; /* 弹出框 */
}
.el-tooltip__popper {
z-index: 99993 !important; /* 工具提示 */
}
.el-select-dropdown {
z-index: 99992 !important; /* 下拉选择框 */
}
.el-picker-panel {
z-index: 99991 !important; /* 日期时间选择器 */
}
/* ================================ /* ================================
组件样式重写示例 - 翠绿色主题 组件样式重写示例 - 翠绿色主题
================================ */ ================================ */
......
...@@ -78,8 +78,8 @@ service.interceptors.response.use( ...@@ -78,8 +78,8 @@ service.interceptors.response.use(
}) })
if (res.status_code === -1) { if (res.status_code === -1) {
// 登录 过期 重新去登录 // 登录 过期 重新去登录
removeToken() // removeToken()
window.location.href = window.location.origin +'/company_app/index.html?corp_id='+Cookies.get('corp_id') // window.location.href = window.location.origin +'/company_app/index.html?corp_id='+Cookies.get('corp_id')
return res return res
} }
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
<script type="text/javascript"> <script type="text/javascript">
import { detailsInfoRequest } from '@/api/works' import { detailsInfoRequest } from '@/api/works'
import {memberView} from '@/api/game'
import { mapState, mapMutations, mapActions } from 'vuex' import { mapState, mapMutations, mapActions } from 'vuex'
import addUser from './addUser.vue' import addUser from './addUser.vue'
// 更新代码 // 更新代码
...@@ -41,6 +42,8 @@ export default { ...@@ -41,6 +42,8 @@ export default {
computed: { computed: {
...mapState('game', [ ...mapState('game', [
'bindGameUserList', 'bindGameUserList',
'accountSelect',
'gameUserInfo'
]), ]),
...mapState('user', [ ...mapState('user', [
'userid', 'userid',
...@@ -48,8 +51,12 @@ export default { ...@@ -48,8 +51,12 @@ export default {
]), ]),
}, },
watch: { watch: {
accountSelect(val) { accountSelect(newVal,oldVal) {
this.bindAccount = val if(newVal){
console.log(newVal,'hahhaha')
this.gameMemberView()
this.bindAccount = newVal
}
} }
}, },
async mounted() { async mounted() {
...@@ -59,7 +66,8 @@ export default { ...@@ -59,7 +66,8 @@ export default {
methods: { methods: {
...mapMutations('game', [ ...mapMutations('game', [
'set_accountSelect', 'set_accountSelect',
'set_chatUserInfo' 'set_chatUserInfo',
'set_gameUserInfo'
]), ]),
...mapActions('game', ['gameBindUser']), ...mapActions('game', ['gameBindUser']),
handleChange(value) { handleChange(value) {
...@@ -69,6 +77,21 @@ export default { ...@@ -69,6 +77,21 @@ export default {
this.set_accountSelect(value) this.set_accountSelect(value)
} }
}, },
gameMemberView(item) {
if (this.accountSelect && this.accountSelect !== '') {
const data = { member_id: this.accountSelect, need_channel: 1, need_roleInfo: 1, need_banned: 1 }
memberView(data).then((res) => {
if (res.status_code === 1) {
this.set_gameUserInfo(res.data)
} else {
this.set_gameUserInfo({})
}
}, (err) => {
this.set_gameUserInfo({})
})
}
},
addNewUser() { addNewUser() {
console.log(11) console.log(11)
}, },
......
...@@ -100,7 +100,7 @@ export default { ...@@ -100,7 +100,7 @@ export default {
...mapState('user',['corp_id']) ...mapState('user',['corp_id'])
}, },
methods: { methods: {
...mapMutations('user',['set_corp_id','set_userid','set_external_userid','set_userInfo','set_token','set_cser_info','set_signData']), ...mapMutations('user',['set_corp_id','set_userid','set_external_userid','set_userInfo','set_token','set_cser_info','set_signData','set_cser_id','set_cser_name']),
// 设置缓存 // 设置缓存
cacheCorp_id(corp_id){ cacheCorp_id(corp_id){
Cookies.set('corp_id',corp_id, { expires: 7 }) Cookies.set('corp_id',corp_id, { expires: 7 })
...@@ -121,6 +121,8 @@ export default { ...@@ -121,6 +121,8 @@ export default {
cser_id:cser_id, cser_id:cser_id,
cser_name:cser_name cser_name:cser_name
}) })
this.set_cser_id(cser_id)
this.set_cser_name(cser_name)
}, },
cacheExternal_userid(external_userid){ cacheExternal_userid(external_userid){
Cookies.set('external_userid',external_userid, { expires: 7 }) Cookies.set('external_userid',external_userid, { expires: 7 })
......
<template> <template>
<div class="info-tab-content"> <div class="info-tab-content">
资料 <div
class="userDetailsPanel columnFlex"
>
<div class="content">
<div
v-if="change_appraisal"
style="
font-size: 28px;
color: red;
text-align: center;
margin-bottom: 20px;
line-height: 40px;
"
>
钓鱼号 禁止转端通知组长!
</div>
<div
v-else-if="gameUserInfo.exp_ip"
style="
font-size: 28px;
color: red;
text-align: center;
margin-bottom: 20px;
line-height: 40px;
"
>
高风险用户,禁止转端 !!!
</div>
<div class="item rowFlex">
<!-- 公共的信息 -->
<el-image
fit="fill"
draggable="false"
style="-webkit-user-drag: none"
:src="chatUserDetails.avatar"
class="tableImage"
></el-image>
<div class="columnFlex">
<div
class="rowFlex"
style="margin-bottom: 3px"
>
<p
class="text"
style="font-weight: 600"
>
{{ chatUserDetails.name }}
</p>
<span v-if="chatUserDetails.add_way_text" style="color: #09b159; margin-left: 10px">@{{ chatUserDetails.add_way_text }}</span>
</div>
<!-- 游戏模块特有 -->
<div
v-if="accountSelect && accountSelect !== ''"
style="margin-top: 3px"
>
<el-button-group>
<el-button size="mini" @click="zyouUnBindConfirm">解绑</el-button>
<el-button size="mini" @click="autoResetPassword">修改密码</el-button>
<el-button size="mini" @click="changePhoneClick">修改手机号</el-button>
<el-button v-if="!chatUserDetails.bind_cser" size="mini" @click="relationKfh">关联客服</el-button>
<el-button size="mini" v-if="false" @click="errorHandle">误操作</el-button>
</el-button-group>
</div>
</div>
</div>
<div class="item rowFlex columnCenter">
<div class="rowFlex columnCenter">
<span class="label" style="min-width: 45px;">备注:</span>
<p
v-if="!showInputRemark"
class="text"
style="max-width: 170px;"
>
{{
chatUserDetails.remark && chatUserDetails.remark != ""
? chatUserDetails.remark
: chatUserDetails.name
}}
</p>
</div>
<el-input
v-if="showInputRemark"
v-model="showInputRemarkValue"
class="showInputRemarkInput"
type="textarea"
@change="handleInputRemark"
@blur="showInputRemark = false"
></el-input>
<i class="el-icon-edit icon" style="font-size: 14px"
@click="editRemark"></i>
</div>
<div>
<!-- 自定义列 -->
<div v-if="false">
<div
v-for="(item, index) in chatUserDetails.self_defined_columns"
:key="index"
class="item rowFlex columnCenter"
>
<div class="rowFlex columnCenter">
<span class="label">{{ item.name }}</span>
<p
v-if="!showInput || inputIndex != index"
class="text"
>
{{ item.value }}
</p>
</div>
<el-input
v-if="showInput && inputIndex == index"
v-model="showInputValue"
style="width: 120px; margin-left: 10px"
@change="handleInput(item, index)"
@blur="showInput = false"
></el-input>
<i class="el-icon-edit icon" style="font-size: 14px"
@click="inputShow(item, index)"></i>
</div>
</div>
<!-- 游戏业务的账号信息 -->
<!-- <gameDetails
v-if="gameUserInfo.username"
:chat-user-details="chatUserDetails"
:game-user-info="gameUserInfo"
@changeAppraisal="changeAppraisal"
/> -->
<!-- 游戏标签 -->
<!-- <div
v-else-if="messageSource === 'company_work' && workerRouter !== 'novel'"
class="item rowFlex columnCenter spaceBetween tagsLost"
>
<div class="rowFlex">
<span class="label">关联标签:</span>
<div
v-if="
chatUserDetails.tag_group &&
chatUserDetails.tag_group.length > 0
"
class="tags rowFlex columnCenter flexWarp"
>
<div
v-for="(item, index) in chatUserDetails.tag_group"
:key="index"
class="tagsItem rowFlex columnCenter flexWarp"
>
<span
v-for="(items, indexs) in item.tag"
:key="indexs"
class="tag hidden"
>{{ items.name }}</span>
</div>
</div>
</div>
<svg-icon
icon-class="edit"
class="icon"
style="font-size: 14px"
@click="editTags"
/>
</div> -->
<!-- 共享信息 -->
<shareInfo :chat-user-details="chatUserDetails" v-if="false" />
</div>
</div>
</div>
<!-- 修改手机号 -->
<changePhone
:show.sync="changePhone"
:phone.sync="gameUserInfo.mobile"
title="修改手机号"
width="350px"
/>
</div> </div>
</template> </template>
<script> <script>
import { mapState } from 'vuex'
// import gameDetails from './gameInfo/gameUserInfo.vue'
import shareInfo from './shareInfo.vue'
import changePhone from './changePhone.vue'
import { zyouUnBind,autoResetPassword,bindUserSelfAdd } from '@/api/game'
export default { export default {
name: 'InfoTabContent', name: 'UserDetailsPanel',
components: {
// gameDetails,
changePhone,
shareInfo
},
props: {
// 用户详情
chatUserDetails: {
type: Object,
default: () => ({})
},
},
data() {
return {
// 备注相关
showInputRemark: false,
showInputRemarkValue: '',
change_appraisal:false,
// 自定义列相关
showInput: false,
showInputValue: '',
inputIndex: -1,
changePhone:false
}
},
computed: {
...mapState('game', [
'accountSelect',
'gameUserInfo',
'bindGameUserList'
]),
...mapState('user', ['cser_info','cser_id','cser_name'])
},
mounted() {
},
methods: {
// 解绑确认
zyouUnBindConfirm() {
this.$confirm('确定要解绑当前账号么?', '确认提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
this.zyouUnBind()
})
.catch(() => {
this.$message({
type: 'info',
message: '已取消'
})
})
},
zyouUnBind() {
const data = {
userid: this.selectUser.userid,
external_userid: this.chatUserDetails.external_userid,
member_id: this.accountSelect
}
zyouUnBind(data).then((res) => {
if (res.status_code == 1) {
this.$message.success(res.msg)
this.set_selectWindow()
}
})
},
// 修改密码 之前是客服手动设置密码 现在改成系统自动设置密码
autoResetPassword() {
this.$confirm('确认重置密码吗?密码重置后玩家将无法登录,请谨慎操作!', '重置密码', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(res => {
const data = {
member_id: this.accountSelect,
zq_user_name: this.cser_name
}
autoResetPassword(data).then((res) => {
if (res.status_code == 1) {
this.$message.success('密码重置成功')
}
})
}).catch(() => {
this.$message({
type: 'info',
message: '已取消'
})
})
},
// 修改手机号
changePhoneClick() {
this.changePhone = true
},
// 关联客服
relationKfh() {
const username = this.bindGameUserList.find(
(item) => item.value == this.accountSelect
)
const params = {
member_id: this.accountSelect,
user_id: this.cser_id,
user_name: this.cser_name,
username: username.username
}
bindUserSelfAdd(params).then((res) => {
if (res.status_code == 1) {
this.$set(this.chatUserDetails, 'bind_cser', 1)
this.$message.success(res.msg)
}
})
},
// 误操作处理
errorHandle() {
this.$emit('error-handle')
},
// 编辑备注
editRemark() {
this.showInputRemark = true
this.showInputRemarkValue = this.chatUserDetails.remark || this.chatUserDetails.name
this.$nextTick(() => {
// document.querySelector('.showInputRemarkInput input').focus()
})
},
// 处理备注输入
handleInputRemark(val) {
this.$emit('update-remark', val)
this.showInputRemark = false
},
// 显示自定义列输入
inputShow(item, index) {
this.showInput = true
this.inputIndex = index
this.showInputValue = item.value
this.$nextTick(() => {
document.querySelectorAll('input')[0].focus()
})
},
// 处理自定义列输入
handleInput(item, index) {
this.$emit('update-custom-column', {
item,
index,
value: this.showInputValue
})
this.showInput = false
},
// 编辑标签
editTags() {
this.$emit('edit-tags')
},
// 处理评估变更
changeAppraisal(val) {
this.change_appraisal = value
}
}
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.info-tab-content{ .info-tab-content{
width: 100%; width: 100%;
height: 100%; height: 100%;
background: #fff; background: #fff;
}
.userDetailsPanel {
width: 100%;
height: 100%;
background-color: #fff;
border-radius: 4px;
overflow: hidden;
.detailsTitle {
height: 50px;
padding: 0 20px;
border-bottom: 1px solid #eee;
p {
font-size: 16px;
font-weight: 600;
}
}
.content {
width: 100%;
height: 100%;
overflow-y: auto;
overflow-x: hidden;
.item {
margin-bottom: 15px;
position: relative;
.tableImage {
width: 40px;
height: 40px;
border-radius: 4px;
margin-right: 10px;
}
.label {
color: #999;
margin-right: 5px;
min-width: 60px;
}
.text {
color: #333;
word-break: break-all;
}
.noBind {
color: #00bf8a;
cursor: pointer;
margin-right: 10px;
}
.icon {
cursor: pointer;
margin-left: 10px;
color: #999;
display: none;
}
.tags {
max-width: 200px;
.tagsItem {
margin-bottom: 5px;
.tag {
background-color: #f5f5f5;
color: #666;
padding: 2px 8px;
border-radius: 2px;
margin-right: 5px;
margin-bottom: 5px;
max-width: 100px;
}
}
}
}
.item:hover .icon {
display: block;
}
.tagsLost {
align-items: flex-start;
}
.showInputRemarkInput {
width: 160px;
}
} }
</style> }
\ No newline at end of file
.hidden {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.rowFlex {
display: flex;
flex-direction: row;
}
.columnFlex {
display: flex;
flex-direction: column;
}
.columnCenter {
align-items: center;
}
.spaceBetween {
justify-content: space-between;
}
.flexWarp {
flex-wrap: wrap;
}
</style>
\ No newline at end of file
<template> <template>
<div class="roleInfo-tab-content"> <div class="roleTab">
角色信息 <el-tabs v-model="roleActive" @tab-click="handleClick">
<el-tab-pane label="角色信息" name="role">
<userInfo v-if="roleActive==='role'" />
</el-tab-pane>
<!-- <el-tab-pane label="举报记录" name="report">
<report v-show="roleActive==='report'" />
</el-tab-pane>
-->
<el-tab-pane label="申诉记录" name="approval">
<approval v-if="roleActive==='approval'" />
</el-tab-pane>
</el-tabs>
</div> </div>
</template> </template>
<script>
export default { <script>
name: 'RoleInfoTabContent', import userInfo from './roleInfo/userInfo.vue'
// import report from './roleInfo/report.vue'
import approval from './roleInfo/approval.vue'
export default {
components: {
userInfo,
approval,
// report
},
props: {
// report_is_send: {
// type: Boolean,
// default: false
// }
},
data() {
return {
roleActive: 'role'
} }
</script> },
<style lang="scss" scoped> watch: {
.roleInfo-tab-content{ // // 监听到变化
// report_is_send(newVal, oldVal) {
// this.roleActive = 'report'
// }
},
methods: {
handleClick(value) {
}
}
}
</script>
<style lang="scss" scoped>
.roleTab{
width: 100%; width: 100%;
height: 100%; height: 100%;
background: #fff; background: #fff;
} }
</style>
\ No newline at end of file </style>
\ No newline at end of file
<template> <template>
<div class="violationRecord-tab-content"> <div class="details columnFlex">
违规记录 <div class="detailsTitle rowFlex spaceBetween columnCenter">
<p>违规记录</p>
<!-- <el-button type="primary" size="small" @click="showAddMember = true">自定义列</el-button> -->
</div> </div>
<el-form
v-loading="loading"
class="content"
label-width="100px"
>
<div v-if="violationList.length > 0">
<div
v-for="(item, index) in violationList"
:key="index"
class="contentItem"
>
<el-form-item label="违规时间:">
<p>{{ item.violation_time }}</p>
</el-form-item>
<el-form-item label="违规操作:">
<p>{{ item.violation_type_name || "" }}</p>
</el-form-item>
<el-form-item label="封禁时间:">
<p>{{ item.create_time }}</p>
</el-form-item>
<el-form-item label="角色名称:">
<p>{{ item.server_name }} - {{ item.role_name }}</p>
</el-form-item>
<el-form-item label="封禁方式:">
<p :class="item.banned_time_type == 3 ? 'error' : ''">
{{ item.banned_type_text }}
</p>
</el-form-item>
<el-form-item label="是否允许申诉:">
<p class="error">{{ item.appeal_name }}</p>
</el-form-item>
<el-form-item
v-if="item.remake != ''"
label="详情:"
>
<!-- AI自动封禁 -->
<div
class="remarkType"
v-if="item.information_type === 6"
>
<p>
<span class="label">所属项目:</span><span>{{ item.newRemake.project || "" }}</span>
</p>
<p>
<span class="label">角色ID:</span><span>{{ item.newRemake.cp_role_id || "" }}</span>
</p>
<p>
<span class="label">名单类型:</span><span>{{ item.newRemake.list_type || "" }}</span>
</p>
<p>
<span class="label">当前命中:</span><span>{{ item.newRemake.current_hit || "" }}</span>
</p>
<p>
<span class="label">累计命中:</span><span>{{ item.newRemake.hit_total || "" }}</span>
</p>
<p>
<span class="label">释放时间:</span><span>{{ item.newRemake.release_time || "" }}</span>
</p>
<p>
<span class="label">操作用户:</span><span>{{ item.newRemake.handel_user || "" }}</span>
</p>
<p>
<span class="label">备注信息:</span><span>{{ item.newRemake.remark || "" }}</span>
</p>
</div>
<!-- 其他类型 -->
<div
class="remarkType"
v-else
>
<div
v-if="item.remake.indexOf('src=') !== -1"
class="remakeImage"
>
<p class="watchDetails">
<el-button
type="text"
icon="el-icon-view"
size="medium"
style="z-index: 1; position: relative; margin-left: 5px"
@click="showRemake(item.remake)"
>查看大图</el-button>
</p>
<p v-html="item.remake"></p>
</div>
<div
v-else
class="remakeImage"
>
<p v-html="item.remake"></p>
</div>
</div>
</el-form-item>
<div>
<div
class="title"
style="font-weight: 600; margin-bottom: 10px"
>
命中统计
</div>
<BiTable
v-if="item && item.newRemake && item.newRemake.hit"
:data="item.newRemake.hit"
size="medium"
:column="tableColums"
>
<template v-slot:main_playlet="{ row }">
<p>{{ $moment(row.time).format("YYYY-MM-DD HH:mm:ss") }}</p>
</template> </template>
<script> </BiTable>
export default { </div>
name: 'ViolationRecordTabContent', </div>
</div>
<div
v-if="!loading && violationList.length == 0"
class="noContent rowFlex allCenter"
>
<svg-icon icon-class="noContent" />
</div>
</el-form>
<el-dialog
title="查看大图"
:visible.sync="imageLayer"
width="50%"
append-to-body
fit="contain"
@close="imageLayer = false"
>
<div
v-html="imageSrc"
class="layerImage"
></div>
</el-dialog>
</div>
</template>
<script>
import { mapState } from "vuex";
import { violationList } from "@/api/game";
export default {
components: {},
data() {
return {
imageSrc: [],
violationList: [],
tableColums: [
{
label: "文本内容",
prop: "content",
},
{
label: "命中类型",
prop: "type",
},
{
label: "关键字",
prop: "key",
},
{
label: "时间",
prop: "time",
width: 120,
slotScope: true
// render: (h, { row }) => {
// if (row.time) {
// return (
// <p>
// {
// this.$moment(row.time)
// .format("YYYY-MM-DD HH:mm:ss")
// }
// </p>
// );
// }
// },
},
],
loading: false,
imageLayer: false,
};
},
computed: {
...mapState("game", ["accountSelect", "gameTabActive"]),
},
watch: {
accountSelect(newVal, oldVal) {
console.log(11, "newVal");
if (newVal && newVal !== "" && this.gameTabActive == 5) {
this.requestViolationList();
} }
</script> },
<style lang="scss" scoped> },
.violationRecord-tab-content{ mounted() {
width: 100%; this.requestViolationList();
},
methods: {
handleRemark(remark) {
try {
const remarkObj = JSON.parse(JSON.parse(remark.replace(/\r\n\t/g, "")));
console.log(remarkObj, "remarkObj");
return remarkObj;
} catch (error) {
return remark;
}
},
showRemake(remake) {
this.imageSrc = remake;
this.imageLayer = true;
},
requestViolationList() {
const data = {
account_type: 1,
member_id: this.accountSelect,
};
this.loading = true;
violationList(data).then(
(res) => {
if (res.status_code == 1 && res.data.data.length > 0) {
this.violationList = res.data.data;
this.violationList.map((item) => {
if (item.information_type == 6) {
item.newRemake = this.handleRemark(item.remake);
}
});
} else {
this.violationList = [];
}
this.loading = false;
},
(err) => {
this.loading = false;
}
);
},
},
};
</script>
<style lang="scss">
.remakeImage {
img {
max-width: 200px;
height: auto;
border-radius: 5px;
margin-top: 10px;
}
}
.layerImage {
img {
max-width: 800px;
}
}
</style>
<style lang="scss" scoped>
.details {
width: vw(444);
height: 100%; height: 100%;
background: #fff; background: #fff;
margin-left: 2px;
.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%;
padding: vw(20);
height: 100%;
overflow: auto;
}
.contentMain {
}
.contentItem {
border-bottom: 1px dashed #ebeef5;
}
.remarkType {
width: auto;
margin-top: 4px;
p {
line-height: 25px;
}
.label {
color: #99a3b4;
margin-right: 5px;
}
.value {
}
}
.error {
color: #ff5959;
}
.foulImage {
max-width: 300px;
height: auto;
}
::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-collapse-item__header {
width: 100%;
height: 44px;
background: #f9faff;
color: #333333;
padding-left: 80px;
font-size: 14px;
font-weight: 400;
}
::v-deep .el-form-item {
margin-bottom: 10px;
}
}
.remakeDetails {
::v-deep img {
max-width: 200px;
max-height: 200px;
} }
</style> }
\ No newline at end of file </style>
<template>
<el-drawer :lock-scroll="true" :title="title" :visible="show" :size="width" :append-to-body="body" @close="close">
<el-form ref="ruleForm" :model="webForm" label-width="80px" class="uploadLink">
<el-form-item label="手机号">
<el-input v-model="webForm.phone" type="text" maxlength="50" placeholder="请输入手机号"></el-input>
</el-form-item>
</el-form>
<span class="dialog-footer rowFlex">
<el-button class="btn" size="small" type="primary" @click="submit">保 存</el-button>
<el-button class="btn" size="small" @click="close">取 消</el-button>
</span>
</el-drawer>
</template>
<script type="text/javascript">
import { bindMobile } from '@/api/game'
import { mapState } from 'vuex'
export default {
components: {
},
props: ['show', 'width', 'title', 'body', 'phone'],
data() {
return {
webForm: {
phone: ''
}
}
},
computed: {
...mapState('game', ['accountSelect'])
},
watch: {
show(newVal, oldVal) {
if (newVal) {
// this.handleInfo()
this.webForm.phone = this.phone
}
}
},
mounted() {
},
methods: {
close() {
this.$emit('update:show', false)
},
submit() {
if (!/^1((3[0-9])|(4[1579])|(5[0-9])|(6[6])|(7[0-9])|(8[0-9])|(9[0-9]))\d{8}$/.test(this.webForm.phone)) {
this.$message.warning('请填写正确的手机号')
return false
}
const data = {
member_id: this.accountSelect,
mobile: this.webForm.phone
}
bindMobile(data).then((res) => {
if (res.status_code == 1) {
this.$message.success(res.msg)
}
})
this.$emit('update:phone', this.webForm.phone)
this.$emit('update:show', false)
this.$emit('update:phone', this.webForm.phone)
}
}
}
</script>
<style lang="scss" scoped>
.dialog-footer {
width: calc(100% - 20px);
height: 52px;
position: absolute;
right: 20px;
bottom: 20px;
padding-top: 20px;
border-top: 1px solid rgba(0, 0, 0, 0.06);
justify-content: flex-end;
.btn {
width: 84px;
height: 32px;
}
}
.createLink {
position: relative;
top: -8px;
left: 8px;
}
// 添加网页
.uploadLink {
padding:20px;
}
</style>
\ No newline at end of file
<template>
<div>
<div class="item rowFlex columnCenter spaceBetween zyouTag">
<div class="rowFlex columnCenter">
<span class="label">掌游标签:</span>
<i
:class="['el-icon-arrow-' + (showZyouTag ? 'down' : 'right'), 'tag-icon']"
@click="toggleZyouTag"
></i>
</div>
</div>
<!-- 掌游标签列表 -->
<div v-if="showZyouTag" class="zyou-tag-list">
<div v-for="(item, index) in roleLabelList" :key="index" class="tag-group">
<div class="tag-group-header">
<div class="tag-type-name">{{ item.label_type_name }}</div>
<i v-if="item.label_type ==2" class="el-icon-circle-plus" style="color: var(--el-color-primary)" @click="toggleAddTag(index)"></i>
</div>
<!-- 新增标签区域 -->
<div v-if="showAddTagIndex === index" class="add-tag-area">
<div class="add-tag-content">
<el-cascader
v-model="searchValue"
:options="searchOptions"
collapse-tags
filterable
:props="{
multiple: true,
value: 'label_id',
label: 'label_name',
children: 'children',
emitPath: false,
disabled: 'disabled',
}"
clearable
placeholder="请选择掌游标签"
class="tag-select"
@change="handleCascaderChange"
></el-cascader>
<div class="button-group">
<el-button type="text" size="small" @click="handleSelectChange(searchValue)">确定</el-button>
<el-button type="text" size="small" @click="toggleAddTag(-1)">取消</el-button>
</div>
</div>
</div>
<div class="tag-list">
<el-popover
v-for="tag in item.label"
:key="tag.id"
placement="top"
width="250px"
trigger="click"
@show="getTagCreateInfo(tag.id)"
>
<div style="height: 50px;">
<div v-if="tagInfo.create_user" class="tag-info-item">
<span class="tag-info-label">操作人:</span>
<span class="tag-info-value">{{ tagInfo.create_user }}</span>
</div>
<div v-if="tagInfo.create_time" class="tag-info-item">
<span class="tag-info-label">操作时间:</span>
<span class="tag-info-value">{{ tagInfo.create_time }}</span>
</div>
</div>
<el-tag slot="reference" class="tag-item">
<span v-if="tag.label_group_name">{{ tag.label_group_name || '' }} / </span>
<span>{{ tag.label_name || '' }}</span>
</el-tag>
</el-popover>
</div>
</div>
</div>
</div>
</template>
<script>
import { editRoleLabel, roleGetRoleLabel, roleLabelSearch, selectSearch, getRoleLabelCreate } from '@/api/game'
import { mapState } from 'vuex'
import { debounce } from '@/utils'
export default {
name: 'ZyouTag',
props: {
accountSelect: {
type: [String, Number],
default: ''
},
gameUserInfo: {
type: Object,
default: () => ({})
}
},
data() {
return {
showZyouTag: false, // 控制标签显示隐藏
roleLabelList: [], // 角色标签列表
showAddTagIndex: -1, // 当前显示新增标签的索引
searchValue: '', // 搜索框的值
searchOptions: [], // 搜索选项
labelTypeList: [], // 标签类型列表
loading: false, // 加载状态
tagInfo: {} // 标签创建信息
}
},
computed: {
...mapState('user', ['userInfo']),
...mapState('common', ['weixin_blongs_id_list'])
},
watch: {
accountSelect: {
handler(newVal) {
if (newVal) {
this.getRoleLabelList()
}
},
immediate: true
}
},
mounted() {
this.getLabelType()
this.getRoleLabelList()
this.searchLabel('')
},
methods: {
// 获取标签类型
async getLabelType() {
try {
const res = await selectSearch({
type: 'label_type'
})
if (res.status_code === 1) {
console.log('getLabelType')
this.labelTypeList = res.data.data || []
}
} catch (error) {
console.error('获取标签类型失败:', error)
}
},
getRoleLabelList: debounce(function() {
this.getRoleLabelListFn()
}, 500),
// 获取角色标签列表
async getRoleLabelListFn() {
console.log('延迟')
if (!this.accountSelect) return
this.loading = true
try {
const weixin_blongs_id = this.weixin_blongs_id_list.map(item => item.value)
const res = await roleGetRoleLabel({
member_id: this.accountSelect,
weixin_blongs_id: weixin_blongs_id
})
if (res.status_code === 1 && res.data.data.length > 0) {
const labelData = res.data.data || []
const groupedLabels = {}
labelData.forEach(item => {
if (item.label && item.label.length > 0) {
item.label.forEach(label => {
label.label_type = Number(item.label_type)
})
}
})
// 初始化标签组
this.labelTypeList.forEach(type => {
groupedLabels[type.value] = {
label_type: type.value,
label_type_name: type.label,
label: []
}
})
// 分组标签数据
labelData.forEach(item => {
if (item.label && item.label.length > 0) {
const labelType = item.label[0].label_type
if (groupedLabels[labelType]) {
groupedLabels[labelType].label = item.label
}
}
})
// 转换为数组格式
this.roleLabelList = Object.values(groupedLabels)
console.log(this.roleLabelList, 'roleLabelList')
} else {
this.roleLabelList = this.labelTypeList.map(item => {
return {
label_type: item.value,
label_type_name: item.label,
label: []
}
})
}
} catch (error) {
console.error('获取角色标签列表失败:', error)
} finally {
this.loading = false
}
},
// 搜索标签
async searchLabel(query) {
try {
const weixin_blongs_id = this.weixin_blongs_id_list.map(item => item.value)
const res = await roleLabelSearch({
label_name: query.trim() || '',
weixin_blongs_id: weixin_blongs_id || [],
label_type: 2
})
if (res.status_code === 1) {
this.searchOptions = res.data.data || []
// 找出 label_group_id 相同的 然后 把 children 合并
const groupedItems = this.searchOptions.reduce((acc, curr) => {
const key = curr.label_group_id
if (!acc[key]) {
acc[key] = {
label_name: curr.label_group_name,
label_id: curr.label_group_id,
select_type: Number(curr.select_type),
children: []
}
}
// 将标签添加到对应标签组的children中
acc[key].children.push({
label_name: curr.label_name,
label_id: curr.id,
disabled: false // 默认不禁用
})
return acc
}, {})
// 处理单选标签组,为已选中项以外的选项添加disabled属性
Object.values(groupedItems).forEach(group => {
if (group.select_type === 1) {
// 如果是单选标签组,需要禁用其他选项
const selectedIds = Array.isArray(this.searchValue) ? this.searchValue : []
const hasSelectedInThisGroup = group.children.some(child =>
selectedIds.includes(child.label_id)
)
if (hasSelectedInThisGroup) {
group.children.forEach(child => {
// 如果当前选项不在已选中列表中,则禁用
if (!selectedIds.includes(child.label_id)) {
child.disabled = true
}
})
}
}
})
this.searchOptions = Object.values(groupedItems)
}
} catch (error) {
console.error('搜索标签失败:', error)
}
},
// 添加标签
async addLabel(selectedLabels) {
console.log(selectedLabels, 'selectedLabels')
const labelId = selectedLabels.map(label => label.label_id)
if (!this.accountSelect || !labelId) {
this.$message.error('请选择标签')
return
}
if (!this.gameUserInfo || !this.gameUserInfo.role_info || !this.gameUserInfo.role_info.role_id) {
this.$message.error('该账号未创角无法添加标签')
return
}
try {
const res = await editRoleLabel({
role_id: this.gameUserInfo.role_info.role_id || '',
member_id: this.accountSelect,
label_id: labelId,
user_id: this.userInfo.id,
user_name: this.userInfo.username,
role_name: this.gameUserInfo.role_info.role_name || '',
cp_role_id: this.gameUserInfo.role_info.cp_role_id || ''
})
if (res.status_code === 1) {
this.$message.success(res.msg)
this.searchValue = ''
this.showAddTagIndex = -1
// 暂时隐藏
// this.roleLabelList[1].label.push(...selectedLabels)
// 重置所有标签的禁用状态
this.searchOptions.forEach(group => {
if (group.children) {
group.children.forEach(child => {
child.disabled = false
})
}
})
// 刷新标签列表
setTimeout(() => {
this.getRoleLabelList()
}, 500)
}
} catch (error) {
console.error('添加标签失败:', error)
}
},
// 切换标签显示
toggleZyouTag() {
this.showZyouTag = !this.showZyouTag
},
// 切换新增标签区域显示
toggleAddTag(index) {
this.showAddTagIndex = this.showAddTagIndex === index ? -1 : index
if (this.showAddTagIndex === -1) {
this.searchValue = ''
// this.searchOptions = []
}
},
// 选择标签
handleSelectChange(value) {
if (value && Array.isArray(value) && value.length > 0) {
// 获取当前标签组的标签
const currentGroupLabels = this.roleLabelList.find(item => Number(item.label_type) === 2).label
// 获取所有选中标签的信息
const selectedLabels = []
// 遍历所有标签组
this.searchOptions.forEach(group => {
// 找出该组中被选中的标签
const selectedInGroup = group.children.filter(child =>
value.includes(child.label_id)
)
// 如果是单选标签组且选中了多个,只保留第一个
if (group.select_type === 1 && selectedInGroup.length > 1) {
this.$message.warning(`标签组"${group.label_name}"为单选,只能选择一个标签`)
// 只添加第一个选中的标签
selectedLabels.push(selectedInGroup[0])
} else {
// 多选标签组或单选标签组只选了一个,全部添加
selectedLabels.push(...selectedInGroup)
}
})
if (!selectedLabels || selectedLabels.length === 0) {
this.$message.warning('请选择有效的标签')
return
}
// 检查selectedLabels中的标签组是否与currentGroupLabels中的标签组重复
if (currentGroupLabels && currentGroupLabels.length > 0) {
const existingGroupIds = currentGroupLabels.map(label => label.label_group_id)
const hasConflict = selectedLabels.some(label =>
existingGroupIds.includes(label.label_group_id)
)
if (hasConflict) {
this.$message.warning('一标签组下只能选择一个标签')
return
}
this.addLabel(selectedLabels)
} else {
this.addLabel(selectedLabels)
}
} else {
this.$message.warning('请选择标签')
}
},
// 处理级联选择器选择变化
handleCascaderChange(value) {
// 每次选择变化时,重新处理searchOptions
// 重置所有选项的disabled状态
this.searchOptions.forEach(group => {
if (group.children) {
group.children.forEach(child => {
child.disabled = false
})
}
})
if (Array.isArray(value) && value.length > 0) {
// 检查是否有全选操作
const prevValue = [...this.searchValue || []]
// 找出所有单选标签组
const singleSelectGroups = this.searchOptions.filter(group => group.select_type === 1)
// 检查单选标签组是否有全选操作
for (const group of singleSelectGroups) {
// 获取当前组中的所有标签ID
const groupLabelIds = group.children.map(child => child.label_id)
// 检查当前组中选中的标签数量
const selectedInThisGroup = groupLabelIds.filter(id => value.includes(id))
// 如果选中的标签数量大于1,说明可能是全选操作
if (selectedInThisGroup.length > 1) {
// 提示用户只能选择一个标签
this.$message.warning(`标签组"${group.label_name}"为单选,只能选择一个标签`)
// 清空该组的选择
const newValue = value.filter(id => !groupLabelIds.includes(id))
// 更新选择值
this.searchValue = newValue
return
}
// 如果该单选标签组有选中的标签,则禁用其他标签
if (selectedInThisGroup.length === 1) {
group.children.forEach(child => {
if (!value.includes(child.label_id)) {
child.disabled = true
}
})
}
// 如果没有选中的标签,则不需要禁用任何标签,已经在前面重置了
}
}
// 如果没有选中任何标签,所有标签都应该是可选的,已经在前面重置了123
},
// 获取标签创建信息
async getTagCreateInfo(id) {
this.tagInfo = {}
try {
const res = await getRoleLabelCreate({
id: id
})
if (res.status_code === 1) {
this.tagInfo = res.data.data || {}
} else {
this.$message.error(res.msg || '获取标签信息失败')
}
} catch (error) {
console.error('获取标签创建信息失败:', error)
this.$message.error('获取标签信息失败')
}
}
}
}
</script>
<style lang="scss" scoped>
.item {
width: 100%;
height: auto;
font-size: 14px;
padding: 16px;
font-weight: 400;
color: #333333;
padding: 10px 0;
transition: all 0.5s;
position: relative;
cursor: pointer;
.label {
font-size: 14px;
color: #999999;
font-weight: 500;
margin-right: 8px;
}
.tag-icon {
cursor: pointer;
font-size: 14px;
color: #333333;
margin-right: 8px;
}
}
.zyou-tag-list {
.tag-group {
margin-bottom: 10px;
padding: 10px;
padding-top: 0;
width: 100%;
background: #F7F8FA;
border-radius: 4px;
&:last-child {
margin-bottom: 0;
}
.tag-group-header {
display: flex;
justify-content: space-between;
align-items: center;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
text-align: left;
padding-top:10px;
margin-bottom: 10px;
.tag-type-name {
font-size: 14px;
color: #323335;
font-weight: 500;
}
.el-icon-circle-plus{
font-size: 16px;
cursor: pointer;
color: #00bf8a !important;
}
}
.tag-list {
.el-tag {
font-size: 12px;
color: #323335;
background-color: #fff;
border-radius: 4px;
border: 1px solid #D6D9E0;
margin-bottom: 5px;
}
}
.add-tag-area {
margin: 10px 0;
background: #f5f7fa;
border-radius: 4px;
.add-tag-content {
gap: 12px;
.tag-select {
width: 100%;
}
.button-group {
display: flex;
justify-content: flex-end;
}
}
}
}
}
.tag-icon {
margin-left: 8px;
cursor: pointer;
color: #909399;
&:hover {
color: #409EFF;
}
}
.tag-info-item {
margin-bottom: 8px;
font-size: 12px;
.tag-info-label {
color: #909399;
margin-right: 2px;
}
.tag-info-value {
color: #333;
font-weight: 500;
}
}
</style>
\ No newline at end of file
<template>
<div class="gameUserDetails">
<!-- 智能标签 -->
<div v-if="isGameSystem && messageSource==='company_work'" class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label" style="min-width:60px; margin-left: -8px;">智能标签:</span>
<p class="text">
<el-tag v-for="(item,index) in chatUserDetails.intelligence_tag_group" :key="index" style="margin-right:5px;margin-bottom:5px;">{{ item.name }} </el-tag>
</p>
</div>
<el-popover
placement="top"
trigger="hover"
content="手动更新当前用户的智能标签,每个用户半个小时仅能更新一次"
>
<i
slot="reference"
class="el-icon-refresh refreshList"
:class="isRefresh?'refreshListActive':''"
@click="refreshTag"
></i>
</el-popover>
</div>
<ZyouTag :game-user-info="gameUserInfo" :account-select="accountSelect" />
<div v-if="accountSelect && accountSelect!=='' && gameUserInfo.username">
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">账号:</span>
<p class="text">{{ gameUserInfo.username }}</p> <span v-if="gameUserInfo.account_type==2" class="account_type"></span>
</div>
</div>
<!-- 充值金额 -->
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">充值金额:</span>
<p class="text">{{ gameUserInfo.real_recharge_total }}</p>
</div>
</div>
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">是否易主:</span>
<p class="text">{{ change_user==1?'是':'否' }}</p>
<el-popconfirm
confirm-button-text="确定"
cancel-button-text="取消"
icon="el-icon-info"
title="是否切换易主状态"
@confirm="changeUserFn"
>
<!-- changeUser -->
<div slot="reference" class="rowFlex columnCenter changeUser">
<p>
<i class="el-icon-sort-down"></i>
</p>
<p>
<i class="el-icon-sort-up"></i>
</p>
</div>
</el-popconfirm>
</div>
</div>
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">白名单:</span>
<p class="text">{{ change_name==1?'是':'否' }}</p>
<el-popconfirm
confirm-button-text="确定"
cancel-button-text="取消"
icon="el-icon-info"
title="是否切换白名单状态"
@confirm="changeNameFn"
>
<div slot="reference" class="rowFlex columnCenter changeUser">
<p>
<i class="el-icon-sort-down"></i>
</p>
<p>
<i class="el-icon-sort-up"></i>
</p>
</div>
</el-popconfirm>
</div>
</div>
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">异常账号:</span>
<p class="text">{{ change_risk==1?'是':'否' }}</p>
<el-popconfirm
confirm-button-text="确定"
cancel-button-text="取消"
icon="el-icon-info"
title="是否切换账号异常状态"
@confirm="changeRiskFn"
>
<div v-if="change_risk==0" slot="reference" class="rowFlex columnCenter changeUser">
<p>
<i class="el-icon-sort-down"></i>
</p>
<p>
<i class="el-icon-sort-up"></i>
</p>
</div>
</el-popconfirm>
</div>
</div>
<div v-if="gameUserInfo.role_info && gameUserInfo.role_info.role_level " class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">等级:</span>
<p class="text">{{ gameUserInfo.role_info.role_level }}</p>
</div>
</div>
<div v-if="gameUserInfo.role_info && gameUserInfo.role_info.trans_check_status_text " class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">转端审核:</span>
<p class="text">{{ gameUserInfo.role_info.trans_check_status_text }}</p>
</div>
</div>
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">近期是否被封禁:</span>
<p class="text">{{ gameUserInfo.is_banned==1?'是':'否' }}</p>
</div>
</div>
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">真实姓名:</span>
<p class="text">{{ gameUserInfo.real_name }}</p>
</div>
</div>
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">CP角色ID:</span>
<p v-if="gameUserInfo.role_info && gameUserInfo.role_info.cp_role_id" class="text">{{ gameUserInfo.role_info.cp_role_id }}</p>
</div>
</div>
<div v-if="messageSource==='company_work'" class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">是否愿意转端:</span>
<p class="text">
<el-radio-group v-model="chatUserDetails.transferred" @change="toTransfer">
<el-radio :label="0"></el-radio>
<el-radio :label="1"></el-radio>
</el-radio-group>
</p>
</div>
</div>
<div class="item rowFlex columnCenter">
<div class="rowFlex columnCenter">
<span class="label">手机号:</span>
<p v-if="!showUserMobile" class="text">{{ gameUserInfo.mobile }}</p>
</div>
<el-input v-if="showUserMobile" v-model="newMobileValue" style="width: 120px; margin-left: 10px" @change="changeUserMobile" @blur="showUserMobile = false"></el-input>
<!-- 暂时禁止用户修改手机号 -->
<svg-icon v-if="false" icon-class="edit" class="icon" style="font-size: 14px" @click="editUserMobile" />
</div>
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">注册游戏:</span>
<p class="text">{{ gameUserInfo.reg_game_name }}</p>
</div>
</div>
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">主游戏:</span>
<p class="text">{{ gameUserInfo.main_game_name }}</p>
</div>
</div>
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">登录系统:</span>
<p class="text">{{ gameUserInfo.last_login_os }}</p>
</div>
</div>
<div v-if="gameUserInfo.service_wechat_number_info && gameUserInfo.service_wechat_number_info.length>0" class="item rowFlex columnCenter spaceBetween">
<div class="columnFlex " style="width:100%;">
<span class="label">客服微信号:</span>
<div v-for="(item,index) in gameUserInfo.service_wechat_number_info" :key="index" class="rowFlex columnCenter " style="margin-top:10px;width:100%;">
<p class="hidden wxName">{{ item.service_wechat_number_name }}({{ item.service_type_name }})</p>
<span class="bradge">{{ item.type_name }}</span>
<div class="colorStatus rowFlex columnCenter" style="margin-left: 10px;">
<span v-if="item.loss_status==1" class="fail">{{ item.loss_status_text }}</span>
</div>
</div>
</div>
</div>
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">注册时间:</span>
<p class="text">{{ moment(gameUserInfo.reg_time * 1000).format('YYYY-MM-DD') }}</p>
</div>
</div>
</div>
</div>
</template>
<script>
import { bindMobile, getMemberLabel, editMemberLabel } from '@/api/game'
import { mapState, mapMutations } from 'vuex'
import { toTransfer, syncSessionIntelTag } from '@/api/works'
import moment from 'moment'
import ZyouTag from './ZyouTag.vue'
export default {
components: {
ZyouTag
},
props: ['gameUserInfo', 'chatUserDetails', 'messageSource'],
data() {
return {
moment,
showUserMobile: false,
change_user: 0,
change_name: 0,
change_risk: 0,
change_appraisal: 0,
newMobileValue: '',
isRefresh: false,
showWxNumber: true
}
},
computed: {
...mapState('user', ['isGameSystem', 'corpId']),
...mapState('common', ['zqUserInfo']),
...mapState('game', ['accountSelect', 'changeChangeUser'])
},
watch: {
changeChangeUser(newVal, oldVal) {
if (newVal) {
this.getMemberLabel()
}
}
},
mounted() {
this.$nextTick(() => {
console.log(this.accountSelect, 'this.accountSelect')
if (this.accountSelect && this.accountSelect !== '') {
this.getMemberLabel()
}
})
console.log(this.chatUserDetails, 'gameUserInfo')
},
methods: {
getMemberLabel() {
const data = {
member_id: this.accountSelect,
label_type: [2, 3, 4, 6]
}
getMemberLabel(data).then(res => {
if (res?.data?.data?.length > 0) {
const change_user = res.data.data.find(item => item.label_type == 2)
const change_name = res.data.data.find(item => item.label_type == 3)
const change_risk = res.data.data.find(item => item.label_type == 4)// 风险用户
const change_appraisal = res.data.data.find(item => item.label_type == 6)// 石锤用户
this.change_user = change_user.label_value
this.change_name = change_name.label_value
this.change_risk = change_risk.label_value
this.change_appraisal = change_appraisal.label_value
// change_appraisal.label_value
this.$emit('changeAppraisal', this.change_appraisal)
} else {
this.change_user = 0
this.change_name = 0
this.change_risk = 0
this.change_appraisal = 0
this.$emit('changeAppraisal', this.change_appraisal)
}
})
},
// 白名单
changeNameFn() {
const data = {
member_id: this.accountSelect,
create_user: this.zqUserInfo.name,
label_type: 3,
label_value: this.change_name == 1 ? 0 : 1
}
editMemberLabel(data).then((res) => {
if (res.status_code == 1) {
this.$message.success(res.msg)
this.change_name == 1 ? this.change_name = 0 : this.change_name = 1
}
this.$emit('update:show', false)
})
},
// 异常账号
changeRiskFn() {
const data = {
member_id: this.accountSelect,
create_user: this.zqUserInfo.name,
label_type: 4,
label_value: this.change_risk == 0 ? 1 : 0
}
editMemberLabel(data).then((res) => {
if (res.status_code == 1) {
this.$message.success(res.msg)
this.change_risk == 1 ? this.change_risk = 0 : this.change_risk = 1
}
this.$emit('update:show', false)
})
},
changeUserFn() {
// { label: '是', value: 1 }, { label: '否', value: 0 }
const data = {
member_id: this.accountSelect,
create_user: this.zqUserInfo.name,
label_type: 2,
label_value: this.change_user == 1 ? 0 : 1
}
editMemberLabel(data).then((res) => {
if (res.status_code == 1) {
this.$message.success(res.msg)
this.change_user == 1 ? this.change_user = 0 : this.change_user = 1
}
this.$emit('update:show', false)
})
},
toTransfer() {
const data = {
external_userid: this.chatUserDetails.external_userid,
userid: this.chatUserDetails.userid,
transferred: this.chatUserDetails.transferred
}
toTransfer(data).then(res => {
if (res.status_code == 1) {
this.$message.success(res.msg)
}
})
},
// 修改用户手机号
changeUserMobile() {
if (!/^1((3[0-9])|(4[1579])|(5[0-9])|(6[6])|(7[0-9])|(8[0-9])|(9[0-9]))\d{8}$/.test(this.newMobileValue)) {
this.$message.warning('请填写正确的手机号')
return false
}
this.gameUserInfo.mobile = this.newMobileValue.substr(0, 3) + '****' + this.newMobileValue.substr(7)
this.showUserMobile = false
const data = {
member_id: this.accountSelect,
mobile: this.newMobileValue
}
bindMobile(data).then((res) => {
if (res.status_code == 1) {
this.$message.success(res.msg)
}
})
},
editUserMobile() {
this.showUserMobile = true
},
async refreshTag() {
this.isRefresh = true
const data = {
corp_id: this.chatUserDetails.corp_id,
userid: this.chatUserDetails.userid,
external_userid: this.chatUserDetails.external_userid
}
try {
const res = await syncSessionIntelTag(data)
if (res.status_code === 1) {
if (res.data.is_can_sync == 1) {
this.$message.success(res.msg)
this.$set(this.chatUserDetails, 'intelligence_tag_group', res.data.intel_tag)
} else {
this.$message.warning('每个用户半个小时仅能更新一次')
}
}
} catch (error) {
this.isRefresh = false
} finally {
this.isRefresh = false
}
}
}
}
</script>
<style lang="scss" scoped>
.gameUserDetails {
width: 100%;
.changeUser{
font-size: 18px;
transform: rotate(90deg);
color: #00bf8a;
margin-left: 10px;
margin-top: -3px;
:first-child{
margin-right: -5px;
}
}
.item {
width: 100%;
height: auto;
font-size: 14px;
font-weight: 400;
color: #333333;
padding: 10px 0;
transition: all 0.5s;
position: relative;
cursor: pointer;
.tableImage {
width: 40px;
height: 40px;
border-radius: 6px;
margin-right: vw(10);
}
.wxName{
max-width: 80%;
}
.bradge{
padding: 2px 5px;
border-radius: 3px;
background: #f4f4f5;
color: #909399;
margin-left: 10px;
}
.showInputRemarkInput {
width: vw(220);
margin-left: 10px;
}
.label {
color: #999999;
}
.text {
color: #333333;
margin-left: 3px;
word-break: break-all;
max-width: calc(100% - 20px);
}
.icon {
display: none;
position: absolute;
right: 0;
top: 12px;
}
.noBind {
width: 44px;
height: 22px;
border-radius: 4px;
border: 1px solid #00bf8a;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #00bf8a;
margin-left: 30px;
cursor: pointer;
}
.tags {
width: vw(300);
margin-left: 10px;
.tagsItem {
width: vw(300);
}
.tag {
height: 22px;
line-height: 22px;
padding: 0 8px;
background: #ffffff;
border-radius: 4px;
border: 1px solid rgba(0, 0, 0, 0.2);
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
margin-right: 10px;
margin-bottom: 10px;
}
}
}
.item:hover .icon {
display: block;
}
}
.refreshList {
color: #00bf8a;
cursor: pointer;
font-size: 18px;
}
.refreshListActive{
animation:rotate 0.5s linear infinite ;
}
@keyframes rotate {
0%{
transform: rotate(0deg);
}
100%{
transform: rotate(360deg);
}
}
</style>
\ No newline at end of file
<template>
<el-drawer
:lock-scroll="true"
title="玩家申诉"
:visible="show"
size="400px"
:append-to-body="true"
@close="close"
>
<div class="drawer-content">
<el-form
ref="appealForm"
:model="appealForm"
:rules="appealRules"
label-position="top"
class="appealForm"
label-width="100px"
>
<el-form-item
label="主游戏"
prop="main_game_id"
>
<mainGameSelect
label=""
:default-value="appealForm.main_game_id"
style="width: 100%"
width="100%"
@result="mainGameResult"
/>
</el-form-item>
<el-form-item label="">
<el-radio-group v-model="appealForm.role_id_type">
<el-radio label="cp_role_id">CP角色ID</el-radio>
<el-radio label="role_id">掌游角色ID</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="CP角色ID" prop="cp_role_id">
<el-input
v-model="appealForm.cp_role_id"
style="width: 100%"
placeholder="请输入CP角色ID"
@change="change_cp_role_id"
></el-input>
</el-form-item>
<el-form-item
label="角色名"
prop="role_name"
>
<el-input
v-model="appealForm.role_name"
placeholder="请先选择主游戏和输入CP角色ID"
disabled
></el-input>
</el-form-item>
<el-form-item
label="区服"
prop="server_name"
>
<el-input
v-model="appealForm.server_name"
placeholder="请先选择主游戏和输入CP角色ID"
disabled
></el-input>
</el-form-item>
<el-form-item
label="申诉类型"
prop="appeal_type"
>
<el-select
v-model="appealForm.appeal_type"
style="width:100%;"
clearable
placeholder="请选择"
>
<el-option
v-for="item in appeal_type_list"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item
label="详情"
prop="content"
style="margin-top:-10px;"
>
<textEditor
:remark.sync="appealForm.remark"
domid="appeal_content"
:contenteditable="true"
@resultReamrk="resultReamrk"
/>
</el-form-item>
</el-form>
<span class="dialog-footer rowFlex">
<el-button
class="btn"
type="primary"
:loading="loading"
@click="submit"
>确 定</el-button>
<el-button
class="btn"
@click="close"
>取 消</el-button>
</span>
</div>
</el-drawer>
</template>
<script type="text/javascript">
import textEditor from '@/components/textEditor.vue'
import { searchcondition, appealAdd } from '@/api/game'
import { mapState } from 'vuex'
import mainGameSelect from '@/components/mainGame.vue'
export default {
components: {
textEditor,
mainGameSelect
},
computed: {
...mapState('user', ['userInfo'])
},
props: ['show', 'appealInfo'],
data() {
return {
appealRules: {
main_game_id: [
{ required: true, message: '请选择主游戏', trigger: 'change' }
],
cp_role_id: [
{ required: true, message: '请选择cp角色id', trigger: 'change' }
],
role_id: [
{ required: true, message: '请选择角色名', trigger: 'change' }
],
server_info: [
{ required: true, message: '请选择区服', trigger: 'change' }
],
appeal_type: [
{ required: true, message: '请选择违规操作', trigger: 'change' }
]
},
appealForm: {
main_game_id: '',
role_id_type: 'cp_role_id',
role_id: '',
cp_role_id: '',
appeal_type: '',
remark: '',
role_name: '',
server_name: '',
user_id: '',
user_name: ''
},
appeal_type_list: [],
loading: false,
serverNameList: []
}
},
mounted() {
this.searchcondition()
if (this.appealInfo && this.appealInfo.id) {
const {
appeal_type = '',
remark = '',
role_id = ''
} = this.appealInfo
this.appealForm.appeal_type = Number(appeal_type)
this.appealForm.remark = remark
}
},
methods: {
searchcondition() {
const data = {
type: 'dictionaries',
table_name: 'zs_appeal_request',
field_name: 'appeal_type'
}
searchcondition(data).then(res => {
this.appeal_type_list = res.data.data
})
},
async change_cp_role_id() {
if (
!!this.appealForm.cp_role_id &&
!!this.appealForm.main_game_id
) {
const res = await searchcondition({
type: 'role',
cp_role_id: this.appealForm.cp_role_id,
main_game_id: this.appealForm.main_game_id
})
if (res.status_code == 1 && res.data.data.length > 0) {
this.appealForm.role_id = res.data.data[0]
? res.data.data[0].value
: ''
this.appealForm.role_name = res.data.data[0]
? res.data.data[0].label
: ''
this.appealForm.server_name = res.data.data[0]
? res.data.data[0].server_name
: ''
} else {
this.$message.warning('角色信息不存在')
}
} else {
this.$message.warning('请先选择主游戏')
this.appealForm.cp_role_id = ''
}
},
mainGameResult(data) {
this.appealForm.main_game_id = data
this.appealForm.cp_role_id = ''
this.appealForm.role_id = ''
this.appealForm.role_name = ''
this.appealForm.server_name = ''
},
resultReamrk(text) {
// console.log(text, '最后编辑器的内容')
},
close() {
this.$emit('update:show', false)
},
submit() {
this.$refs['appealForm'].validate(async valid => {
if (valid) {
this.loading = true
await this.appealAdd()
} else {
return false
}
})
},
async appealAdd() {
const { id, username } = this.userInfo
const { role_id, appeal_type, remark, main_game_id, cp_role_id, role_name, server_name, role_id_type } = this.appealForm
const data = {
user_id: id,
user_name: username,
role_id,
appeal_type,
remark,
main_game_id,
cp_role_id,
role_name,
role_id_type,
server_name
}
try {
const res = await appealAdd(data)
if (res.status_code === 1) {
this.$message.success(res.msg)
this.close()
this.$emit('updateReportList')
}
this.loading = false
} catch (error) {
this.loading = false
}
setTimeout(() => {
this.loading = false
}, 2000)
}
}
}
</script>
<style lang="scss" scoped>
// ::v-deep .el-drawer {
// height: 100%;
// overflow: auto;
// overflow-x: hidden;
// }
.drawer-content {
width: 100%;
height: 100%;
overflow: auto;
padding: 20px;
padding-bottom: 100px;
margin-top: -20px;
}
.dialog-footer {
width: 100%;
height: auto;
position: absolute;
right: 0px;
bottom: 0px;
padding-right: 10px;
padding-top: 20px;
padding-bottom: 20px;
border-top: 1px solid rgba(0, 0, 0, 0.06);
justify-content: flex-end;
background: #fff;
.btn {
width: 84px;
height: 32px;
}
}
</style>
\ No newline at end of file
<template>
<div class="approval-role-list">
<el-form ref="taskForm" :model="reportForm" class="taskForm" label-width="85px">
<el-form-item label="角色名称">
<el-input
v-model="reportForm.role_name"
style="width:95%;"
clearable
placeholder="请输入角色名称"
@change="filterChange"
>
</el-input>
</el-form-item>
<el-form-item label="审批状态">
<el-select
v-model="reportForm.approval_status"
style="width:95%;"
clearable
placeholder="请选择审批状态"
@change="filterChange"
>
<el-option v-for="item in approvalList" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="申请方式">
<el-select
v-model="reportForm.register_type"
style="width:95%;"
clearable
placeholder="请选择申请方式"
@change="filterChange"
>
<el-option
v-for="item in register_type_list"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="时间范围">
<BiDatePicker
v-model="reportForm.create_time"
style="width: 95%"
type="datetimerange"
format="yyyy-MM-dd HH:mm:ss"
:picker-option="pickerOptions"
value-format="yyyy-MM-dd HH:mm:ss"
:default-time="['00:00:00', '23:59:59']"
:clearable="false"
range-separator="~"
start-placeholder="开始日期"
end-placeholder="结束日期"
@change="createResult"
/>
</el-form-item>
</el-form>
<div
v-infinite-scroll="paperScroll"
:infinite-scroll-disabled="!isMoreRecord"
:infinite-scroll-immediate="false"
class="mailListScroll"
>
<!-- 举报申请 -->
<div class="scrollMain">
<div v-for="(item, index) in reportList" :key="index" class="reportContent" @click="appealProcess(item, index)">
<div class="reportItem rowFlex columnCenter spaceBetween">
<div class="reportItemLeft">
<p><span class="label">角色名称:</span><span class="value">{{ item.role_name }}</span></p>
<div class="rowFlex spaceBetween columnCenter">
<p>
<span class="label">累计充值:</span><span class="value">{{ formatNumber(item.recharge_total_amount) }}
</span>
</p>
</div>
<p>
<span class="label">近一周充值:</span><span class="value">{{ formatNumber(item.recharge_week_amount)
}}</span>
</p>
<p><span class="label">违规操作:</span><span class="value">{{ item.appeal_type_text }}</span></p>
</div>
<div class="reportItemRight columnFlex columnCenter">
<el-button
v-if="item.approval_status == 1 && (item.customer_id == userInfo.id)"
type="primary"
size="mini"
style="margin-bottom:15px;"
@click.stop="handleReport(item)"
>撤销</el-button>
<el-button
v-else-if="item.approval_status == 4"
type="primary"
size="mini"
style="margin-bottom:15px;"
@click.stop="resubmitApproval(item)"
>重新提交</el-button>
<svg-icon v-if="item.approval_status == 1" icon-class="shenpi1" class="icon" />
<svg-icon v-else-if="item.approval_status == 2" icon-class="shenpi2" class="icon" />
<svg-icon v-else-if="item.approval_status == 3" icon-class="shenpi3" class="icon" />
<svg-icon v-else-if="item.approval_status == 4" icon-class="shenpi4" class="icon" />
<svg-icon v-else-if="item.approval_status == 5" icon-class="shenpi5" class="icon" />
</div>
</div>
<!-- 审批进度 -->
<el-collapse-transition>
<div v-if="item.showStep" class="appealProcessList">
<el-steps direction="vertical" :active="item.current" finish-status="success">
<el-step
v-for="(items, indexs) in item.appealProcessList"
:key="'trans_item_' + indexs"
:title="items.node_name"
>
<template slot="description">
<div v-if="items" class="trans-follow-1 card-style">
<div class="follow-item">
<span class="follow-info-label label-font">
{{ items.node_sort !== '0' ? '审批人:' : '登记人:' }}
</span>
<span class="info-value value-font">
{{ Array.isArray(items.user_name) ? items.user_name[0] : items.user_name }}
</span>
<el-tooltip
v-if="Array.isArray(items.user_name) && items.user_name.length > 1"
class="item"
effect="dark"
:content="items.user_name.slice(1).join('、')"
placement="top"
>
<span class="info-value value-font info-value-color">
{{ `+${items.user_name.length - 1}` }}
</span>
</el-tooltip>
</div>
<div v-if="items.node_sort !== '0' || item.node_name === '系统'" class="follow-item">
<span class="follow-info-label label-font">
审批结果:
</span>
<span
class="info-value value-font"
:class="[items.current < indexs ? '' : switchStateTag(items.approval_result)]"
>
{{ items.current < indexs ? '' : items.approval_result_text }}
</span>
</div>
<div class="follow-item">
<span class="follow-info-label label-font">
{{ (items.node_sort !== '0' || items.node_name === '系统') ? '审批时间:' : '登记时间:' }}
</span>
<span class="info-value value-font">
{{ items.node_sort === '0' ? items.create_time : items.update_time }}
</span>
</div>
<div
v-if="(items.node_sort !== '0' || items.node_name === '系统') && items.approval_result==='2'"
class="follow-item"
>
<span class="follow-info-label label-font">
驳回原因:
</span>
<span class="info-value value-font">
{{ items.extra_attribution.remark }}
</span>
</div>
<!-- <div
v-if="items.node_sort === item.appealProcessList[item.appealProcessList.length - 1 ].node_sort+ '' && items.approval_result === '1' && items.node_sort !== '0'"
class="follow-item-remark follow-item"
>
<span class="follow-info-label label-font">
处理结果:
</span>
<span class="info-value value-font">
{{ items.extra_attribution.banned_text }}
</span>
</div> -->
<!-- 同步掌游的内容 -->
<div
v-if="(items.node_sort === '0' || (items.extra_attribution && items.extra_attribution.remark)) && items.node_name !== '系统'"
class="info-item-remark"
>
<div style="display: flex;">
<span class="info-label remark-label">详情:</span>
<span class="preview-btn" @click.stop="previewRemark(items.extra_attribution.remark)">
<i class="el-icon-view"></i>
点击查看大图
</span>
</div>
<div class="remark-value" v-html="formatImg(items.extra_attribution && items.extra_attribution.remark ? items.extra_attribution.remark : '')"></div>
</div>
</div>
</template>
</el-step>
</el-steps>
</div>
</el-collapse-transition>
</div>
</div>
</div>
<el-dialog :visible.sync="dialogRemarkVisible" append-to-body title="查看大图" custom-class="remake-dialog">
<div class="remake-box">
<div v-html="dialogRemake"></div>
</div>
</el-dialog>
<resubmitApproval
v-if="showResubmitApproval"
:show.sync="showResubmitApproval"
:appeal-info="appealInfo"
@updateReportList="filterChange"
/>
</div>
</template>
<script>
import { searchcondition, appealList, appealCancel, appealProcess } from '@/api/game'
import { mapState, mapMutations } from 'vuex'
import { removeDp, formatNumber } from '@/utils/index'
import resubmitApproval from './appeal.vue'
export default {
computed: {
...mapState('game', ['accountSelect']),
...mapState('user', ['userInfo'])
},
components: {
resubmitApproval
},
data() {
return {
pickerOptions: {
disabledDate(time) {
const curDate = (new Date()).getTime()
const three = 90 * 24 * 3600 * 1000
const threeMonths = curDate - three
return time.getTime() > Date.now() || time.getTime() < threeMonths
}
},
reportForm: {
customer_id: '',
member_id: '',
role_id: '',
username: '',
role_name: '',
register_type: 1,
approval_status: '',
create_time: [],
create_time_start: '',
create_time_end: ''
},
appealInfo: {},
showResubmitApproval: false,
pageInfo: {
page: 1,
page_size: 20
},
reportList: [],
isMoreRecord: false,
approvalList: [],
register_type_list: [],
dialogRemarkVisible: false,
dialogRemake: '',
formatNumber: formatNumber,
taskTypeList: []
}
},
mounted() {
this.reportForm.create_time = [this.$moment().subtract(1, 'months').format('YYYY-MM-DD HH:mm:ss'), this.$moment().endOf('day').format('YYYY-MM-DD HH:mm:ss')]
this.reportForm.create_time_start = this.$moment().subtract(1, 'months').format('YYYY-MM-DD HH:mm:ss')
this.reportForm.create_time_end = this.$moment().endOf('day').format('YYYY-MM-DD HH:mm:ss')
this.requstApprovalList()
this.request_register_type()
this.filterChange()
},
methods: {
filterChange() {
this.pageInfo.page = 1
this.reportList = []
this.isMoreRecord = true
this.appealList()
},
createResult(data) {
if (data) {
this.reportForm.create_time_start = data[0]
this.reportForm.create_time_end = data[1]
} else {
this.reportForm.create_time_start = ''
this.reportForm.create_time_end = ''
}
this.filterChange()
},
async requstApprovalList() {
const data = {
type: 'dictionaries',
table_name: 'zs_refund_request',
field_name: 'approval_status'
}
const res = await searchcondition(data)
if (res.status_code === 1) {
this.approvalList = res.data.data
}
},
previewRemark(remark) {
this.dialogRemake = remark
this.dialogRemarkVisible = true
},
async appealProcess(item, index) {
console.log(item.current, 'item')
item.showStep = !item.showStep
if (item.appealProcessList.length === 0) {
const res = await appealProcess({ id: item.id })
item.appealProcessList = res.data.data
res.data.data.map((items) => {
if (items.approval_result !== '0' && items.approval_result !== '2') {
item.current += 1
}
})
this.$forceUpdate()
}
this.$forceUpdate()
},
async request_register_type() {
const data = {
type: 'dictionaries',
table_name: 'zs_report_request',
field_name: 'register_type'
}
const res = await searchcondition(data)
if (res.status_code === 1) {
this.register_type_list = res.data.data
}
},
paperScroll() {
console.log('下一页')
this.requestNextPage()
},
requestNextPage(pageInfo) {
this.pageInfo.page++
this.appealList()
},
handleCurrentChange(val) {
this.pageInfo.page = val
},
switchStateTag(status) {
switch (status) {
case '0':
return 'unhandle'
case '1':
return 'handled'
case '2':
return 'sendFail'
}
},
formatImg(html) {
return html.replaceAll(/<img/g, '<img style="max-width:100px;"')
},
switchStateText(status) {
switch (status) {
case '0':
return '待审批'
case '1':
return '通过'
case '2':
return '驳回'
}
},
// 重新提交
resubmitApproval(item) {
this.appealInfo = item
this.showResubmitApproval = true
},
handleReport(item) {
this.$confirm('确定要撤销该申请么?', '确认提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
const data = {
id: item.id,
user_id: this.userInfo.id,
user_name: this.userInfo.username
}
appealCancel(data).then(res => {
if (res.status_code === 1) {
this.$message({
type: 'success',
message: '撤销成功!'
})
this.filterChange()
}
})
})
.catch(() => {
this.$message({
type: 'info',
message: '已取消'
})
})
},
// 申诉列表
async appealList() {
if (this.accountSelect === '') {
this.$message.warning('暂无关联的账号,请先去关联账号!')
return false
}
if (this.pageInfo.page == 1) {
this.reportList = []
}
const { username, role_name, approval_status, register_type, create_time_start, create_time_end } = this.reportForm
// const { id } = this.userInfo
const data = {
username,
role_name,
approval_status,
register_type,
create_time_start,
create_time_end,
member_id: this.accountSelect,
// customer_id: id,
...this.pageInfo
}
const res = await appealList(data)
if (this.pageInfo.page == 1) {
this.reportList = res.data.data
} else {
this.reportList = removeDp(this.reportList, res.data.data, 'id')
}
if (this.reportList.length > 0) {
this.reportList.map((item) => {
item.showStep = false
item.current = 0
item.appealProcessList = []
})
} else {
this.reportList = []
}
if (res.data.data.length < 20) {
this.isMoreRecord = false
} else {
this.isMoreRecord = true
}
}
}
}
</script>
<style lang="scss" scoped>
.approval-role-list {
width: 100%;
height: 100%;
overflow: auto;
.taskForm {
::v-deep .el-form-item {
margin-bottom: 10px;
}
}
// 会话筛选
.filterChat {
width: 100%;
margin-top: 20px;
::v-deep .el-button {
margin-left: 6px;
margin-right: 0 !important;
}
.btnListScroll {
margin-bottom: 10px;
}
.chatIcon {
font-size: 20px;
margin-left: 5px;
margin-top: 10px;
cursor: pointer;
}
.itemActive {
background: #e1fff0;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #00bf8a;
border: none;
}
.btnList {
width: 100%;
margin-bottom: 10px;
overflow: auto;
.btnItem {
border: none;
background: #eef0f4;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #6e7073;
}
}
}
.mailListScroll {
width: 100%;
height: calc(100vh - 260px);
overflow-y: auto;
overflow-x: hidden;
.scrollMain {
width: 100%;
height: auto;
margin-bottom: 40px;
.reportContent {
width: calc(100% - 10px);
}
//举报申请
.reportItem {
padding: 10px;
background: #f7f8fa;
margin-bottom: 10px;
position: relative;
cursor: pointer;
color: #333333;
font-size: 14px;
font-weight: 500;
p {
line-height: 25px;
}
.reportItemLeft {
width: 100%;
.label {
font-weight: 400;
font-size: 14px;
color: #86909c;
line-height: 20px;
margin-right: 10px;
}
.value {
font-weight: 400;
font-size: 14px;
color: #333333;
line-height: 20px;
text-align: left;
}
}
.reportItemRight {
height: 100%;
.icon {
font-size: 50px;
}
}
}
.chatListItem {
width: 100%;
height: 68px;
padding: 3px vw(20);
position: relative;
cursor: pointer;
color: #333333;
font-size: 14px;
font-weight: 500;
.left {
color: #333333;
font-size: 14px;
font-weight: 500;
}
.info,
.top {
font-size: 14px;
font-weight: 400;
}
.bottom {
font-size: 14px;
color: #999999;
}
.right {
font-size: 12px;
font-weight: 400;
}
}
}
.chatListItemActive {
background: #e4fff1 !important;
}
.chatListItem:hover {
background: #e4fff1 !important;
}
}
}
// 掌游的样式
::v-deep.el-step .el-step__line {
width: 1px;
}
::v-deep .el-step>.is-success {
color: #00bf8a;
border-color: #00bf8a;
.el-step__line {
background-color: #e5e6eb;
}
}
::v-deep .el-step__main>.is-success {
color: #00bf8a;
}
::v-deep .el-step>.is-process {
color: #00bf8a;
border-color: #00bf8a;
.el-step__line {
background-color: #e5e6eb;
}
}
::v-deep .el-step__main>.is-process {
color: #00bf8a;
}
.form-item-btn {
margin: 0 0 0 20px;
}
.audit-label {
font-size: 14px;
font-weight: 800;
margin: 0 0 10px 0;
}
.remark-label {
color: #949fb0;
font-size: 14px;
}
.preview-btn {
cursor: pointer;
font-size: 14px;
color: #00bf8a;
margin: 0 0 0 10px;
i {
margin: 0 5px 0 0;
}
}
.remark-value {
min-height: 100px;
margin: 10px 0 0 40px;
padding: 6px 12px;
border: 1px solid #d9d9d9;
border-radius: 4px;
cursor: not-allowed;
color: #333;
}
.flex-box {
display: flex;
.remark-lebel {
width: 50px;
text-align: right;
}
}
.refund-flow-drawer {
position: fixed;
top: 0;
right: 700px;
}
.btm-btn-box {
position: fixed;
bottom: 20px;
width: 560px;
height: 32px;
}
.audit-state {
width: 50px;
height: 50px;
position: absolute;
top: 50%;
right: 0;
transform: translateY(-50%);
z-index: 100;
.audit-state-stamp {
font-size: 50px;
}
}
.info-item {
width: 45%;
display: flex;
height: 18px;
margin: 0 0 12px 0;
}
.info-item-pic {
width: 100%;
min-height: 96px;
max-height: 192px;
display: flex;
.img-list {
width: 464px;
display: flex;
flex-wrap: wrap;
&-item {
width: 80px;
height: 80px;
border-radius: 4px;
overflow: hidden;
margin: 0 10px 10px 0;
position: relative;
.preview-pic {
width: 80px;
height: 80px;
background: rgba(0, 0, 0, 0.5);
position: absolute;
top: 0;
left: 0;
z-index: -1;
text-align: center;
line-height: 80px;
.preview-icon {
font-size: 16px;
color: #fff;
cursor: pointer;
}
}
.screenshot {
object-fit: center;
width: 80px;
height: 80px;
}
&:hover>.preview-pic {
z-index: 100;
}
}
}
}
.flex-btn {
display: flex;
justify-content: space-between;
}
.info-label {
// width: 90px;
// text-align: right;
display: block;
margin: 0 10px 0 0;
font-size: 14px;
color: #949fb0;
}
.info-value {
display: block;
font-size: 14px;
color: #333;
}
.card-style {
background: #f2f2f7;
border-radius: 4px;
}
.trans-follow-1 {
width: vw(300);
min-height: fit-content;
margin: 6px 0 12px 0;
padding: 12px 12px 2px 12px;
position: relative;
.collapse-btn {
position: absolute;
top: 20px;
right: 15px;
}
.follow-item-remark {
width: 100%;
line-height: 20px;
margin: 0 0 12px 0;
}
.info-value-color {
color: #00bf8a;
margin-left: 5px;
}
}
.follow-item {
min-height: 20px;
line-height: 20px;
margin: 0 0 12px 0;
display: flex;
.label-left {
width: 90px;
text-align: right;
}
}
.left-label {
width: 60px;
}
.follow-info-label {
width: fit-content;
text-align: left;
display: inline-block;
margin: 0 10px 0 0;
}
.info-value {
font-size: 14px;
color: #333;
}
.label-font {
font-size: 14px;
color: #949fb0;
}
.info-item-remark {
width: 100%;
padding: 0 0 12px 0;
line-height: 20px;
.info-label {
display: block;
}
.info-value {
display: block;
width: 440px;
}
}
.appealProcessList {
margin-bottom: 20px;
margin-top: 20px;
}
</style>
\ No newline at end of file
<template>
<div class="reportList">
<el-form
ref="taskForm"
:model="reportForm"
class="taskForm"
label-width="85px"
>
<el-form-item label="角色名称">
<el-input
v-model="reportForm.role_name"
style="width:95%;"
clearable
placeholder="请输入角色名称"
@change="filterChange"
>
</el-input>
</el-form-item>
<el-form-item label="审批状态">
<el-select
v-model="reportForm.approval_status"
style="width:95%;"
clearable
placeholder="请选择审批状态"
@change="filterChange"
>
<el-option
v-for="item in approvalList"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="申请方式">
<el-select
v-model="reportForm.register_type"
style="width:95%;"
clearable
placeholder="请选择申请方式"
@change="filterChange"
>
<el-option
v-for="item in register_type_list"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
</el-form>
<div
v-infinite-scroll="paperScroll"
:infinite-scroll-disabled="!isMoreRecord"
:infinite-scroll-immediate="false"
class="mailListScroll"
>
<!-- 举报申请 -->
<div class="scrollMain">
<div
v-for="(item, index) in reportList"
:key="index"
class="reportContent"
@click="reportProcess(item, index)"
>
<div class="reportItem rowFlex spaceBetween columnCenter">
<div class="reportItemLeft">
<p><span class="label">角色名称:</span><span class="value">{{ item.role_name }}</span></p>
<p>
<span class="label">累计充值:</span><span class="value">{{ formatNumber(item.recharge_total_amount) }}
</span>
</p>
<p>
<span class="label">近一周充值:</span><span class="value">{{ formatNumber(item.recharge_week_amount)
}}</span>
</p>
<p><span class="label">违规操作:</span><span class="value">{{ item.violation_type_text }}</span></p>
</div>
<div class="reportItemRight columnFlex columnCenter">
<!-- 撤销 当item.create_user_id == zq_user_id 的时候才可以撤销 只能撤销自己提交的审批 -->
<el-button
v-if="item.approval_status == 1 && (item.create_user_id == userInfo.id)"
type="primary"
size="mini"
@click.stop="handleReport(item)"
>撤销</el-button>
<!-- 审批 只有待审批状态可以并且申请方式是玩家登记的时候才有这个 -->
<el-button
v-if="item.approval_status == 1 && reportForm.register_type == 2 && (item.customer_id == userInfo.id)"
type="primary"
size="mini"
@click.stop="resubmitReportApproval(item)"
>审批</el-button>
<!-- 重新提交 -->
<el-button
v-else-if="item.approval_status == 4"
type="primary"
size="mini"
@click.stop="resubmitReport(item)"
>重新提交</el-button>
<svg-icon
v-if="item.approval_status == 1"
icon-class="shenpi1"
class="icon"
/>
<svg-icon
v-else-if="item.approval_status == 2"
icon-class="shenpi2"
class="icon"
/>
<svg-icon
v-else-if="item.approval_status == 3"
icon-class="shenpi3"
class="icon"
/>
<svg-icon
v-else-if="item.approval_status == 4"
icon-class="shenpi4"
class="icon"
/>
<svg-icon
v-else-if="item.approval_status == 5"
icon-class="shenpi5"
class="icon"
/>
</div>
</div>
<!-- 审批进度 -->
<el-collapse-transition>
<div
v-if="item.showStep"
class="reportProcessList"
>
<el-steps
direction="vertical"
:active="item.current"
finish-status="success"
>
<el-step
v-for="(items, indexs) in item.reportProcessList"
:key="'trans_item_' + indexs"
:title="items.node_name"
>
<template slot="description">
<div
v-if="items"
class="trans-follow-1 card-style"
>
<div class="follow-item">
<span class="follow-info-label label-font">
{{ items.node_sort !== '0' ? '审批人:' : '登记人:' }}
</span>
<span class="info-value value-font">
{{ Array.isArray(items.user_name) ? items.user_name[0] : items.user_name }}
</span>
<el-tooltip
v-if="Array.isArray(items.user_name) && items.user_name.length > 1"
class="item"
effect="dark"
:content="items.user_name.slice(1).join('、')"
placement="top"
>
<span class="info-value value-font info-value-color">
{{ `+${items.user_name.length - 1}` }}
</span>
</el-tooltip>
</div>
<div
v-if="items.node_sort !== '0' || items.node_name === '系统'"
class="follow-item"
>
<span class="follow-info-label label-font">
审批结果:
</span>
<span
class="info-value value-font"
:class="[items.current < indexs? '' : switchStateTag(items.approval_result)]"
>
{{ items.current < indexs ? '' : items.approval_result_text }}
</span>
</div>
<div class="follow-item">
<span class="follow-info-label label-font">
{{ items.node_sort !== '0' || items.node_name === '系统' ? '审批时间:' : '登记时间:' }}
</span>
<span class="info-value value-font">
{{ items.node_sort === '0' ? items.create_time : items.update_time }}
</span>
</div>
<div
v-if="(items.node_sort !== '0' || items.node_name === '系统') && items.approval_result==='2'"
class="follow-item"
>
<span class="follow-info-label label-font">
驳回原因:
</span>
<span class="info-value value-font">
{{ items.extra_attribution.remark }}
</span>
</div>
<div
v-if="items.node_sort === item.reportProcessList[item.reportProcessList.length - 1 ].node_sort+ '' && items.approval_result === '1' && items.node_sort !== '0'"
class="follow-item-remark follow-item"
>
<span class="follow-info-label label-font">
处理结果:
</span>
<span class="info-value value-font">
{{ items.extra_attribution.banned_text }}
</span>
</div>
<div
v-if="items.node_sort === '0' && items.node_name !== '系统'"
class="info-item-remark"
>
<div style="display: flex;">
<span class="info-label remark-label">详情:</span>
<span
class="preview-btn"
@click.stop="previewRemark(items.extra_attribution.remark)"
>
<i class="el-icon-view"></i>
点击查看大图
</span>
</div>
<div
class="remark-value"
v-html="formatImg(items.extra_attribution && items.extra_attribution.remark ? items.extra_attribution.remark : '')"
></div>
</div>
</div>
</template>
</el-step>
</el-steps>
</div>
</el-collapse-transition>
</div>
</div>
</div>
<el-dialog
:visible.sync="dialogRemarkVisible"
append-to-body
title="查看大图"
custom-class="remake-dialog"
>
<div class="remake-box">
<div v-html="dialogRemake"></div>
</div>
</el-dialog>
<!-- 重新提交 -->
<resubmitReport
v-if="showResubmitReport"
:report-info="reportInfo"
:show.sync="showResubmitReport"
@updateReportList="filterChange"
/>
<!-- 审批 -->
<approvalTask
v-if="isApproval"
:show.sync="isApproval"
:report-info="reportInfo"
@updateReportList="filterChange"
/>
</div>
</template>
<script>
import { searchcondition, reportIndex, reportCancel, reportProcess } from '@/api/game'
import { mapState, mapMutations } from 'vuex'
import { removeDp, formatNumber } from '@/utils/index'
import resubmitReport from '../layer/report.vue'
import approvalTask from '../layer/approvalTask.vue'
export default {
computed: {
...mapState('game', ['accountSelect', 'report_is_send']),
...mapState('user', ['userInfo'])
},
components: {
resubmitReport,
approvalTask
},
data() {
return {
reportForm: {
customer_id: '',
member_id: '',
role_id: '',
username: '',
role_name: '',
register_type: 1,
approval_status: ''
},
isApproval: false,
register_type_list: [
{ value: 2, label: '玩家登记' },
{ value: 1, label: '客服登记' }
],
reportInfo: {},
pageInfo: {
page: 1,
page_size: 20
},
showResubmitReport: false,
reportList: [],
isMoreRecord: false,
approvalList: [],
dialogRemarkVisible: false,
dialogRemake: '',
formatNumber: formatNumber,
taskTypeList: []
}
},
watch: {
// 监听到变化
report_is_send(newVal, oldVal) {
console.log('变化了')
this.reportForm.register_type = 2
this.reportForm.approval_status = 1
this.filterChange()
}
},
mounted() {
// this.request_register_type()
this.requstApprovalList()
this.filterChange()
},
methods: {
resubmitReport(item) {
this.reportInfo = item
this.showResubmitReport = true
},
// 审批
resubmitReportApproval(item) {
this.reportInfo = item
this.isApproval = true
},
filterChange() {
this.pageInfo.page = 1
this.reportList = []
this.isMoreRecord = true
this.reportIndex()
},
async requstApprovalList() {
const data = {
type: 'dictionaries',
table_name: 'zs_refund_request',
field_name: 'approval_status'
}
const res = await searchcondition(data)
if (res.status_code === 1) {
this.approvalList = res.data.data
}
},
async request_register_type() {
const data = {
type: 'dictionaries',
table_name: 'zs_report_request',
field_name: 'register_type'
}
const res = await searchcondition(data)
if (res.status_code === 1) {
this.register_type_list = res.data.data
}
},
previewRemark(remark) {
this.dialogRemake = remark
this.dialogRemarkVisible = true
},
async reportProcess(item, index) {
console.log(item.current, 'item')
item.showStep = !item.showStep
if (item.reportProcessList.length === 0) {
const res = await reportProcess({ id: item.id })
item.reportProcessList = res.data.data
res.data.data.map((items) => {
if (items.approval_result !== '0' && items.approval_result !== '2') {
item.current += 1
}
})
this.$forceUpdate()
}
this.$forceUpdate()
},
paperScroll() {
this.requestNextPage()
},
requestNextPage(pageInfo) {
this.pageInfo.page++
this.reportIndex()
},
handleCurrentChange(val) {
this.pageInfo.page = val
},
switchStateTag(status) {
switch (status) {
case '0':
return 'unhandle'
case '1':
return 'handled'
case '2':
return 'sendFail'
}
},
formatImg(html) {
return html.replaceAll(/<img/g, '<img style="max-width:100px;"')
},
switchStateText(status) {
switch (status) {
case '0':
return '待审批'
case '1':
return '通过'
case '2':
return '驳回'
}
},
handleReport(item) {
this.$confirm('确定要撤销该申请么?', '确认提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
console.log(1231)
const data = {
id: item.id,
user_id: this.userInfo.id,
user_name: this.userInfo.username
}
reportCancel(data).then(res => {
if (res.status_code === 1) {
this.$message({
type: 'success',
message: '撤销成功!'
})
this.filterChange()
}
})
})
.catch(() => {
this.$message({
type: 'info',
message: '已取消'
})
})
},
// 举报列表
async reportIndex() {
if (this.accountSelect === '') {
this.$message.warning('暂无关联的账号,请先去关联账号!')
return false
}
if (this.pageInfo.page == 1) {
this.reportList = []
}
const { username, role_name, approval_status, register_type } = this.reportForm
// const { id } = this.userInfo
const data = {
username,
role_name,
approval_status,
// customer_id: id,
member_id: this.accountSelect,
register_type,
...this.pageInfo
}
const res = await reportIndex(data)
if (this.pageInfo.page == 1) {
this.reportList = res.data.data
} else {
this.reportList = removeDp(this.reportList, res.data.data, 'id')
}
if (this.reportList.length > 0) {
this.reportList.map((item) => {
item.showStep = false
item.current = 0
item.reportProcessList = []
})
} else {
this.reportList = []
}
if (res.data.data.length < 20) {
this.isMoreRecord = false
} else {
this.isMoreRecord = true
}
if (res.data.data.length < 20) {
this.isMoreRecord = false
} else {
this.isMoreRecord = true
}
}
}
}
</script>
<style lang="scss" scoped>
.reportList {
width: 100%;
height: calc(100% - 60px);
overflow: auto;
.taskForm {
::v-deep .el-form-item {
margin-bottom: 10px;
}
}
// 会话筛选
.filterChat {
width: 100%;
margin-top: 20px;
::v-deep .el-button {
margin-left: 6px;
margin-right: 0 !important;
}
.btnListScroll {
margin-bottom: 10px;
}
.chatIcon {
font-size: 20px;
margin-left: 5px;
margin-top: 10px;
cursor: pointer;
}
.itemActive {
background: #e1fff0;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #00bf8a;
border: none;
}
.btnList {
width: 100%;
margin-bottom: 10px;
overflow: auto;
.btnItem {
border: none;
background: #eef0f4;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #6e7073;
}
}
}
.mailListScroll {
width: 100%;
height: calc(100vh - 220px);
overflow-y: auto;
overflow-x: hidden;
.scrollMain {
width: 100%;
height: auto;
margin-bottom: 40px;
.reportContent {
width: calc(100% - 10px);
}
//举报申请
.reportItem {
padding: 10px;
background: #f7f8fa;
margin-bottom: 10px;
position: relative;
cursor: pointer;
color: #333333;
font-size: 14px;
font-weight: 500;
p {
line-height: 25px;
}
.reportItemLeft {
width: 100%;
.label {
font-weight: 400;
font-size: 14px;
color: #86909c;
line-height: 20px;
margin-right: 10px;
}
.value {
font-weight: 400;
font-size: 14px;
color: #333333;
line-height: 20px;
text-align: left;
}
}
.reportItemRight {
height: 100%;
.icon {
font-size: 50px;
}
}
}
.chatListItem {
width: 100%;
height: 68px;
padding: 3px vw(20);
position: relative;
cursor: pointer;
color: #333333;
font-size: 14px;
font-weight: 500;
.left {
color: #333333;
font-size: 14px;
font-weight: 500;
}
.info,
.top {
font-size: 14px;
font-weight: 400;
}
.bottom {
font-size: 14px;
color: #999999;
}
.right {
font-size: 12px;
font-weight: 400;
}
}
}
.chatListItemActive {
background: #e4fff1 !important;
}
.chatListItem:hover {
background: #e4fff1 !important;
}
}
}
// 掌游的样式
::v-deep.el-step .el-step__line {
width: 1px;
}
::v-deep .el-step > .is-success {
color: #00bf8a;
border-color: #00bf8a;
.el-step__line {
background-color: #e5e6eb;
}
}
::v-deep .el-step__main > .is-success {
color: #00bf8a;
}
::v-deep .el-step > .is-process {
color: #00bf8a;
border-color: #00bf8a;
.el-step__line {
background-color: #e5e6eb;
}
}
::v-deep .el-step__main > .is-process {
color: #00bf8a;
}
.form-item-btn {
margin: 0 0 0 20px;
}
.audit-label {
font-size: 14px;
font-weight: 800;
margin: 0 0 10px 0;
}
.remark-label {
color: #949fb0;
font-size: 14px;
}
.preview-btn {
cursor: pointer;
font-size: 14px;
color: #00bf8a;
margin: 0 0 0 10px;
i {
margin: 0 5px 0 0;
}
}
.remark-value {
min-height: 100px;
margin: 10px 0 0 40px;
padding: 6px 12px;
border: 1px solid #d9d9d9;
border-radius: 4px;
cursor: not-allowed;
color: #333;
}
.flex-box {
display: flex;
.remark-lebel {
width: 50px;
text-align: right;
}
}
.refund-flow-drawer {
position: fixed;
top: 0;
right: 700px;
}
.btm-btn-box {
position: fixed;
bottom: 20px;
width: 560px;
height: 32px;
}
.audit-state {
width: 50px;
height: 50px;
position: absolute;
top: 50%;
right: 0;
transform: translateY(-50%);
z-index: 100;
.audit-state-stamp {
font-size: 50px;
}
}
.info-item {
width: 45%;
display: flex;
height: 18px;
margin: 0 0 12px 0;
}
.info-item-pic {
width: 100%;
min-height: 96px;
max-height: 192px;
display: flex;
.img-list {
width: 464px;
display: flex;
flex-wrap: wrap;
&-item {
width: 80px;
height: 80px;
border-radius: 4px;
overflow: hidden;
margin: 0 10px 10px 0;
position: relative;
.preview-pic {
width: 80px;
height: 80px;
background: rgba(0, 0, 0, 0.5);
position: absolute;
top: 0;
left: 0;
z-index: -1;
text-align: center;
line-height: 80px;
.preview-icon {
font-size: 16px;
color: #fff;
cursor: pointer;
}
}
.screenshot {
object-fit: center;
width: 80px;
height: 80px;
}
&:hover > .preview-pic {
z-index: 100;
}
}
}
}
.flex-btn {
display: flex;
justify-content: space-between;
}
.info-label {
// width: 90px;
// text-align: right;
display: block;
margin: 0 10px 0 0;
font-size: 14px;
color: #949fb0;
}
.info-value {
display: block;
font-size: 14px;
color: #333;
}
.card-style {
background: #f2f2f7;
border-radius: 4px;
}
.trans-follow-1 {
width: vw(300);
min-height: fit-content;
margin: 6px 0 12px 0;
padding: 12px 12px 2px 12px;
position: relative;
.collapse-btn {
position: absolute;
top: 20px;
right: 15px;
}
.follow-item-remark {
width: 100%;
line-height: 20px;
margin: 0 0 12px 0;
}
.info-value-color {
color: #00bf8a;
margin-left: 5px;
}
}
.follow-item {
min-height: 20px;
line-height: 20px;
margin: 0 0 12px 0;
display: flex;
.label-left {
width: 90px;
text-align: right;
}
}
.left-label {
width: 60px;
}
.follow-info-label {
white-space: nowrap;
text-align: left;
margin: 0 10px 0 0;
}
.info-value {
font-size: 14px;
color: #333;
}
.label-font {
font-size: 14px;
color: #949fb0;
}
.info-item-remark {
width: 100%;
padding: 0 0 12px 0;
line-height: 20px;
.info-label {
display: block;
}
.info-value {
display: block;
width: 440px;
}
}
.reportProcessList {
margin-bottom: 20px;
margin-top: 20px;
}
</style>
\ No newline at end of file
<template>
<div class="details-user-info-role columnFlex">
<div
v-loading="loading"
class="detailsContent"
>
<div v-if="roleList.length>0">
<p class="textInfo">角色充值金额信息会有5-10分钟延迟,请以订单信息为准</p>
<el-collapse
v-model="collapseActive"
@change="handleChange"
>
<div
v-for="(items,indexs) in roleList"
:key="indexs"
class="contentItem"
>
<div class="title"></div>
<el-collapse-item :name="items.id">
<template slot="title">
<div class="collapseTitle rowFlex columnCenter spaceBetween">
<p class="hidden">
{{ items.role_name }} - {{ items.server_name }} - {{ items.recharge_total?items.recharge_total+'元':'0元' }}
</p>
<el-button
type="primary"
size="mini"
class="collapseTitleBtn"
@click.stop="appealLayer(items)"
>申诉</el-button>
</div>
</template>
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">区服:</span>
<p class="text">{{ items.server_name }}</p>
</div>
</div>
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">合区区服:</span>
<p class="text">{{ items.merge_server_name }}</p>
</div>
</div>
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">角色名称:</span>
<p class="text">{{ items.role_name }}</p>
</div>
</div>
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">等级:</span>
<p class="text">{{ items.role_level }}</p>
</div>
</div>
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">战力:</span>
<p class="text">{{ items.combat_num }}</p>
</div>
</div>
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">充值金额:</span>
<p class="text">{{ items.recharge_total }}</p>
</div>
</div>
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">转端审核:</span>
<p class="text">{{ items.trans_status_name || '无' }}</p>
</div>
</div>
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">CP角色ID:</span>
<p class="text">{{ items.cp_role_id }}</p>
</div>
</div>
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">最近活跃时间:</span>
<p class="text">{{ $moment( items.last_login_time * 1000).format('YYYY-MM-DD HH:mm:ss') }}</p>
</div>
</div>
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">创建时间:</span>
<p class="text">{{ $moment( items.create_time * 1000).format('YYYY-MM-DD HH:mm:ss') }}</p>
</div>
</div>
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">创角天数:</span>
<p class="text">{{ items.create_role_day }}天</p>
</div>
</div>
</el-collapse-item>
</div>
</el-collapse>
</div>
<div
v-else-if="!loading && roleList.length==0"
class="noContent rowFlex allCenter"
>
<noContent/>
</div>
</div>
<appeal
v-if="showAppeal"
:show.sync="showAppeal"
:appeal-info="appealInfo"
/>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex'
import { getRoleHoLo } from '@/api/game'
import noContent from '@/components/noContent.vue'
import appeal from './appeal.vue'
export default {
components: {
noContent,
appeal
},
data() {
return {
collapseActive: [],
roleList: [],
nowTime: '',
loading: false,
showAppeal: false,
appealInfo: {},
pageInfo: {
page_size: 100,
page: 1,
total: 0
},
infoList: []
}
},
computed: {
...mapState('game', ['accountSelect', 'gameTabActive'])
},
watch: {
accountSelect(newVal, oldVal) {
if (newVal && newVal !== '' && this.gameTabActive == 2) {
this.requestRoleList()
}
}
},
mounted() {
this.requestRoleList()
this.nowTime = new Date().getTime()
},
methods: {
handleChange() {
},
// 申诉
appealLayer(item) {
this.appealInfo = item
this.showAppeal = true
},
requestRoleList() {
if (this.accountSelect === '') {
this.$message.warning('暂无关联的账号,请先去关联账号!')
return false
}
this.loading = true
const data = {
api_search_name: '',
member_id: this.accountSelect,
search_type: 'list',
...this.pageInfo
}
getRoleHoLo(data).then(res => {
this.loading = false
if (res.status_code == 1) {
if (res.data.data.length > 0) {
this.roleList = res.data.data.sort((a, b) => { return Number(b.recharge_total) - Number(a.recharge_total) })
} else {
this.roleList = []
}
}
}, err => {
this.loading = false
})
}
}
}
</script>
<style lang="scss" scoped>
.details-user-info-role {
width: 100%;
height: 100%;
background: #fff;
margin-left: 2px;
.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;
}
}
.detailsContent {
width: 100%;
height: calc(100vh - 100px);
overflow: auto;
.textInfo {
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999999;
font-size: 12px;
margin-bottom: 10px;
}
.contentItem {
position: relative;
.title {
position: absolute;
left: 10px;
top: 14px;
font-size: 14px;
color: #999999;
}
.collapseTitle {
width: 90%;
}
}
.item {
width: 100%;
height: auto;
font-size: 14px;
font-weight: 400;
color: #333333;
padding: 5px 0;
transition: all 0.5s;
position: relative;
padding-left: 10px;
cursor: pointer;
.tableImage {
width: 40px;
height: 40px;
border-radius: 6px;
margin-right: vw(10);
}
.label {
color: #999999;
}
.text {
color: #333333;
margin-left: 10px;
word-break: break-all;
max-width: 80%;
}
.icon {
display: none;
position: absolute;
right: 0;
top: 12px;
}
.tags {
width: vw(300);
margin-left: 10px;
.tagsItem {
width: vw(300);
}
.tag {
height: 22px;
line-height: 22px;
padding: 0 8px;
background: #ffffff;
border-radius: 4px;
border: 1px solid rgba(0, 0, 0, 0.2);
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
margin-right: 10px;
margin-bottom: 10px;
}
}
}
.item:hover .icon {
display: block;
}
}
::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-collapse-item__header {
width: 100%;
height: 44px;
background: #f9faff;
color: #333333;
padding-left: 10px;
font-size: 14px;
font-weight: 400;
}
}
</style>
\ No newline at end of file
<template>
<div class="newPage">
<!-- 共享信息 -->
<div v-if="userList.length > 0" class="item columnFlex spaceBetween">
<!-- <div class="rowFlex columnCenter">
<span class="label">共享信息:</span>
<i style="margin-left: 10px; font-size: 20px; color: #0ac358; cursor: pointer" class="el-icon-circle-plus-outline" type="primary" @click="addGroupText"></i>
</div> -->
<div v-for="(i,k) in userList" :key="k" class="userList rowFlex ">
<p class="label hidden">{{ i.zq_user_name }} -- {{ i.name }}</p>
<div style="margin-bottom:10px;" class="columnFlex ">
<div v-for="(item,index) in i.text" :key="index+'1'" class="keyWordsItem rowFlex columnCenter">
<el-input v-model="item.text" type="textarea" :disabled="chatUserDetails.userid !== i.userid || i.zq_user_id!== userInfo.id" placeholder="请输入共享信息" @change="inputBlur(k,index)"> </el-input>
<div v-if="chatUserDetails.userid == i.userid && i.zq_user_id=== userInfo.id">
<i v-if="index==0" style="margin-left:10px;font-size:20px;color:#0AC358;cursor: pointer;" class="el-icon-circle-plus-outline" type="primary" @click="addInputItem(k,index)"></i>
<i v-else style="margin-left:10px;font-size:20px;color:#0AC358;cursor: pointer;" class="el-icon-remove-outline" type="primary" @click="removeInput(k,index)"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { shareInfoUpsert, shareInfoDel } from '@/api/works'
import { mapState } from 'vuex'
export default {
name: 'ShareInfo',
props: ['chatUserDetails'],
data() {
return {
inputList: [],
userList: []
}
},
computed: {
...mapState('user', ['userInfo'])
},
watch: {
chatUserDetails(newVal, oldVal) {
this.handleUserList()
}
},
mounted() {
this.handleUserList()
},
methods: {
handleUserList() {
if (this.chatUserDetails.share_info && this.chatUserDetails.share_info.length > 0) {
const item = this.chatUserDetails.share_info.find(item => item.userid === this.chatUserDetails.userid && item.zq_user_id === this.userInfo.id)
if (!item) {
this.userList = [...this.chatUserDetails.share_info, { zq_user_name: this.userInfo.username, zq_user_id: this.userInfo.id, userid: this.chatUserDetails.userid, name: this.chatUserDetails?.user?.name || '', text: [{ id: '', text: '' }] }]
} else {
this.userList = this.chatUserDetails.share_info
}
} else {
this.userList = [{ zq_user_name: this.userInfo.username, zq_user_id: this.userInfo.id, userid: this.chatUserDetails.userid, name: this.chatUserDetails?.user?.name || '', text: [{ id: '', text: '' }] }]
}
},
addGroupText() {
if (this.userList.length > 0) {
const user = this.userList.find(item => {
if (this.chatUserDetails.user.name === item.zq_user_name) {
return item
}
})
if (user !== -1) {
this.$message.warning(user.zq_user_name + '共享信息已存在')
} else {
this.userList.push({ zq_user_name: this.chatUserDetails.user.name, text: [{ _id: '', text: '' }] })
}
} else {
this.userList.push({ zq_user_name: this.chatUserDetails.user.name, text: [{ _id: '', text: '' }] })
}
},
shareInfoUpsert(_id, text) {
if (text && text.trim() == '') {
this.$message.warning('请输入内容')
return false
}
const data = {
_id: _id || '',
userid: this.chatUserDetails.userid,
external_userid: this.chatUserDetails.external_userid,
text: text.trim()
}
shareInfoUpsert(data).then(res => {
if (res.status_code == 1) {
this.$message.success('保存成功')
}
})
},
inputBlur(k, index) {
// 修改信息
this.shareInfoUpsert(this.userList[k]?.text[index]._id, this.userList[k]?.text[index].text)
},
removeInput(k, index) {
if (this.userList[k]?.text[index]?._id !== '') {
this.shareInfoDel({ _id: this.userList[k].text[index]._id, userid: this.chatUserDetails.userid })
// 请求删除接口
} else {
}
this.userList[k].text.splice(index, 1)
},
// 删除共享信息
shareInfoDel(data) {
shareInfoDel(data).then(res => {
if (res.status_code == 1) {
this.$message.success(res.msg)
}
})
},
// 添加时间点
addInputItem(index) {
this.userList[index].text.push({ _id: '', text: '' })
this.inputList.push({ text: '' })
}
}
}
</script>
<style lang="scss" scoped>
.newPage {
width: 100%;
height: auto;
.item {
width: 100%;
height: auto;
font-size: 14px;
font-weight: 400;
color: #333333;
padding: 10px 0;
transition: all 0.5s;
position: relative;
cursor: pointer;
.tableImage {
width: 40px;
height: 40px;
border-radius: 6px;
margin-right: vw(10);
}
.showInputRemarkInput {
width: vw(220);
margin-left: 10px;
}
.label {
color: #999999;
width: vw(125);
}
.text {
color: #333333;
margin-left: 10px;
word-break: break-all;
max-width: 100%;
}
.icon {
display: none;
position: absolute;
right: 0;
top: 12px;
}
.noBind {
width: 44px;
height: 22px;
border-radius: 4px;
border: 1px solid #00bf8a;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #00bf8a;
margin-left: 30px;
cursor: pointer;
}
.tags {
width: vw(300);
margin-left: 10px;
.tagsItem {
width: vw(300);
}
.tag {
height: 22px;
line-height: 22px;
padding: 0 8px;
background: #ffffff;
border-radius: 4px;
border: 1px solid rgba(0, 0, 0, 0.2);
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
margin-right: 10px;
margin-bottom: 10px;
}
}
}
.item:hover .icon {
display: block;
}
.userList{
width: 100%;
height: auto;
margin-top: 20px;
.label{
margin-right: 10px;
margin-top: 8px;
}
.keyWordsItem{
margin-bottom: 20px;
}
}
}
</style>
\ No newline at end of file
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
<!-- 用 el-tabs 有三个 tab 分别是 客户资料 角色信息 违规记录 用 v-for 循环 --> <!-- 用 el-tabs 有三个 tab 分别是 客户资料 角色信息 违规记录 用 v-for 循环 -->
<el-tabs v-model="activeTab" > <el-tabs v-model="activeTab" >
<el-tab-pane v-for="item in tabList" :key="item.name" :label="item.name" :name="item.value"> <el-tab-pane v-for="item in tabList" :key="item.name" :label="item.name" :name="item.value">
<Info v-if="item.value === 'userInfo'"/> <Info v-if="activeTab === 'userInfo'" :chatUserDetails="chatUserInfo"/>
<RoleInfo v-if="item.value === 'roleInfo'"/> <RoleInfo v-if="activeTab === 'roleInfo'"/>
<ViolationRecord v-if="item.value === 'violationRecord'"/> <ViolationRecord v-if="activeTab === 'violationRecord'"/>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</div> </div>
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
import Info from './components/Info.vue' import Info from './components/Info.vue'
import RoleInfo from './components/RoleInfo.vue' import RoleInfo from './components/RoleInfo.vue'
import ViolationRecord from './components/ViolationRecord.vue' import ViolationRecord from './components/ViolationRecord.vue'
import { mapState,mapMutations } from 'vuex'
import Cookies from 'js-cookie'
export default { export default {
name: 'UserInfo', name: 'UserInfo',
components:{ components:{
...@@ -22,7 +24,9 @@ export default { ...@@ -22,7 +24,9 @@ export default {
ViolationRecord ViolationRecord
}, },
mounted() { mounted() {
},
computed: {
...mapState('game', ['chatUserInfo']),
}, },
data() { data() {
return { return {
...@@ -44,14 +48,25 @@ export default { ...@@ -44,14 +48,25 @@ export default {
} }
}, },
created(){ created(){
console.log(window.location.href,'window.location.href') // 初始化 vuex 中的值
}, this.initVuexValue()
computed: {
}, },
methods: { methods:{
...mapMutations('game',['set_chatUserInfo']),
...mapMutations('user',['set_userid','set_corp_id','set_external_userid','set_token','set_cser_info','set_cser_id','set_cser_name']),
initVuexValue(){
this.set_userid(Cookies.get('userid'))
this.set_corp_id(Cookies.get('corp_id'))
this.set_external_userid(Cookies.get('external_userid'))
this.set_token(Cookies.get('token'))
this.set_cser_id(Cookies.get('cser_id'))
this.set_cser_name(Cookies.get('cser_name'))
const cser_info = Cookies.get('cser_info')
console.log(Cookies.get('cser_id'),'cser_info',Cookies.get('cser_name'))
cser_info?this.set_cser_info(JSON.parse(cser_info)):this.set_cser_info({})
} }
}
} }
</script> </script>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论