提交 c8006204 作者: 施汉文

🌈 style: 新增关联账号样式修改

上级 a21e58e2
......@@ -17,7 +17,7 @@
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0,shrink-to-fit=no,user-scalable=no"> -->
<script src="https://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script>
<!-- iconpark CDN链接 -->
<script src="https://lf1-cdn-tos.bytegoofy.com/obj/iconpark/icons_27278_168.abab0e7be76224e5929cf4315f14d58c.es5.js"></script>
<script src="https://lf1-cdn-tos.bytegoofy.com/obj/iconpark/icons_27278_169.71fe6b5f95ef2c1f5cb5bd7e2398c9dd.es5.js"></script>
</head>
<body>
<noscript>
......
<template>
<div id="app" class="mobile-app-wrapper">
<Debug />
<div class="mobile-content">
<div class="mobile-content flex flex-col">
<div class="!p-[10px] !min-h-auto text-[13px] text-[#131920] font-medium">
{{ title }}
</div>
<!-- 绑定的 w 账号 -->
<bindUserList class="!min-h-auto" />
<div class="flex-1 w-full h-full overflow-hidden">
<router-view></router-view>
</div>
</div>
<div
class="mobile-menu-bar w-[40px] overflow-hidden"
v-if="token && external_userid && showMemberId"
......@@ -40,8 +47,11 @@
<el-tooltip
class="item"
effect="dark"
:disabled="item.path !== '/agentStatusManagement'"
:content="'客服状态:' + csStatusInfo.text"
:content="
item.path === '/agentStatusManagement'
? '客服状态:' + csStatusInfo.text
: item.label
"
placement="left"
>
<div
......@@ -63,18 +73,22 @@
</div>
<!-- 普通菜单项 -->
<!-- <span >{{ item.label }}</span> -->
<iconpark-icon
<el-tooltip
v-else
class="item"
effect="dark"
:content="item.label"
placement="left"
>
<iconpark-icon
class="w-[14px] h-[14px]"
:name="item.icon"
></iconpark-icon>
</el-tooltip>
</div>
</el-menu-item>
</el-menu>
</div>
<!-- 绑定的 w 账号 -->
<bindUserList />
</div>
</div>
</template>
......@@ -85,6 +99,7 @@ import { mapState, mapMutations, mapActions } from "vuex";
import Cookies from "js-cookie";
import { getParams } from "@/utils/index";
import Debug from "@/components/debug.vue";
import { getClientStatus } from "@/api/user";
export default {
name: "App",
......@@ -174,6 +189,7 @@ export default {
"token",
"userInfo",
"client_online_status",
"userid",
]),
...mapState("game", ["taskData"]),
// 计算任务列表是否需要显示红点
......@@ -198,6 +214,10 @@ export default {
};
return statusMap[this.client_online_status] || "未知";
},
title() {
return this.menuList.find((item) => item.path === this.$route.path)
?.label;
},
},
watch: {
"$route.path"(val) {
......@@ -258,6 +278,7 @@ export default {
this.set_token(cookieToken);
console.log("从 Cookie 恢复 token:", cookieToken);
}
// 初始化时处理路径
const currentPath = this.$route.path;
if (
......@@ -277,6 +298,10 @@ export default {
this.$nextTick(() => {
this.checkMenuOverflow();
this.initVuexValue();
// 获取客服状态和相关信息
if (this.userid && this.token) {
this.getInitialData();
}
});
},
beforeDestroy() {
......@@ -291,6 +316,7 @@ export default {
"set_cser_id",
"set_cser_name",
"set_userInfo",
"set_client_online_status",
]),
...mapMutations("game", ["set_accountSelect"]),
...mapActions("game", ["getTaskUnReadData"]),
......@@ -320,6 +346,25 @@ export default {
handleSelect(key, keyPath) {
console.log("菜单选择:", key, keyPath, window.location.href);
},
// 获取初始数据
async getInitialData() {
try {
// 获取客服休息状态
const statusRes = await getClientStatus();
if (statusRes.status_code === 1) {
if (statusRes.data.client_online_status === "offline") {
removeToken();
window.location.href =
window.location.origin +
"/company_app/index.html?corp_id=" +
this.corp_id;
}
this.set_client_online_status(statusRes.data.client_online_status);
}
} catch (error) {
console.error("获取初始数据失败:", error);
}
},
// 检查菜单是否需要换行
checkMenuOverflow() {
......@@ -442,8 +487,7 @@ export default {
.mobile-content > div {
background: #fff;
border-radius: 8px;
min-height: 60vh;
padding: 10px;
padding: 10px 0px;
}
.el-menu--horizontal > .el-menu-item {
......@@ -484,4 +528,7 @@ body {
align-items: center;
justify-content: center;
}
.p-common {
padding: 0 10px;
}
</style>
<template>
<el-drawer
:visible="visible"
:title="title"
:size="size"
:append-to-body="true"
@close="$emit('close')"
:show-close="false"
>
<template #title>
<div class="flex items-center">
<iconpark-icon
@click="$emit('close')"
name="icon-fanhui"
class="mr-[8px] w-[20px] text-[20px] cursor-pointer"
></iconpark-icon>
<span class="text-[13px] text-[#131920] leading-[13px]">{{
title
}}</span>
</div>
</template>
<slot></slot>
<span class="dialog-footer rowFlex">
<slot name="footer">
<el-button class="btn" size="small" @click="$emit('close')">
取 消
</el-button>
<el-button
class="btn"
type="primary"
size="small"
:disabled="okDisabled"
@click="this.$emit('ok')"
>
确 定
</el-button>
</slot>
</span>
</el-drawer>
</template>
<script>
export default {
name: "Ui-Drawer",
props: ["visible", "size", "title", "okDisabled"],
};
</script>
<style scoped>
::v-deep .el-drawer__header {
padding: 12px 0px;
margin: 0 12px;
}
.dialog-footer {
width: 100%;
position: absolute;
bottom: 0;
padding-top: 20px;
padding-bottom: 20px;
border-top: 0;
justify-content: flex-end;
background: #fff;
z-index: 10;
.btn {
width: 60px;
height: 32px;
border-radius: 6px;
}
}
</style>
......@@ -5,38 +5,36 @@
:current-page.sync="pageInfo.page"
:page-size="Number(pageInfo.page_size)"
background
layout="total,prev, pager, next, jumper"
layout="prev, pager, next"
@current-change="handleCurrentChange"
>
</el-pagination>
</div>
</template>
</template>
<script type="text/javascript">
export default {
name: 'pageNum',
props: ['pageInfo'],
<script type="text/javascript">
export default {
name: "pageNum",
props: ["pageInfo"],
data() {
return {}
},
mounted() {
return {};
},
mounted() {},
methods: {
handleCurrentChange(newPage) {
this.pageInfo.page = newPage
this.$emit('requestNextPage', this.pageInfo)
}
}
}
</script>
this.pageInfo.page = newPage;
this.$emit("requestNextPage", this.pageInfo);
},
},
};
</script>
<style lang="scss" scoped>
.newPage {
<style lang="scss" scoped>
.newPage {
width: 100%;
height: 60px;
background: #fff;
border-radius: 0 0 5px 5px;
padding-bottom: 20px;
}
</style>
\ No newline at end of file
}
</style>
......@@ -80,6 +80,8 @@ const mutations = {
state.isWecomSDKReady = status
},
set_client_online_status(state, status) {
console.log('设置客服休息状态', status);
state.client_online_status = status
}
}
......
<template>
<div class="p-3 h-full">
<div class="text-[13px] text-[#131920] font-medium">在线客服</div>
<div class="!p-[12px] h-full">
<div class="px-[9px] pt-[60px] flex flex-col items-center justify-center">
<div class="h-[80px] w-[80px]">
<img :src="avatar" alt="" class="h-full w-full rounded-[6px]" />
......@@ -141,44 +140,11 @@ export default {
return this.client_online_status;
},
},
mounted() {
// 获取客服状态和相关信息
this.$nextTick(() => {
if (this.userid && this.token) {
this.getInitialData();
}
});
},
mounted() {},
methods: {
...mapMutations("user", ["set_client_online_status"]),
...mapActions("user", ["initWecom"]),
// 获取初始数据
async getInitialData() {
console.log(this.userInfo, 1111111);
// 如果userInfo.id存在,说明已经获取过客服状态,直接返回
if (this.userInfo.id) return;
try {
// 获取客服休息状态
const statusRes = await getClientStatus();
if (statusRes.status_code === 1) {
if (statusRes.data.client_online_status === "offline") {
removeToken();
window.location.href =
window.location.origin +
"/company_app/index.html?corp_id=" +
this.corp_id;
}
console.log(statusRes.data, 123131231);
this.set_client_online_status(statusRes.data.client_online_status);
}
} catch (error) {
console.error("获取初始数据失败:", error);
}
},
// 下线确认
logout() {
if (this.client_online_status === "rest") {
......
<template>
<el-drawer title="新增关联账号" :visible="show" size="360px" :append-to-body="true" @close="close">
<Drawer
title="新增关联账号"
:visible="show"
size="360px"
@close="close"
:okDisabled="!userDetails.id"
@ok="confirmSubmit"
>
<div class="w-full h-full py-[10px]">
<div class="flex items-center px-[12px]">
<el-input
v-model.trim="inputValue"
@input="handleChange"
class="custom-input"
placeholder="请输入W账号/角色名"
>
<i slot="prepend" class="el-icon-search"></i>
</el-input>
<el-popover placement="bottom" width="180" trigger="click">
<div>
<div>注游戏</div>
<el-select
v-model="form.main_game_id"
filterable
remote
clearable
reserve-keyword
placeholder="请输入"
style="width: 100%"
:remote-method="remoteMethod"
:loading="loading"
@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>
<el-select
v-model.trim="form.server_info"
filterable
remote
:disabled="form.main_game_id == ''"
clearable
style="width: 100%"
reserve-keyword
placeholder="请先选择主游戏"
:remote-method="remoteMethodServer"
:loading="loading"
>
<el-option
v-for="item in serverNameList"
:key="item.id"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
<div class="flex items-center justify-end">
<el-button type="text" @click="" class="text-[#323335]">
重置
</el-button>
<el-button
type="primary"
size="small"
class="rounded-[4px] h-[24px] py-[5px] px-[12px]"
@click="onSubmit"
>
查询
</el-button>
</div>
</div>
<el-button
slot="reference"
class="shrink-0 !h-[32px] !w-[32px] ml-[8px] !p-[7px]"
>
<iconpark-icon
name="icon-shaixuan"
class="text-[16px] text-[#D6D9E0]"
></iconpark-icon>
</el-button>
</el-popover>
</div>
<div class="mt-[12px]">
<div
class="flex items-center p-[12px] cursor-pointer hover:bg-[#F5F6F7]"
v-for="item in tableList"
:key="item.role_id"
@click.prevent="checkedTag(item)"
>
<el-radio
class="w-[15px] mr-0"
:value="checkoutUser.role_id"
:label="item.role_id"
>{{ "" }}</el-radio
>
<div class="mx-[12px]">
<iconpark-icon
name="icon-shouqi"
class="text-[18px] text-[#B0B2B5]"
@click.stop="expandTag(item)"
></iconpark-icon>
</div>
<div class="flex-1">
<div class="text-[#323335] text-[16px] font-medium">
{{ item.username }}
</div>
<div class="text-[#6D7176] text-[12px] mt-[2px]">
区服/角色:{{ item.server_name }}-{{ item.role_name }}
</div>
</div>
<div>
<div class="text-[#B0B2B5] text-[12px]">充值金额</div>
<div class="text-[#6D7176] text-[13px] mt-[2px]">
{{ item.recharge_total }}
</div>
</div>
</div>
</div>
</div>
<div class="content">
<el-form ref="form" :model="form" label-position="top" :rules="rules" label-width="120px">
<el-form
ref="form"
:model="form"
label-position="top"
:rules="rules"
label-width="120px"
>
<div class="inputContent">
<el-form-item label="请输入w账号" prop="username">
<el-input v-model.trim="form.username" placeholder="请输入w账号" class="input-with-select">
<el-input
v-model.trim="form.username"
placeholder="请输入w账号"
class="input-with-select"
>
</el-input>
</el-form-item>
<el-form-item label="请输入主游戏名" prop="main_game_id">
<el-select v-model="form.main_game_id" filterable remote clearable reserve-keyword placeholder="请输入主游戏名"
style="width: 100%;" :remote-method="remoteMethod" :loading="loading" @focus="gameNameList = optionsList">
<el-option v-for="item in gameNameList" :key="item.value" :label="item.label" :value="item.value">
<el-select
v-model="form.main_game_id"
filterable
remote
clearable
reserve-keyword
placeholder="请输入主游戏名"
style="width: 100%"
:remote-method="remoteMethod"
:loading="loading"
@focus="gameNameList = optionsList"
>
<el-option
v-for="item in gameNameList"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="请输入区服" prop="server_info">
<el-select v-model.trim="form.server_info" filterable remote :disabled="form.main_game_id == ''" clearable
style="width: 100%;" reserve-keyword placeholder="请先选择主游戏" :remote-method="remoteMethodServer"
:loading="loading">
<el-option v-for="item in serverNameList" :key="item.id" :label="item.label" :value="item.value">
<el-select
v-model.trim="form.server_info"
filterable
remote
:disabled="form.main_game_id == ''"
clearable
style="width: 100%"
reserve-keyword
placeholder="请先选择主游戏"
:remote-method="remoteMethodServer"
:loading="loading"
>
<el-option
v-for="item in serverNameList"
:key="item.id"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="请输入角色名" prop="role_name">
<el-input v-model.trim="form.role_name" placeholder="请输入角色" class="input-with-select">
<el-input
v-model.trim="form.role_name"
placeholder="请输入角色"
class="input-with-select"
>
</el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" size="small" @click="onSubmit">搜索</el-button>
<el-button type="primary" size="small" @click="onSubmit"
>搜索</el-button
>
</el-form-item>
</div>
</el-form>
<div class="table account_table">
<div class="bind-account-title">
账号列表
</div>
<!-- <div class="table account_table">
<div class="bind-account-title">账号列表</div>
<userTable :list="tableList" @checkedTag="checkedTag" />
</div>
</div> -->
<!-- <div class="line"></div> w92865226508-->
<div v-if="userDetails.username" class="account_select_userInfo">
<div class="bind-account-title" style="margin-top: 20px;">
账号详情
<div class="bind-account-title" style="margin-top: 20px">账号详情</div>
<div class="item rowFlex columnCenter">
<span class="label">账号</span>
<p class="text">{{ userDetails.username }}</p>
<span v-if="userDetails.account_type == 2" class="account_type"
></span
>
</div>
<div class="item rowFlex columnCenter"><span class="label">账号</span>
<p class="text">{{ userDetails.username }}</p> <span v-if="userDetails.account_type == 2"
class="account_type"></span>
</div>
<div class="item rowFlex columnCenter"><span class="label">获客渠道</span>
<div class="item rowFlex columnCenter">
<span class="label">获客渠道</span>
<p class="text">{{ userDetails.channel_name }}</p>
</div>
<div class="item rowFlex columnCenter"><span class="label">注册渠道</span>
<div class="item rowFlex columnCenter">
<span class="label">注册渠道</span>
<p class="text">{{ userDetails.register_channel_name }}</p>
</div>
<div class="item rowFlex columnCenter"><span class="label">运营渠道</span>
<div class="item rowFlex columnCenter">
<span class="label">运营渠道</span>
<p class="text">{{ userDetails.operator_channel_name }}</p>
</div>
<div class="item rowFlex columnCenter"><span class="label">注册游戏</span>
<div class="item rowFlex columnCenter">
<span class="label">注册游戏</span>
<p class="text">{{ userDetails.reg_game_name }}</p>
</div>
<div class="item rowFlex columnCenter"><span class="label">主游戏</span>
<div class="item rowFlex columnCenter">
<span class="label">主游戏</span>
<p class="text">{{ userDetails.main_game_name }}</p>
</div>
<div class="item rowFlex columnCenter"><span class="label">真实姓名</span>
<div class="item rowFlex columnCenter">
<span class="label">真实姓名</span>
<p class="text">{{ userDetails.real_name }}</p>
</div>
<div class="item rowFlex columnCenter"><span class="label">手机号</span>
<div class="item rowFlex columnCenter">
<span class="label">手机号</span>
<p class="text">{{ userDetails.mobile }}</p>
</div>
<div class="item rowFlex columnCenter"><span class="label">染色时间</span>
<p class="text">{{ moment(userDetails.seq_time * 1000).format('YYYY-MM-DD') }}</p>
<div class="item rowFlex columnCenter">
<span class="label">染色时间</span>
<p class="text">
{{ moment(userDetails.seq_time * 1000).format("YYYY-MM-DD") }}
</p>
</div>
<div class="item rowFlex columnCenter"><span class="label">注册时间</span>
<p class="text">{{ moment(userDetails.reg_time * 1000).format('YYYY-MM-DD') }}</p>
<div class="item rowFlex columnCenter">
<span class="label">注册时间</span>
<p class="text">
{{ moment(userDetails.reg_time * 1000).format("YYYY-MM-DD") }}
</p>
</div>
<div class="item rowFlex columnCenter"><span class="label">登录系统</span>
<div class="item rowFlex columnCenter">
<span class="label">登录系统</span>
<p class="text">{{ userDetails.last_login_os }}</p>
</div>
<div class="item rowFlex columnCenter"><span class="label">充值金额</span>
<div class="item rowFlex columnCenter">
<span class="label">充值金额</span>
<p class="text">{{ userDetails.recharge_total }}</p>
</div>
<div class="item rowFlex columnCenter"><span class="label">是否添加微信</span>
<div class="item rowFlex columnCenter">
<span class="label">是否添加微信</span>
<p class="text">{{ userDetails.wechat_add_status_text }}</p>
</div>
</div>
</div>
<page class="pageInfo" :page-info="pageInfo" @requestNextPage="requestNextPage" />
<span class="dialog-footer rowFlex">
<el-button class="btn" type="primary" size="small" :disabled="!userDetails.id" @click="confirmSubmit">
</el-button>
<page
class="pageInfo"
:page-info="pageInfo"
@requestNextPage="requestNextPage"
/>
<!-- <span class="dialog-footer rowFlex">
<el-button
class="btn"
type="primary"
size="small"
:disabled="!userDetails.id"
@click="confirmSubmit"
>确 定</el-button
>
<el-button class="btn" size="small" @click="close">取 消</el-button>
</span>
</el-drawer>
</span> -->
</Drawer>
</template>
<script type="text/javascript">
import moment from 'moment'
import userTable from './userTable.vue'
import { getRoleHoLo, memberView, selectSearch } from '@/api/game'
import { checkZyouBind,zyouBind } from '@/api/works'
import { mapMutations, mapActions, mapState } from 'vuex'
import page from '@/components/page/pageNum.vue'
export default {
name: 'addUser',
import moment from "moment";
import userTable from "./userTable.vue";
import { getRoleHoLo, memberView, selectSearch } from "@/api/game";
import { checkZyouBind, zyouBind } from "@/api/works";
import { mapMutations, mapActions, mapState } from "vuex";
import page from "@/components/page/pageNum.vue";
import Drawer from "@/components/common/Drawer.vue";
import { debounce } from "@/utils/index";
export default {
name: "addUser",
components: {
userTable,
page
page,
Drawer,
},
props: ['show'],
props: ["show"],
data() {
return {
moment,
inputValue: "",
tableList: [],
checkoutUser: {},
userDetails: {},
......@@ -117,221 +314,246 @@
pageInfo: {
page: 1,
page_size: 20,
total: 0
total: 0,
},
form: {
member_id: '',
username: '',
role_name: '',
main_game_id: '',
server_info: ''
member_id: "",
username: "",
role_name: "",
main_game_id: "",
server_info: "",
},
gameNameList: [],
optionsList: [],
serverNameList: [],
rules: {
}
}
rules: {},
};
},
computed: {
...mapState('game', ['chatUserInfo','userid','external_userid']),
...mapState("game", ["chatUserInfo", "userid", "external_userid"]),
},
watch: {
show(newVal, oldVal) {
if (newVal) {
// this.requestRoleList()
this.requestGameList()
}
this.requestGameList();
}
},
mounted() {
},
mounted() {},
methods: {
...mapActions('game', ['gameBindUser']),
...mapMutations('game', ['set_accountSelect']),
...mapActions("game", ["gameBindUser"]),
...mapMutations("game", ["set_accountSelect"]),
requestRoleList() {
const data = {
member_id: this.form.member_id,
username: this.form.username.trim(),
role_name: this.form.role_name.trim(),
main_game_id: this.form.main_game_id !== '' ? [this.form.main_game_id] : [],
server_info: this.form.server_info !== '' ? [this.form.server_info] : [],
search_type: 'bind',
...this.pageInfo
}
getRoleHoLo(data).then(res => {
main_game_id:
this.form.main_game_id !== "" ? [this.form.main_game_id] : [],
server_info:
this.form.server_info !== "" ? [this.form.server_info] : [],
search_type: "bind",
...this.pageInfo,
};
getRoleHoLo(data).then((res) => {
if (res.status_code == 1) {
if (res.data.data.length == 0) {
this.tableList = []
this.$message.warning('暂无数据')
this.tableList = [];
this.$message.warning("暂无数据");
} else {
this.tableList = res.data.data
this.pageInfo = res.data.page_info
this.tableList = res.data.data;
this.pageInfo = res.data.page_info;
}
}
})
});
},
// S181.啊呸¤可瑞 八荒181服
// 分页
requestNextPage(pageInfo) {
this.pageInfo.page = pageInfo.page
this.requestRoleList()
this.pageInfo.page = pageInfo.page;
this.requestRoleList();
},
remoteMethodServer(query) {
if (query !== '') {
this.loading = true
if (query !== "") {
this.loading = true;
const data = {
type: 'server_info',
type: "server_info",
value: query,
main_game_ids: this.form.main_game_id
}
selectSearch(data).then(res => {
this.loading = false
main_game_ids: this.form.main_game_id,
};
selectSearch(data).then((res) => {
this.loading = false;
if (res.status_code == 1) {
this.serverNameList = res.data.data
this.serverNameList = res.data.data;
}
})
});
}
},
remoteMethod(query) {
if (query !== '') {
this.gameNameList = this.optionsList.filter(item => {
return item.label.toLowerCase()
.indexOf(query.toLowerCase()) > -1
})
if (query !== "") {
this.gameNameList = this.optionsList.filter((item) => {
return item.label.toLowerCase().indexOf(query.toLowerCase()) > -1;
});
} else {
this.gameNameList = []
this.gameNameList = [];
}
},
requestGameList() {
const data = {
type: 'mainGameList',
value: '',
weixin_blong_id: ''
}
selectSearch(data).then(res => {
this.loading = false
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
this.gameNameList = this.optionsList = res.data.data;
}
})
});
},
close() {
this.$emit('update:show', false)
this.resizeData()
this.$emit('close')
this.$emit("update:show", false);
this.resizeData();
this.$emit("close");
},
// 防抖处理输入变化,300毫秒延迟
handleChange: debounce(function () {
if (this.inputValue == "") {
return;
}
this.onSubmit();
}, 300),
onSubmit() {
this.$refs.form.validate((valid) => {
this.pageInfo = {
page: 1,
page_size: 20,
total: 0
}
total: 0,
};
if (valid) {
if (this.form.role_name == '' && this.form.username == '') {
this.$message.warning('请输入角色名或者w账号')
return
if (this.inputValue == "") {
this.$message.warning("请输入角色名或者w账号");
return;
}
// 正则表达式:以w开头,后面全是数字为username,否则为role_name
if (/^w\d+$/.test(this.inputValue)) {
this.form.username = this.inputValue;
this.form.role_name = "";
} else {
this.form.role_name = this.inputValue;
this.form.username = "";
}
this.requestRoleList()
this.requestRoleList();
} else {
console.log('error submit!!')
return false
console.log("error submit!!");
return false;
}
})
});
},
expandTag(item) {
console.log(item);
},
resizeData() {
this.form = {
member_id: '',
username: '',
role_name: '',
main_game_id: '',
server_info: ''
}
this.tableList = []
this.checkoutUser = {}
this.userDetails = {}
member_id: "",
username: "",
role_name: "",
main_game_id: "",
server_info: "",
};
this.inputValue = "";
this.tableList = [];
this.checkoutUser = {};
this.userDetails = {};
},
confirmSubmit() {
const data = {
member_id: this.userDetails.id && this.userDetails.id != '' ? this.userDetails.id : this.checkoutUser.member_id,
username: this.userDetails.username
}
checkZyouBind(data).then(res => {
console.log(data)
member_id:
this.userDetails.id && this.userDetails.id != ""
? this.userDetails.id
: this.checkoutUser.member_id,
username: this.userDetails.username,
};
checkZyouBind(data).then((res) => {
console.log(data);
if (!res.data.has_bind) {
this.submit()
this.submit();
} else {
this.$confirm(res.data.tip || '', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
this.$confirm(res.data.tip || "", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
this.submit()
this.submit();
})
.catch((err) => {
console.log(err)
console.log(err);
this.$message({
type: 'info',
message: '已取消删除'
})
})
type: "info",
message: "已取消删除",
});
});
}
})
});
},
submit() {
const data = {
userid: this.chatUserInfo.userid || this.userid,
external_userid: this.chatUserInfo.external_userid || this.external_userid,
member_id: this.userDetails.id && this.userDetails.id != '' ? this.userDetails.id : this.checkoutUser.member_id,
external_userid:
this.chatUserInfo.external_userid || this.external_userid,
member_id:
this.userDetails.id && this.userDetails.id != ""
? this.userDetails.id
: this.checkoutUser.member_id,
username: this.userDetails.username,
reg_game_id: this.userDetails.reg_game_id,
main_game_id: this.userDetails.main_game_id,
recharge_total: this.userDetails.recharge_total,
}
};
// 绑定掌游账号
zyouBind(data).then(res => {
zyouBind(data).then((res) => {
if (res.status_code == 1) {
this.$message.success(res.msg)
this.updateData()
this.$message.success(res.msg);
this.updateData();
}
})
});
},
// 更新列表数据
updateData() {
const data = {
userid: this.chatUserInfo.userid,
external_userid: this.chatUserInfo.external_userid
}
this.gameBindUser(data).then(res => {
this.set_accountSelect(this.userDetails.id)
this.close()
})
external_userid: this.chatUserInfo.external_userid,
};
this.gameBindUser(data).then((res) => {
this.set_accountSelect(this.userDetails.id);
this.close();
});
},
// 勾选活码
checkedTag(value) {
this.checkoutUser = value
console.log(1);
this.checkoutUser = value;
const data = {
member_id: value.member_id,
need_channel: 1,
need_roleInfo: 1
}
this.rquestUserInfo(data)
need_roleInfo: 1,
};
this.rquestUserInfo(data);
},
rquestUserInfo(data) {
memberView(data).then(res => {
memberView(data).then((res) => {
if (res.status_code == 1) {
this.userDetails = res.data
this.userDetails = res.data;
}
})
}
}
}
</script>
});
},
},
};
</script>
<style lang="scss" scoped>
::v-deep .el-drawer {
......@@ -410,7 +632,6 @@
}
}
}
}
.account_table {
......@@ -429,7 +650,7 @@
}
.pageInfo {
width: calc(100% - 20px);
width: 100%;
height: 82px;
position: absolute;
right: 20px;
......@@ -438,7 +659,7 @@
}
.dialog-footer {
width: calc(100% - 20px);
width: 100%;
position: absolute;
right: 20px;
bottom: 0;
......@@ -454,9 +675,26 @@
height: 32px;
}
}
</style>
<style>
::v-deep .el-select-dropdown {
min-width: 210px !important;
::v-deep .el-input-group--prepend .el-input__inner {
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
.custom-input {
::v-deep .el-input {
position: relative;
}
::v-deep .el-input__inner {
padding-left: 34px;
}
::v-deep .el-input-group__prepend {
background-color: transparent;
padding: 0;
border: none;
position: absolute;
left: 12px;
top: 50%;
transform: translate(0, -50%);
}
}
</style>
<template>
<div class="bindUserList rowFlex columnCenter">
<div class="bindUserList rowFlex columnCenter !pt-0 !px-[10px]">
<div class="select">
<el-select
v-model="bindAccount"
placeholder="请选择关联账号"
:clearable="false"
class="w-[258px]"
:class="{ 'show-number': bindGameUserList.length > 0 }"
:style="{ '--number': `'${bindGameUserList.length}'` }"
@change="handleChange"
>
<el-option label="新增关联账号" value="add" @click="addNewUser">
</el-option>
<!-- <el-option label="新增关联账号" value="add" @click="addNewUser">
</el-option> -->
<el-option
v-for="(item, index) in bindGameUserList"
:key="index"
......@@ -34,9 +37,15 @@
</el-option>
</el-select>
</div>
<p v-if="bindGameUserList.length > 0" class="num">
<!-- <p v-if="bindGameUserList.length > 0" class="num">
总共{{ bindGameUserList.length }}个账号
</p>
</p> -->
<el-button
icon="el-icon-plus "
size="small"
class="!h-[32px] ml-[8px] !w-[32px] text-[16px] flex items-center justify-center"
@click="addNewUser"
></el-button>
<addUser
:show.sync="showLayer"
title="选择玩家"
......@@ -102,11 +111,7 @@ export default {
...mapMutations("user", ["set_avatar"]),
...mapActions("game", ["gameBindUser"]),
handleChange(value) {
if (value == "add") {
this.showLayer = true;
} else {
this.set_accountSelect(value);
}
},
close() {
this.bindAccount = this.accountSelect;
......@@ -137,7 +142,7 @@ export default {
}
},
addNewUser() {
console.log(11);
this.showLayer = true;
},
async requestDetails() {
const data = {
......@@ -186,53 +191,24 @@ export default {
</script>
<style lang="scss" scoped>
.bindUserList {
margin: 10px;
.select {
::v-deep .el-input--small .el-input__inner {
border-radius: 4px;
border: 1px solid #e4e7ed;
min-width: 200px;
height: 32px;
line-height: 32px;
background-color: #e8f7ff;
color: #3491fa;
font-size: 14px;
&:hover,
&:focus {
border-color: #3491fa;
}
}
::v-deep .el-input__suffix {
color: #3491fa;
}
::v-deep .el-select-dropdown__item.selected {
color: #3491fa;
}
}
.num {
.show-number ::v-deep .el-input {
position: relative;
&:after {
display: flex;
justify-content: center;
align-items: center;
content: var(--number);
height: 20px;
width: 20px;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 600;
margin-left: 10px;
white-space: nowrap;
color: #f53f3f;
}
color: #267ef0;
background: #e7f1fd;
border-radius: 50%;
::v-deep .el-button--danger {
background-color: #f56c6c;
border-color: #f56c6c;
&:hover,
&:focus {
background-color: #f78989;
border-color: #f78989;
}
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 30px;
}
}
</style>
<template>
<div class="skillLibrary">
<div v-loading="loading" class="rowFlex skillBox">
<div v-loading="loading" class="rowFlex skillBox pl-[10px]">
<!-- 标签 -->
<el-collapse-transition>
<div v-if="groupList.length > 0" class="tagList columnFlex">
<div v-for="(item, index) in groupList" :key="index" class="tagItem columnCenter" :draggable="false"
<div
v-if="groupList.length > 0"
class="tagList columnFlex overflow-y-auto"
>
<div
v-for="(item, index) in groupList"
:key="index"
class="tagItem columnCenter"
:draggable="false"
:class="groupActive == item.value ? 'tagItemActiveText' : ''"
@dragstart="handleDragStart($event, item, index)" @dragover.prevent="handleDragOver($event, item)"
@dragenter="handleDragEnter($event, item, 'group')" @dragend="handleDragEnd($event, item, 'group')">
<div class="rowFlex columnCenter spaceBetween tagItemGroup" @click="groupFilter(item, index)">
@dragstart="handleDragStart($event, item, index)"
@dragover.prevent="handleDragOver($event, item)"
@dragenter="handleDragEnter($event, item, 'group')"
@dragend="handleDragEnd($event, item, 'group')"
>
<div
class="rowFlex columnCenter spaceBetween tagItemGroup"
@click="groupFilter(item, index)"
>
<div class="rowFlex columnCenter">
<el-tooltip effect="dark" placement="top" :content="item.name" v-if="item.name.length >= 6">
<el-tooltip
effect="dark"
placement="top"
:content="item.name"
v-if="item.name.length >= 6"
>
<p class="text hidden">{{ item.name }}</p>
</el-tooltip>
<p v-else class="text hidden">{{ item.name }}</p>
</div>
<i class="el-icon-caret-right rotageIcon" :class="groupActive == item.value ? 'rotage' : ''"></i>
<i
class="el-icon-caret-right rotageIcon"
:class="groupActive == item.value ? 'rotage' : ''"
></i>
</div>
<!-- 二级分组 -->
<div v-if="item.child.length > 0 && groupActive == item.value" class="childGroup">
<div v-for="child in item.child" :key="child._id" class="childGroupText"
:class="[groupActiveChild == child._id ? 'tagItemActive' : '']" @click.stop="groupFilterChild(child)">
<div
v-if="item.child.length > 0 && groupActive == item.value"
class="childGroup"
>
<div
v-for="child in item.child"
:key="child._id"
class="childGroupText"
:class="[groupActiveChild == child._id ? 'tagItemActive' : '']"
@click.stop="groupFilterChild(child)"
>
<p class="text hidden">{{ child.name }}</p>
</div>
</div>
......@@ -33,27 +62,67 @@
<!-- 话术 -->
<div class="libraryListContent">
<div class="inputContent">
<el-input v-model="requestData.title" placeholder="请输入话术内容" class="input-with-select">
<el-button slot="append" icon="el-icon-search" @click="contentSearch"></el-button>
<el-input
v-model="requestData.title"
placeholder="请输入话术内容"
class="input-with-select"
>
<el-button
slot="append"
icon="el-icon-search"
@click="contentSearch"
></el-button>
</el-input>
</div>
<div ref="skillLibrary" v-loading="skillLoading" @scroll="paperScroll" class="scrollList">
<div v-for="(items, indexs) in groupDataList" :key="indexs" class="answerContent">
<div class="question"><span class="title">Q:</span>{{ items.question }}</div>
<div v-for="(answer, answerIndex) in items.answer" :key="answerIndex" class="answerItem"
style="width: 100%">
<div
ref="skillLibrary"
v-loading="skillLoading"
@scroll="paperScroll"
class="scrollList"
>
<div
v-for="(items, indexs) in groupDataList"
:key="indexs"
class="answerContent"
>
<div class="question">
<span class="title">Q:</span>{{ items.question }}
</div>
<div
v-for="(answer, answerIndex) in items.answer"
:key="answerIndex"
class="answerItem"
style="width: 100%"
>
<!-- <span class="question">{{ answerIndex + 1 }}: {{ answer }}</span> -->
<div v-if="answer.msgtype == 'text'" class="answerText rowFlex spaceBetween">
<div
v-if="answer.msgtype == 'text'"
class="answerText rowFlex spaceBetween"
>
<span class="title rowFlex">A{{ answerIndex + 1 }}:</span>
<p v-if="answer.msgtype == 'text'" class="rowFlex textAnswer flex1">
{{ answer.text.content || '' }}
<p
v-if="answer.msgtype == 'text'"
class="rowFlex textAnswer flex1 break-all"
>
{{ answer.text.content || "" }}
</p>
<i class="el-icon-document-copy copyIcon rowFlex" @click="sendMessageEdit(answer, items._id)"></i>
<i
class="el-icon-document-copy copyIcon rowFlex"
@click="sendMessageEdit(answer, items._id)"
></i>
</div>
<div v-else-if="answer.msgtype == 'image'" class="answerText rowFlex">
<div
v-else-if="answer.msgtype == 'image'"
class="answerText rowFlex"
>
<span class="title rowFlex">A{{ answerIndex + 1 }}:</span>
<el-image style="max-width: 200px" :src="answer.image.picurl"
@click="sendMessageImage(answer, items._id)" :preview-src-list="[answer.image.picurl]"> </el-image>
<el-image
style="max-width: 200px"
:src="answer.image.picurl"
@click="sendMessageImage(answer, items._id)"
:preview-src-list="[answer.image.picurl]"
>
</el-image>
</div>
</div>
</div>
......@@ -65,26 +134,34 @@
<script>
// procedure_group, procedureList, procedureSort, procedureGroupSort, skillQuote,
import { cross_corp_robot_knowledge_group_index, cross_corp_robot_knowledge_group_getList } from '@/api/skill'
import { mapState, mapMutations, mapActions } from 'vuex'
import { throttle, debounce, copyToClipboard, sendChatMessage } from '@/utils/index'
import noContent from '@/components/noContent.vue'
import {
cross_corp_robot_knowledge_group_index,
cross_corp_robot_knowledge_group_getList,
} from "@/api/skill";
import { mapState, mapMutations, mapActions } from "vuex";
import {
throttle,
debounce,
copyToClipboard,
sendChatMessage,
} from "@/utils/index";
import noContent from "@/components/noContent.vue";
export default {
name: 'skillLibrary',
name: "skillLibrary",
components: {
noContent
noContent,
},
props: {
activeName: {
default: '',
type: String
}
default: "",
type: String,
},
},
data() {
return {
collapseActive: '',
groupActive: '0',
groupActiveChild: '0',
collapseActive: "",
groupActive: "0",
groupActiveChild: "0",
activeGroup: {},
groupList: [],
groupLastList: [],
......@@ -93,93 +170,93 @@ export default {
pageInfo: {
page: 1,
page_size: 20,
total: 0
total: 0,
},
skillLoading: false,
loading: false,
requestData: {
title: '',
first_group_id: '',
second_group_id: ''
title: "",
first_group_id: "",
second_group_id: "",
},
sortType: '',
sortType: "",
sortID: {
_id: '',
before_id: '',
after_id: ''
_id: "",
before_id: "",
after_id: "",
},
filterText: {},
dragging: null,
orderList: [
{ label: '知识库', type: 'library' },
{ label: '个人话术', type: 'personal' },
{ label: '企业话术', type: 'company' }
]
}
{ label: "知识库", type: "library" },
{ label: "个人话术", type: "personal" },
{ label: "企业话术", type: "company" },
],
};
},
computed: {
...mapState('game', ['accountSelect', 'chatUserInfo']),
...mapState("game", ["accountSelect", "chatUserInfo"]),
},
watch: {
accountSelect(newVal, oldVal) {
if (newVal && newVal !== '') {
if (newVal && newVal !== "") {
this.pageInfo = {
page: 1,
page_size: 20,
total: 0
}
total: 0,
};
}
},
activeName(newVal, oldVal) {
if (newVal == 'library' && newVal != oldVal) {
this.resizeSelect()
this.requestLibraryData()
}
if (newVal == "library" && newVal != oldVal) {
this.resizeSelect();
this.requestLibraryData();
}
},
},
mounted() {
this.requestLibraryData()
this.requestLibraryData();
},
methods: {
sendMessage: throttle(function (item, id) {
console.log(item, id)
console.log(item, id);
// this.skillQuote(id, item.length)
}, 500),
handleDragStart(e, item, index) {
this.sortID._id = item._id
this.dragging = item
this.sortID._id = item._id;
this.dragging = item;
},
paperScroll: debounce(function () {
const el = this.$refs.skillLibrary
const el = this.$refs.skillLibrary;
if (el.offsetHeight + el.scrollTop + 10 >= el.scrollHeight) {
console.log('下一页')
this.pageInfo.page++
this.searchTable()
console.log("下一页");
this.pageInfo.page++;
this.searchTable();
}
}, 500),
skillQuote(id, num) {
const data = {
type: this.activeName,
procedure_id: id,
quote_count: num || 1
}
quote_count: num || 1,
};
skillQuote(data).then((res) => {
console.log(res)
})
console.log(res);
});
},
sortSkill() {
procedureSort(this.sortID).then((res) => {
if (res.status_code == 1) {
this.$message.success(res.msg)
this.$message.success(res.msg);
}
})
});
},
sortSkillGroup() {
procedureGroupSort(this.sortID).then((res) => {
if (res.status_code == 1) {
this.$message.success(res.msg)
this.$message.success(res.msg);
}
})
});
},
// 发送语音的时候 先编辑再发送
sendMessageEdit(item, id) {
......@@ -189,98 +266,107 @@ export default {
item.text.content,
(message) => this.$message.success(message),
(message) => this.$message.error(message)
)
);
}
this.sendChatMessage(item.text.content || '', 'text')
this.sendChatMessage(item.text.content || "", "text");
},
sendMessageImage(item) {
console.log(item, 'item')
this.sendChatMessage(item.image.picurl || '', 'image')
console.log(item, "item");
this.sendChatMessage(item.image.picurl || "", "image");
},
contentSearch() {
this.pageInfo = {
page: 1,
page_size: 20,
total: 0
}
this.searchTable('msg')
total: 0,
};
this.searchTable("msg");
},
// 知识库话术
requestLibraryData() {
console.log(this.chatUserInfo, 'chatUserInfo')
this.loading = true
console.log(this.chatUserInfo, "chatUserInfo");
this.loading = true;
const data = {
page: 1,
page_size: 100,
userid: this.chatUserInfo.userid
}
userid: this.chatUserInfo.userid,
};
cross_corp_robot_knowledge_group_index(data).then((res) => {
this.loading = false
this.loading = false;
if (res.data.data) {
res.data.data.unshift({
name: '全部分组',
value: '',
child: []
})
name: "全部分组",
value: "",
child: [],
});
this.groupList = res.data.data.map((item, index) => {
item.label = item.name
item.value = item._id
return item
})
this.groupLastList = this.groupList
this.groupFilter(this.groupList[0])
item.label = item.name;
item.value = item._id;
return item;
});
this.groupLastList = this.groupList;
this.groupFilter(this.groupList[0]);
} else {
this.groupList = []
this.groupLastList = []
this.groupList = [];
this.groupLastList = [];
}
})
});
},
groupFilter(item, index) {
if (!item._id) {
this.requestData.second_group_id = ''
this.activeGroup = {}
}
this.groupActive = item.value
item.child && item.child[0] ? ((this.activeGroup = item.child[0]), (this.groupActiveChild = item.child[0]._id)) : ''
this.searchTable()
this.requestData.second_group_id = "";
this.activeGroup = {};
}
this.groupActive = item.value;
item.child && item.child[0]
? ((this.activeGroup = item.child[0]),
(this.groupActiveChild = item.child[0]._id))
: "";
this.searchTable();
},
groupFilterChild(child) {
this.groupActiveChild = 0
this.activeGroup = child
this.groupActiveChild = child._id
this.searchTable()
this.$forceUpdate()
this.groupActiveChild = 0;
this.activeGroup = child;
this.groupActiveChild = child._id;
this.searchTable();
this.$forceUpdate();
},
// 搜索结果
async searchTable(msg) {
this.skillLoading = true
this.requestData.second_group_id = this.activeGroup._id || ''
this.requestData.title = this.requestData.title.trim()
const data = { ...this.requestData, ...this.pageInfo, log_scan: msg ? 1 : 0, userid: this.chatUserInfo.userid }
this.skillLoading = true;
this.requestData.second_group_id = this.activeGroup._id || "";
this.requestData.title = this.requestData.title.trim();
const data = {
...this.requestData,
...this.pageInfo,
log_scan: msg ? 1 : 0,
userid: this.chatUserInfo.userid,
};
cross_corp_robot_knowledge_group_getList(data).then((res) => {
this.skillLoading = false
this.pageInfo.page === 1 ? this.groupDataList = res.data.data : this.groupDataList = this.groupDataList.concat(res.data.data)
this.groupLastDataList = this.groupDataList
})
this.skillLoading = false;
this.pageInfo.page === 1
? (this.groupDataList = res.data.data)
: (this.groupDataList = this.groupDataList.concat(res.data.data));
this.groupLastDataList = this.groupDataList;
});
},
handleChange() { },
handleChange() {},
// 重置select
resizeSelect() {
this.groupActive = '0'
this.isResize = true
this.groupDataList = []
this.requestData.content = ''
this.pageInfo.page = 1
this.groupActive = "0";
this.isResize = true;
this.groupDataList = [];
this.requestData.content = "";
this.pageInfo.page = 1;
setTimeout(() => {
this.isResize = false
}, 2000)
this.isResize = false;
}, 2000);
},
sendChatMessage(content, type) {
sendChatMessage(content, type)
sendChatMessage(content, type);
},
}
}
},
};
</script>
<style lang="scss" scoped>
.skillLibrary {
......@@ -321,7 +407,7 @@ export default {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #409EFF;
color: #409eff;
margin-right: 10px;
}
......@@ -457,8 +543,8 @@ export default {
.inputContent {
width: 100%;
margin-bottom: 20px;
margin-left: 20px;
margin-left: 10px;
margin-right: 10px;
::v-deep .el-input {
width: 90%;
}
......@@ -467,7 +553,6 @@ export default {
.skillBox {
width: 100%;
height: calc(100% - 20px);
}
.tagList {
......@@ -513,14 +598,14 @@ export default {
}
.tagItemActive {
color: #409EFF !important;
color: #409eff !important;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
background: #e4fff1;
}
.tagItemActiveText {
color: #409EFF;
color: #409eff;
}
}
......@@ -555,7 +640,7 @@ export default {
.scrollList {
width: 100%;
height: 100%;
padding-left: 20px;
padding-left: 10px;
.answerContent {
width: 100%;
......@@ -607,7 +692,7 @@ export default {
.copyIcon {
width: 20px;
color: #409EFF;
color: #409eff;
font-size: 16px;
position: relative;
top: 2px;
......@@ -619,7 +704,7 @@ export default {
}
.scrollList::-webkit-scrollbar {
display: none
display: none;
}
.container {
......@@ -676,7 +761,7 @@ export default {
}
.skillLibrary::-webkit-scrollbar {
display: none
display: none;
}
::v-deep .el-icon-circle-close {
......
<template>
<div class="skillTab">
<div class="inputContent">
<el-input v-model="requestData.content" placeholder="请输入话术内容" class="input-with-select" @change="contentSearch">
<el-input
v-model="requestData.content"
placeholder="请输入话术内容"
class="input-with-select"
@change="contentSearch"
>
<el-button slot="append" icon="el-icon-search"></el-button>
</el-input>
</div>
<div v-loading="loading" class="rowFlex skillBox">
<div v-loading="loading" class="rowFlex skillBox pl-[10px]">
<!-- 标签 -->
<el-collapse-transition>
<div v-if="groupList.length > 0" class="tagList columnFlex">
<div v-for="(item, index) in groupList" :key="index" class="tagItem rowFlex columnCenter"
<div
v-for="(item, index) in groupList"
:key="index"
class="tagItem rowFlex columnCenter"
:draggable="activeName == 'personal' ? true : false"
:class="groupActive == item.value ? 'tagItemActive' : ''" @dragstart="handleDragStart($event, item, index)"
@dragover.prevent="handleDragOver($event, item)" @dragenter="handleDragEnter($event, item, 'group')"
@dragend="handleDragEnd($event, item, 'group')">
<el-tooltip effect="dark" placement="top" :content="item.group_name" v-if="item.group_name.length >= 6">
<p class="text hidden" @click="groupFilter(item, index)">{{ item.group_name }}</p>
:class="groupActive == item.value ? 'tagItemActive' : ''"
@dragstart="handleDragStart($event, item, index)"
@dragover.prevent="handleDragOver($event, item)"
@dragenter="handleDragEnter($event, item, 'group')"
@dragend="handleDragEnd($event, item, 'group')"
>
<el-tooltip
effect="dark"
placement="top"
:content="item.group_name"
v-if="item.group_name.length >= 6"
>
<p class="text hidden" @click="groupFilter(item, index)">
{{ item.group_name }}
</p>
</el-tooltip>
<p v-else class="text hidden" @click="groupFilter(item, index)">{{ item.group_name }}</p>
<p v-else class="text hidden" @click="groupFilter(item, index)">
{{ item.group_name }}
</p>
</div>
</div>
<div v-else>暂无话术内容</div>
</el-collapse-transition>
<!-- 话术 -->
<div v-loading="skillLoading" class="scrollList">
<div v-loading="skillLoading" class="scrollList px-[10px]">
<el-collapse v-model="collapseActive" @change="handleChange">
<transition-group v-if="groupDataList.length > 0" tag="div" class="container">
<div v-for="(items, indexs) in groupDataList" :key="indexs"
:draggable="activeName == 'personal' ? true : false" class="draggable"
@dragstart="handleDragStart($event, items, indexs)" @dragover.prevent="handleDragOver($event, items)"
@dragenter="handleDragEnter($event, items, 'item')" @dragend="handleDragEnd($event, items, 'item')">
<transition-group
v-if="groupDataList.length > 0"
tag="div"
class="container"
>
<div
v-for="(items, indexs) in groupDataList"
:key="indexs"
:draggable="activeName == 'personal' ? true : false"
class="draggable"
@dragstart="handleDragStart($event, items, indexs)"
@dragover.prevent="handleDragOver($event, items)"
@dragenter="handleDragEnter($event, items, 'item')"
@dragend="handleDragEnd($event, items, 'item')"
>
<el-popover placement="top" width="300" trigger="hover">
<p>{{ items.title }}</p>
<div slot="reference" class="contentItemTitle allCenter"
:style="{ top: items.title.length > 8 ? '5px' : '13px' }">{{ items.title }}</div>
<div
slot="reference"
class="contentItemTitle allCenter"
:style="{ top: items.title.length > 8 ? '5px' : '13px' }"
>
{{ items.title }}
</div>
</el-popover>
<div class="rowFlex titleFixed columnCenter">
<div class="num">{{ items.message && items.message.attachments && items.message.attachments.length > 1 ?
`+${items.message.attachments.length - 1}条` : '' }}</div>
<div class="num">
{{
items.message &&
items.message.attachments &&
items.message.attachments.length > 1
? `+${items.message.attachments.length - 1}条`
: ""
}}
</div>
</div>
<el-collapse-item title="" :name="items._id" class="contentItem">
<div v-for="(i, j) in items.message.attachments" :key="j">
<div>
<div v-if="i.msgtype == 'text'" class="contentItemDetails rowFlex spaceBetween columnCenter">
<div
v-if="i.msgtype == 'text'"
class="contentItemDetails rowFlex spaceBetween columnCenter"
>
<div class="text">{{ i.text.content }}</div>
<el-button class="sendButton rowFlex allCenter"
@click.stop="sendMessageEdit(i, items._id)">发送</el-button>
<el-button
class="sendButton rowFlex allCenter"
@click.stop="sendMessageEdit(i, items._id)"
>发送</el-button
>
</div>
<div v-if="i.msgtype == 'image'" class="contentItemDetails rowFlex spaceBetween columnCenter">
<el-image class="image" :src="i.image.picurl" :preview-src-list="[i.image.picurl]"
fit="contain"></el-image>
<el-button class="sendButton rowFlex allCenter"
@click.stop="sendMessageEdit(i, items._id)">发送</el-button>
<div
v-if="i.msgtype == 'image'"
class="contentItemDetails rowFlex spaceBetween columnCenter"
>
<el-image
class="image"
:src="i.image.picurl"
:preview-src-list="[i.image.picurl]"
fit="contain"
></el-image>
<el-button
class="sendButton rowFlex allCenter"
@click.stop="sendMessageEdit(i, items._id)"
>发送</el-button
>
</div>
</div>
</div>
......@@ -67,23 +124,29 @@
</div>
</template>
<script>
import { procedure_group, procedureList, procedureSort, procedureGroupSort, skillQuote } from '@/api/skill'
import { mapState, mapMutations, mapActions } from 'vuex'
import { throttle, copyToClipboard } from '@/utils/index'
import { getMediaId } from '@/api/works'
import {
procedure_group,
procedureList,
procedureSort,
procedureGroupSort,
skillQuote,
} from "@/api/skill";
import { mapState, mapMutations, mapActions } from "vuex";
import { throttle, copyToClipboard } from "@/utils/index";
import { getMediaId } from "@/api/works";
export default {
name: 'skillCompany',
name: "skillCompany",
components: {},
props: {
activeName: {
default: '',
type: String
}
default: "",
type: String,
},
},
data() {
return {
collapseActive: '',
groupActive: '0',
collapseActive: "",
groupActive: "0",
activeGroup: {},
groupList: [],
groupLastList: [],
......@@ -92,282 +155,294 @@ export default {
pageInfo: {
page: 1,
page_size: 100,
total: 0
total: 0,
},
skillLoading: false,
loading: false,
requestData: {
content: '',
type: '',
procedure_group_id: ''
content: "",
type: "",
procedure_group_id: "",
},
sortType: '',
sortType: "",
sortID: {
_id: '',
before_id: '',
after_id: ''
_id: "",
before_id: "",
after_id: "",
},
filterText: {},
dragging: null,
orderList: [
{ label: '个人话术', type: 'personal' },
{ label: '企业话术', type: 'company' }
]
}
{ label: "个人话术", type: "personal" },
{ label: "企业话术", type: "company" },
],
};
},
computed: {
...mapState('game', ['accountSelect']),
...mapState("game", ["accountSelect"]),
},
watch: {
accountSelect(newVal, oldVal) {
if (newVal && newVal !== '') {
if (newVal && newVal !== "") {
this.pageInfo = {
page: 1,
page_size: 100,
total: 0
}
total: 0,
};
}
},
activeName(newVal, oldVal) {
if (newVal == 'company' && newVal != oldVal) {
this.resizeSelect()
this.requestGroup()
}
if (newVal == "company" && newVal != oldVal) {
this.resizeSelect();
this.requestGroup();
}
},
},
mounted() {
// this.requestGroup()
},
methods: {
handleDragStart(e, item, index) {
this.sortID._id = item._id
this.dragging = item
this.sortID._id = item._id;
this.dragging = item;
},
skillQuote(id, num) {
const data = {
type: this.activeName,
procedure_id: id,
quote_count: num || 1
}
quote_count: num || 1,
};
skillQuote(data).then((res) => {
console.log(res)
})
console.log(res);
});
},
sortSkill() {
procedureSort(this.sortID).then((res) => {
if (res.status_code == 1) {
this.$message.success(res.msg)
this.$message.success(res.msg);
}
})
});
},
sortSkillGroup() {
procedureGroupSort(this.sortID).then((res) => {
if (res.status_code == 1) {
this.$message.success(res.msg)
this.$message.success(res.msg);
}
})
});
},
handleDragEnd(e, item, type) {
// type group 话术库排序 item 话术排序
console.log(type, 'type', this.sortID)
this.dragging = null
this.groupLastDataList = this.groupDataList
this.groupLastList = this.groupList
type === 'group' ? this.sortSkillGroup() : this.sortSkill()
console.log(type, "type", this.sortID);
this.dragging = null;
this.groupLastDataList = this.groupDataList;
this.groupLastList = this.groupList;
type === "group" ? this.sortSkillGroup() : this.sortSkill();
},
// 首先把div变成可以放置的元素,即重写dragenter/dragover
// DataTransfer 对象用来保存,通过拖放动作,拖动到浏览器的数据。
// 如果dropEffect 属性设定为none,则不允许被拖放到目标元素中。
handleDragOver(e) {
e.dataTransfer.dropEffect = 'move' // e.dataTransfer.dropEffect="move";//在dragenter中针对放置目标来设置!
e.dataTransfer.dropEffect = "move"; // e.dataTransfer.dropEffect="move";//在dragenter中针对放置目标来设置!
},
handleDragEnter(e, item, type) {
e.dataTransfer.effectAllowed = 'move' // 为需要移动的元素设置dragstart事件
e.dataTransfer.effectAllowed = "move"; // 为需要移动的元素设置dragstart事件
if (item === this.dragging) {
return
return;
}
if (type === 'group') {
if (type === "group") {
// 话术租排序
const newItems = [...this.groupList]
const src = newItems.indexOf(this.dragging)
const dst = newItems.indexOf(item)
const newItems = [...this.groupList];
const src = newItems.indexOf(this.dragging);
const dst = newItems.indexOf(item);
if (src > dst) {
// 往上拖动
this.sortID.after_id = this.groupLastList[dst]._id
this.groupLastList[dst - 1] ? (this.sortID.before_id = this.groupLastList[dst - 1]._id) : (this.sortID.before_id = '')
this.sortID.after_id = this.groupLastList[dst]._id;
this.groupLastList[dst - 1]
? (this.sortID.before_id = this.groupLastList[dst - 1]._id)
: (this.sortID.before_id = "");
// 替换
} else {
// 往下拖动
this.sortID.before_id = this.groupLastList[dst]._id
this.groupLastList[dst + 1] ? (this.sortID.after_id = this.groupLastList[dst + 1]._id) : (this.sortID.after_id = '')
this.sortID.before_id = this.groupLastList[dst]._id;
this.groupLastList[dst + 1]
? (this.sortID.after_id = this.groupLastList[dst + 1]._id)
: (this.sortID.after_id = "");
}
// 替换
newItems.splice(dst, 0, ...newItems.splice(src, 1))
newItems.splice(dst, 0, ...newItems.splice(src, 1));
// 让item的颜色等于新交换的颜色
this.groupList = newItems
this.groupList = newItems;
} else {
// 话术排序
const newItems = [...this.groupDataList]
const src = newItems.indexOf(this.dragging)
const dst = newItems.indexOf(item)
const newItems = [...this.groupDataList];
const src = newItems.indexOf(this.dragging);
const dst = newItems.indexOf(item);
if (src > dst) {
// 往上拖动
this.sortID.after_id = this.groupLastDataList[dst]._id
this.groupLastDataList[dst - 1] ? (this.sortID.before_id = this.groupLastDataList[dst - 1]._id) : (this.sortID.before_id = '')
this.sortID.after_id = this.groupLastDataList[dst]._id;
this.groupLastDataList[dst - 1]
? (this.sortID.before_id = this.groupLastDataList[dst - 1]._id)
: (this.sortID.before_id = "");
// 替换
} else {
// 往下拖动
this.sortID.before_id = this.groupLastDataList[dst]._id
this.groupLastDataList[dst + 1] ? (this.sortID.after_id = this.groupLastDataList[dst + 1]._id) : (this.sortID.after_id = '')
this.sortID.before_id = this.groupLastDataList[dst]._id;
this.groupLastDataList[dst + 1]
? (this.sortID.after_id = this.groupLastDataList[dst + 1]._id)
: (this.sortID.after_id = "");
}
newItems.splice(dst, 0, ...newItems.splice(src, 1))
newItems.splice(dst, 0, ...newItems.splice(src, 1));
// 让item的颜色等于新交换的颜色
this.groupDataList = newItems
this.groupDataList = newItems;
}
},
// 发送语音的时候 先编辑再发送
// 发送语音的时候 先编辑再发送
sendMessageEdit(item, id) {
// 复制内容到粘贴板
if (item.msgtype == 'text') {
if (item.msgtype == "text") {
if (item && item.text && item.text.content) {
// copyToClipboard(
// item.text.content,
// (message) => this.$message.success(message),
// (message) => this.$message.error(message)
// )
this.sendChatMessage(item.text.content)
this.sendChatMessage(item.text.content);
}
} else if (item.msgtype == 'image' && item.image.picurl) {
this.sendMessageImage(item)
} else if (item.msgtype == "image" && item.image.picurl) {
this.sendMessageImage(item);
}
},
async sendMessageImage(item, id) {
// 发送图片作为链接消息
if (item.image && item.image.picurl) {
const res = await getMediaId({ url: item.image.picurl })
const res = await getMediaId({ url: item.image.picurl });
if (res.status_code == 1) {
this.sendImageAsMedia(res.data.media_id)
this.sendImageAsMedia(res.data.media_id);
}
} else {
// 如果没有图片URL,提示用户
this.$message.error('图片链接不存在,无法发送')
this.$message.error("图片链接不存在,无法发送");
}
},
// 发送图片作为链接消息
sendImageAsMedia(media_id) {
this.$ww.sendChatMessage({
msgtype: 'image',
msgtype: "image",
image: {
mediaid: media_id
mediaid: media_id,
},
success: (res) => {
console.log(res, '发送图片链接成功')
this.$message.success('图片发送成功')
console.log(res, "发送图片链接成功");
this.$message.success("图片发送成功");
},
fail: (err) => {
console.log(err, '发送图片链接失败')
this.$message.error('图片发送失败:' + (err.errMsg || err.message || '未知错误'))
}
})
console.log(err, "发送图片链接失败");
this.$message.error(
"图片发送失败:" + (err.errMsg || err.message || "未知错误")
);
},
});
},
// 发送文本消息
sendChatMessage(text) {
this.$ww.sendChatMessage({
msgtype: 'text',
msgtype: "text",
text: {
content: text
content: text,
},
success: (res) => {
console.log(res, '发送文本成功')
console.log(res, "发送文本成功");
},
fail: (err) => {
console.log(err, '发送文本失败')
}
})
console.log(err, "发送文本失败");
},
});
},
contentSearch() {
this.pageInfo = {
page: 1,
page_size: 100,
total: 0
}
this.searchTable()
total: 0,
};
this.searchTable();
},
requestGroup() {
this.loading = true
this.loading = true;
const data = {
page: 1,
pageSize: 100,
type: this.activeName
}
type: this.activeName,
};
procedure_group(data).then((res) => {
this.loading = false
this.loading = false;
if (res.data && res.data.data && res.data.data.length > 0) {
this.groupList = res.data.data.map((item, index) => {
item.label = item.group_name
item.value = item._id
return item
})
this.groupLastList = this.groupList
this.groupFilter(this.groupList[0])
item.label = item.group_name;
item.value = item._id;
return item;
});
this.groupLastList = this.groupList;
this.groupFilter(this.groupList[0]);
} else {
this.groupList = []
this.groupLastList = []
this.groupList = [];
this.groupLastList = [];
}
})
});
},
// 62bd394d3747fe7c600a04f1
groupFilter(item, index) {
if (!item._id) {
this.requestData.second_group_id = ''
this.activeGroup = {}
this.requestData.second_group_id = "";
this.activeGroup = {};
}
this.groupActive = item.value
this.activeGroup = item
this.searchTable()
this.groupActive = item.value;
this.activeGroup = item;
this.searchTable();
},
// 搜索结果
async searchTable(msg) {
this.skillLoading = true
this.requestData.type = this.activeName
this.requestData.procedure_group_id = this.activeGroup._id || ''
const data = { ...this.requestData, ...this.pageInfo }
this.skillLoading = true;
this.requestData.type = this.activeName;
this.requestData.procedure_group_id = this.activeGroup._id || "";
const data = { ...this.requestData, ...this.pageInfo };
procedureList(data).then((res) => {
this.skillLoading = false
this.groupDataList = res.data.data
this.skillLoading = false;
this.groupDataList = res.data.data;
this.groupDataList.map((item, index) => {
const text = item.message.attachments.find((item) => item.msgtype === 'text')
const text = item.message.attachments.find(
(item) => item.msgtype === "text"
);
if (text) {
item.title = text.text.content
item.title = text.text.content;
} else {
item.title = ''
item.title = "";
}
})
this.groupLastDataList = this.groupDataList
})
});
this.groupLastDataList = this.groupDataList;
});
},
handleChange() { },
handleChange() {},
// 重置select
resizeSelect() {
this.groupActive = '0'
this.isResize = true
this.groupDataList = []
this.requestData.content = ''
this.pageInfo.page = 1
this.groupActive = "0";
this.isResize = true;
this.groupDataList = [];
this.requestData.content = "";
this.pageInfo.page = 1;
setTimeout(() => {
this.isResize = false
}, 2000)
this.isResize = false;
}, 2000);
},
handleClick(tab, event) {
// 切换table
this.resizeSelect()
this.requestGroup()
}
}
}
this.resizeSelect();
this.requestGroup();
},
},
};
</script>
<style lang="scss" scoped>
.details {
......@@ -425,7 +500,7 @@ export default {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #409EFF;
color: #409eff;
margin-right: 10px;
}
......@@ -611,7 +686,7 @@ export default {
}
.tagItemActive {
color: #409EFF;
color: #409eff;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
background: #e4fff1;
......
<template>
<div class="skillLibrary">
<div v-loading="loading" class="rowFlex skillBox">
<div v-loading="loading" class="rowFlex skillBox pl-[10px]">
<!-- 标签 -->
<el-collapse-transition>
<div v-if="groupList.length > 0" class="tagList columnFlex">
<div v-for="(item, index) in groupList" :key="index" class="tagItem columnCenter" :draggable="false"
<div
v-for="(item, index) in groupList"
:key="index"
class="tagItem columnCenter"
:draggable="false"
:class="groupActive == item.value ? 'tagItemActiveText' : ''"
@dragstart="handleDragStart($event, item, index)" @dragover.prevent="handleDragOver($event, item)"
@dragenter="handleDragEnter($event, item, 'group')" @dragend="handleDragEnd($event, item, 'group')">
<div class="rowFlex columnCenter spaceBetween tagItemGroup" @click="groupFilter(item, index)">
@dragstart="handleDragStart($event, item, index)"
@dragover.prevent="handleDragOver($event, item)"
@dragenter="handleDragEnter($event, item, 'group')"
@dragend="handleDragEnd($event, item, 'group')"
>
<div
class="rowFlex columnCenter spaceBetween tagItemGroup"
@click="groupFilter(item, index)"
>
<div class="rowFlex columnCenter">
<el-tooltip effect="dark" placement="top" :content="item.name" v-if="item.name.length >= 6">
<p class="text hidden" @click="groupFilter(item, index)">{{ item.name }}</p>
<el-tooltip
effect="dark"
placement="top"
:content="item.name"
v-if="item.name.length >= 6"
>
<p class="text hidden" @click="groupFilter(item, index)">
{{ item.name }}
</p>
</el-tooltip>
<p v-else class="text hidden" @click="groupFilter(item, index)">{{ item.name }}</p>
<p v-else class="text hidden" @click="groupFilter(item, index)">
{{ item.name }}
</p>
</div>
<i class="el-icon-caret-right rotageIcon" :class="groupActive == item.value ? 'rotage' : ''"></i>
<i
class="el-icon-caret-right rotageIcon"
:class="groupActive == item.value ? 'rotage' : ''"
></i>
</div>
<!-- 二级分组 -->
<div v-if="item.child.length > 0 && groupActive == item.value" class="childGroup">
<div v-for="child in item.child" :key="child._id" class="childGroupText"
:class="[groupActiveChild == child._id ? 'tagItemActive' : '']" @click.stop="groupFilterChild(child)">
<div
v-if="item.child.length > 0 && groupActive == item.value"
class="childGroup"
>
<div
v-for="child in item.child"
:key="child._id"
class="childGroupText"
:class="[groupActiveChild == child._id ? 'tagItemActive' : '']"
@click.stop="groupFilterChild(child)"
>
<p class="text hidden">{{ child.name }}</p>
</div>
</div>
......@@ -33,27 +63,67 @@
<!-- 话术 -->
<div class="libraryListContent">
<div class="inputContent">
<el-input v-model="requestData.title" placeholder="请输入话术内容" class="input-with-select">
<el-button slot="append" icon="el-icon-search" @click="contentSearch"></el-button>
<el-input
v-model="requestData.title"
placeholder="请输入话术内容"
class="input-with-select"
>
<el-button
slot="append"
icon="el-icon-search"
@click="contentSearch"
></el-button>
</el-input>
</div>
<div ref="skillLibrary" v-loading="skillLoading" @scroll="paperScroll" class="scrollList">
<div v-for="(items, indexs) in groupDataList" :key="indexs" class="answerContent">
<div class="question"><span class="title">Q:</span>{{ items.name }}</div>
<div v-for="(answer, answerIndex) in items.answer" :key="answerIndex" class="answerItem"
style="width: 100%">
<div
ref="skillLibrary"
v-loading="skillLoading"
@scroll="paperScroll"
class="scrollList px-[10px]"
>
<div
v-for="(items, indexs) in groupDataList"
:key="indexs"
class="answerContent"
>
<div class="question">
<span class="title">Q:</span>{{ items.name }}
</div>
<div
v-for="(answer, answerIndex) in items.answer"
:key="answerIndex"
class="answerItem"
style="width: 100%"
>
<!-- <span class="question">{{ answerIndex + 1 }}: {{ answer }}</span> -->
<div v-if="answer.msgtype == 'text'" class="answerText rowFlex spaceBetween">
<div
v-if="answer.msgtype == 'text'"
class="answerText rowFlex spaceBetween"
>
<span class="title rowFlex">A{{ answerIndex + 1 }}:</span>
<p v-if="answer.msgtype == 'text'" class="rowFlex textAnswer flex1">
{{ answer.text.content || '' }}
<p
v-if="answer.msgtype == 'text'"
class="rowFlex textAnswer flex1"
>
{{ answer.text.content || "" }}
</p>
<i class="el-icon-document-copy copyIcon rowFlex" @click="sendMessageEdit(answer, items._id)"></i>
<i
class="el-icon-document-copy copyIcon rowFlex"
@click="sendMessageEdit(answer, items._id)"
></i>
</div>
<div v-else-if="answer.msgtype == 'image'" class="answerText rowFlex">
<div
v-else-if="answer.msgtype == 'image'"
class="answerText rowFlex"
>
<span class="title rowFlex">A{{ answerIndex + 1 }}:</span>
<el-image style="max-width: 200px" :src="answer.image.picurl"
@click="sendMessageImage(answer, items._id)" :preview-src-list="[answer.image.picurl]"> </el-image>
<el-image
style="max-width: 200px"
:src="answer.image.picurl"
@click="sendMessageImage(answer, items._id)"
:preview-src-list="[answer.image.picurl]"
>
</el-image>
</div>
</div>
</div>
......@@ -65,26 +135,31 @@
<script>
// procedure_group, procedureList, procedureSort, procedureGroupSort, skillQuote,
import { groupList, libraryIndex, logClickTime } from '@/api/skill'
import { mapState, mapMutations, mapActions } from 'vuex'
import { throttle, debounce, copyToClipboard, sendChatMessage } from '@/utils/index'
import noContent from '@/components/noContent.vue'
import { groupList, libraryIndex, logClickTime } from "@/api/skill";
import { mapState, mapMutations, mapActions } from "vuex";
import {
throttle,
debounce,
copyToClipboard,
sendChatMessage,
} from "@/utils/index";
import noContent from "@/components/noContent.vue";
export default {
name: 'skillLibrary',
name: "skillLibrary",
components: {
noContent
noContent,
},
props: {
activeName: {
default: '',
type: String
}
default: "",
type: String,
},
},
data() {
return {
collapseActive: '',
groupActive: '0',
groupActiveChild: '0',
collapseActive: "",
groupActive: "0",
groupActiveChild: "0",
activeGroup: {},
groupList: [],
groupLastList: [],
......@@ -93,93 +168,93 @@ export default {
pageInfo: {
page: 1,
page_size: 20,
total: 0
total: 0,
},
skillLoading: false,
loading: false,
requestData: {
title: '',
first_group_id: '',
second_group_id: ''
title: "",
first_group_id: "",
second_group_id: "",
},
sortType: '',
sortType: "",
sortID: {
_id: '',
before_id: '',
after_id: ''
_id: "",
before_id: "",
after_id: "",
},
filterText: {},
dragging: null,
orderList: [
{ label: '知识库', type: 'library' },
{ label: '个人话术', type: 'personal' },
{ label: '企业话术', type: 'company' }
]
}
{ label: "知识库", type: "library" },
{ label: "个人话术", type: "personal" },
{ label: "企业话术", type: "company" },
],
};
},
computed: {
...mapState('game', ['accountSelect', 'chatUserInfo']),
...mapState("game", ["accountSelect", "chatUserInfo"]),
},
watch: {
accountSelect(newVal, oldVal) {
if (newVal && newVal !== '') {
if (newVal && newVal !== "") {
this.pageInfo = {
page: 1,
page_size: 20,
total: 0
}
total: 0,
};
}
},
activeName(newVal, oldVal) {
if (newVal == 'library' && newVal != oldVal) {
this.resizeSelect()
this.requestLibraryData()
}
if (newVal == "library" && newVal != oldVal) {
this.resizeSelect();
this.requestLibraryData();
}
},
},
mounted() {
this.requestLibraryData()
this.requestLibraryData();
},
methods: {
sendMessage: throttle(function (item, id) {
console.log(item, id)
console.log(item, id);
// this.skillQuote(id, item.length)
}, 500),
handleDragStart(e, item, index) {
this.sortID._id = item._id
this.dragging = item
this.sortID._id = item._id;
this.dragging = item;
},
paperScroll: debounce(function () {
const el = this.$refs.skillLibrary
const el = this.$refs.skillLibrary;
if (el.offsetHeight + el.scrollTop + 10 >= el.scrollHeight) {
console.log('下一页')
this.pageInfo.page++
this.searchTable()
console.log("下一页");
this.pageInfo.page++;
this.searchTable();
}
}, 500),
skillQuote(id, num) {
const data = {
type: this.activeName,
procedure_id: id,
quote_count: num || 1
}
quote_count: num || 1,
};
skillQuote(data).then((res) => {
console.log(res)
})
console.log(res);
});
},
sortSkill() {
procedureSort(this.sortID).then((res) => {
if (res.status_code == 1) {
this.$message.success(res.msg)
this.$message.success(res.msg);
}
})
});
},
sortSkillGroup() {
procedureGroupSort(this.sortID).then((res) => {
if (res.status_code == 1) {
this.$message.success(res.msg)
this.$message.success(res.msg);
}
})
});
},
// 发送语音的时候 先编辑再发送
sendMessageEdit(item, id) {
......@@ -189,98 +264,107 @@ export default {
item.text.content,
(message) => this.$message.success(message),
(message) => this.$message.error(message)
)
);
}
this.sendChatMessage(item.text.content || '', 'text')
this.sendChatMessage(item.text.content || "", "text");
},
sendMessageImage(item) {
console.log(item, 'item')
this.sendChatMessage(item.image.picurl || '', 'image')
console.log(item, "item");
this.sendChatMessage(item.image.picurl || "", "image");
},
contentSearch() {
this.pageInfo = {
page: 1,
page_size: 20,
total: 0
}
this.searchTable('msg')
total: 0,
};
this.searchTable("msg");
},
// 知识库话术
requestLibraryData() {
console.log(this.chatUserInfo, 'chatUserInfo')
this.loading = true
console.log(this.chatUserInfo, "chatUserInfo");
this.loading = true;
const data = {
page: 1,
page_size: 100,
userid: this.chatUserInfo.userid
}
userid: this.chatUserInfo.userid,
};
groupList(data).then((res) => {
this.loading = false
this.loading = false;
if (res.data.data) {
res.data.data.unshift({
name: '全部分组',
value: '',
child: []
})
name: "全部分组",
value: "",
child: [],
});
this.groupList = res.data.data.map((item, index) => {
item.label = item.name
item.value = item._id
return item
})
this.groupLastList = this.groupList
this.groupFilter(this.groupList[0])
item.label = item.name;
item.value = item._id;
return item;
});
this.groupLastList = this.groupList;
this.groupFilter(this.groupList[0]);
} else {
this.groupList = []
this.groupLastList = []
this.groupList = [];
this.groupLastList = [];
}
})
});
},
groupFilter(item, index) {
if (!item._id) {
this.requestData.second_group_id = ''
this.activeGroup = {}
}
this.groupActive = item.value
item.child && item.child[0] ? ((this.activeGroup = item.child[0]), (this.groupActiveChild = item.child[0]._id)) : ''
this.searchTable()
this.requestData.second_group_id = "";
this.activeGroup = {};
}
this.groupActive = item.value;
item.child && item.child[0]
? ((this.activeGroup = item.child[0]),
(this.groupActiveChild = item.child[0]._id))
: "";
this.searchTable();
},
groupFilterChild(child) {
this.groupActiveChild = 0
this.activeGroup = child
this.groupActiveChild = child._id
this.searchTable()
this.$forceUpdate()
this.groupActiveChild = 0;
this.activeGroup = child;
this.groupActiveChild = child._id;
this.searchTable();
this.$forceUpdate();
},
// 搜索结果
async searchTable(msg) {
this.skillLoading = true
this.requestData.second_group_id = this.activeGroup._id || ''
this.requestData.title = this.requestData.title.trim()
const data = { ...this.requestData, ...this.pageInfo, log_scan: msg ? 1 : 0, userid: this.chatUserInfo.userid }
this.skillLoading = true;
this.requestData.second_group_id = this.activeGroup._id || "";
this.requestData.title = this.requestData.title.trim();
const data = {
...this.requestData,
...this.pageInfo,
log_scan: msg ? 1 : 0,
userid: this.chatUserInfo.userid,
};
libraryIndex(data).then((res) => {
this.skillLoading = false
this.pageInfo.page === 1 ? this.groupDataList = res.data.data : this.groupDataList = this.groupDataList.concat(res.data.data)
this.groupLastDataList = this.groupDataList
})
this.skillLoading = false;
this.pageInfo.page === 1
? (this.groupDataList = res.data.data)
: (this.groupDataList = this.groupDataList.concat(res.data.data));
this.groupLastDataList = this.groupDataList;
});
},
handleChange() { },
handleChange() {},
// 重置select
resizeSelect() {
this.groupActive = '0'
this.isResize = true
this.groupDataList = []
this.requestData.content = ''
this.pageInfo.page = 1
this.groupActive = "0";
this.isResize = true;
this.groupDataList = [];
this.requestData.content = "";
this.pageInfo.page = 1;
setTimeout(() => {
this.isResize = false
}, 2000)
this.isResize = false;
}, 2000);
},
sendChatMessage(content, type) {
sendChatMessage(content, type)
sendChatMessage(content, type);
},
}
}
},
};
</script>
<style lang="scss" scoped>
.skillLibrary {
......@@ -321,7 +405,7 @@ export default {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #409EFF;
color: #409eff;
margin-right: 10px;
}
......@@ -467,7 +551,6 @@ export default {
.skillBox {
width: 100%;
height: calc(100% - 20px);
}
.tagList {
......@@ -513,14 +596,14 @@ export default {
}
.tagItemActive {
color: #409EFF !important;
color: #409eff !important;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
background: #e4fff1;
}
.tagItemActiveText {
color: #409EFF;
color: #409eff;
}
}
......@@ -607,7 +690,7 @@ export default {
.copyIcon {
width: 20px;
color: #409EFF;
color: #409eff;
font-size: 16px;
position: relative;
top: 2px;
......@@ -619,7 +702,7 @@ export default {
}
.scrollList::-webkit-scrollbar {
display: none
display: none;
}
.container {
......@@ -676,7 +759,7 @@ export default {
}
.skillLibrary::-webkit-scrollbar {
display: none
display: none;
}
::v-deep .el-icon-circle-close {
......
<template>
<div class="skillTab">
<div class="inputContent">
<el-input v-model="requestData.content" placeholder="请输入话术内容" class="input-with-select" @change="contentSearch">
<el-input
v-model="requestData.content"
placeholder="请输入话术内容"
class="input-with-select"
@change="contentSearch"
>
<el-button slot="append" icon="el-icon-search"></el-button>
</el-input>
</div>
<div v-loading="loading" class="rowFlex skillBox">
<div v-loading="loading" class="rowFlex skillBox pl-[10px]">
<!-- 标签 -->
<el-collapse-transition>
<div v-if="groupList.length > 0" class="tagList columnFlex">
<div v-for="(item, index) in groupList" :key="index" class="tagItem rowFlex columnCenter"
<div
v-for="(item, index) in groupList"
:key="index"
class="tagItem rowFlex columnCenter"
:draggable="activeName == 'personal' ? true : false"
:class="groupActive == item.value ? 'tagItemActive' : ''" @dragstart="handleDragStart($event, item, index)"
@dragover.prevent="handleDragOver($event, item)" @dragenter="handleDragEnter($event, item, 'group')"
@dragend="handleDragEnd($event, item, 'group')">
<el-tooltip effect="dark" placement="top" :content="item.group_name" v-if="item.group_name.length >= 6">
<p class="text hidden" @click="groupFilter(item, index)">{{ item.group_name }}</p>
:class="groupActive == item.value ? 'tagItemActive' : ''"
@dragstart="handleDragStart($event, item, index)"
@dragover.prevent="handleDragOver($event, item)"
@dragenter="handleDragEnter($event, item, 'group')"
@dragend="handleDragEnd($event, item, 'group')"
>
<el-tooltip
effect="dark"
placement="top"
:content="item.group_name"
v-if="item.group_name.length >= 6"
>
<p class="text hidden" @click="groupFilter(item, index)">
{{ item.group_name }}
</p>
</el-tooltip>
<p v-else class="text hidden" @click="groupFilter(item, index)">{{ item.group_name }}</p>
<p v-else class="text hidden" @click="groupFilter(item, index)">
{{ item.group_name }}
</p>
</div>
</div>
<div v-else>暂无话术内容</div>
</el-collapse-transition>
<!-- 话术 -->
<div v-loading="skillLoading" class="scrollList">
<div v-loading="skillLoading" class="scrollList px-[10px]">
<el-collapse v-model="collapseActive" @change="handleChange">
<transition-group v-if="groupDataList.length > 0" tag="div" class="container">
<div v-for="(items, indexs) in groupDataList" :key="indexs"
:draggable="activeName == 'personal' ? true : false" class="draggable"
@dragstart="handleDragStart($event, items, indexs)" @dragover.prevent="handleDragOver($event, items)"
@dragenter="handleDragEnter($event, items, 'item')" @dragend="handleDragEnd($event, items, 'item')">
<transition-group
v-if="groupDataList.length > 0"
tag="div"
class="container"
>
<div
v-for="(items, indexs) in groupDataList"
:key="indexs"
:draggable="activeName == 'personal' ? true : false"
class="draggable"
@dragstart="handleDragStart($event, items, indexs)"
@dragover.prevent="handleDragOver($event, items)"
@dragenter="handleDragEnter($event, items, 'item')"
@dragend="handleDragEnd($event, items, 'item')"
>
<el-popover placement="top" width="300" trigger="hover">
<p>{{ items.title }}</p>
<div slot="reference" class="contentItemTitle allCenter"
:style="{ top: items.title.length > 8 ? '5px' : '13px' }">{{ items.title }}</div>
<div
slot="reference"
class="contentItemTitle allCenter"
:style="{ top: items.title.length > 8 ? '5px' : '13px' }"
>
{{ items.title }}
</div>
</el-popover>
<div class="rowFlex titleFixed columnCenter">
<div class="num">{{ items.message.attachments.length > 1 ? `+${items.message.attachments.length - 1}条` :
'' }}</div>
<div class="num">
{{
items.message.attachments.length > 1
? `+${items.message.attachments.length - 1}条`
: ""
}}
</div>
<!-- <el-button class="button rowFlex allCenter" @click.stop="sendMessage(items.message.attachments, items._id)">发送</el-button> -->
</div>
<el-collapse-item title="" :name="items._id" class="contentItem">
<div v-for="(i, j) in items.message.attachments" :key="j">
<div>
<div v-if="i.msgtype == 'text'" class="contentItemDetails rowFlex spaceBetween columnCenter">
<div
v-if="i.msgtype == 'text'"
class="contentItemDetails rowFlex spaceBetween columnCenter"
>
<div class="text">{{ i.text.content }}</div>
<el-button class="sendButton rowFlex allCenter"
@click.stop="sendMessageEdit(i, items._id)">发送</el-button>
<el-button
class="sendButton rowFlex allCenter"
@click.stop="sendMessageEdit(i, items._id)"
>发送</el-button
>
</div>
<div v-if="i.msgtype == 'image'" class="contentItemDetails rowFlex spaceBetween columnCenter">
<el-image class="image" :src="i.image.picurl" :preview-src-list="[i.image.picurl]"
fit="contain"></el-image>
<el-button class="sendButton rowFlex allCenter"
@click.stop="sendMessageEdit(i, items._id)">发送</el-button>
<div
v-if="i.msgtype == 'image'"
class="contentItemDetails rowFlex spaceBetween columnCenter"
>
<el-image
class="image"
:src="i.image.picurl"
:preview-src-list="[i.image.picurl]"
fit="contain"
></el-image>
<el-button
class="sendButton rowFlex allCenter"
@click.stop="sendMessageEdit(i, items._id)"
>发送</el-button
>
</div>
</div>
</div>
......@@ -67,23 +123,28 @@
</div>
</template>
<script>
import { procedure_group, procedureList, procedureSort, procedureGroupSort } from '@/api/skill'
import { getMediaId } from '@/api/works'
import { mapState, mapMutations, mapActions } from 'vuex'
import { debounce, copyToClipboard } from '@/utils/index'
import {
procedure_group,
procedureList,
procedureSort,
procedureGroupSort,
} from "@/api/skill";
import { getMediaId } from "@/api/works";
import { mapState, mapMutations, mapActions } from "vuex";
import { debounce, copyToClipboard } from "@/utils/index";
export default {
name: 'skillPersonal',
name: "skillPersonal",
components: {},
props: {
activeName: {
default: '',
type: String
}
default: "",
type: String,
},
},
data() {
return {
collapseActive: '',
groupActive: '0',
collapseActive: "",
groupActive: "0",
activeGroup: {},
groupList: [],
groupLastList: [],
......@@ -92,196 +153,206 @@ export default {
pageInfo: {
page: 1,
page_size: 100,
total: 0
total: 0,
},
skillLoading: false,
loading: false,
requestData: {
content: '',
type: '',
procedure_group_id: ''
content: "",
type: "",
procedure_group_id: "",
},
sortType: '',
sortType: "",
sortID: {
_id: '',
before_id: '',
after_id: ''
_id: "",
before_id: "",
after_id: "",
},
filterText: {},
dragging: null,
orderList: [
{ label: '个人话术', type: 'personal' },
{ label: '企业话术', type: 'company' }
]
}
{ label: "个人话术", type: "personal" },
{ label: "企业话术", type: "company" },
],
};
},
computed: {
...mapState('game', ['accountSelect']),
...mapState('user', ['userid', 'external_userid']),
...mapState("game", ["accountSelect"]),
...mapState("user", ["userid", "external_userid"]),
},
watch: {
accountSelect(newVal, oldVal) {
if (newVal && newVal !== '') {
if (newVal && newVal !== "") {
this.pageInfo = {
page: 1,
page_size: 100,
total: 0
}
total: 0,
};
}
},
activeName(newVal, oldVal) {
if (newVal == 'personal' && newVal != oldVal) {
this.resizeSelect()
this.requestGroup()
}
if (newVal == "personal" && newVal != oldVal) {
this.resizeSelect();
this.requestGroup();
}
},
},
mounted() {
this.requestGroup()
this.requestGroup();
},
methods: {
// ...mapMutations('common', ['set_sendSkillMessage', 'set_isEditSkill']),
sendMessage: debounce(function (item, id) {
console.log(item, id, 'sendMessage')
console.log(item, id, "sendMessage");
}, 500),
// 发送语音的时候 先编辑再发送
sendMessageEdit(item, id) {
console.log(item)
console.log(item);
// 复制内容到粘贴板
if (item.msgtype == 'text') {
if (item.msgtype == "text") {
if (item && item.text && item.text.content) {
// copyToClipboard(
// item.text.content,
// (message) => this.$message.success(message),
// (message) => this.$message.error(message)
// )
this.sendChatMessage(item.text.content)
this.sendChatMessage(item.text.content);
}
} else if (item.msgtype == 'image' && item.image.picurl) {
this.sendMessageImage(item)
} else if (item.msgtype == "image" && item.image.picurl) {
this.sendMessageImage(item);
}
},
async sendMessageImage(item, id) {
// 发送图片作为链接消息
if (item.image && item.image.picurl) {
const res = await getMediaId({ url: item.image.picurl })
const res = await getMediaId({ url: item.image.picurl });
if (res.status_code == 1) {
this.sendImageAsMedia(res.data.media_id)
this.sendImageAsMedia(res.data.media_id);
}
} else {
// 如果没有图片URL,提示用户
this.$message.error('图片链接不存在,无法发送')
this.$message.error("图片链接不存在,无法发送");
}
},
// 发送图片作为链接消息
sendImageAsMedia(media_id) {
this.$ww.sendChatMessage({
msgtype: 'image',
msgtype: "image",
image: {
mediaid: media_id
mediaid: media_id,
},
success: (res) => {
console.log(res, '发送图片链接成功')
this.$message.success('图片发送成功')
console.log(res, "发送图片链接成功");
this.$message.success("图片发送成功");
},
fail: (err) => {
console.log(err, '发送图片链接失败')
this.$message.error('图片发送失败:' + (err.errMsg || err.message || '未知错误'))
}
})
console.log(err, "发送图片链接失败");
this.$message.error(
"图片发送失败:" + (err.errMsg || err.message || "未知错误")
);
},
});
},
// 发送文本消息
sendChatMessage(text) {
this.$ww.sendChatMessage({
msgtype: 'text',
msgtype: "text",
text: {
content: text
content: text,
},
success: (res) => {
console.log(res, '发送文本成功')
console.log(res, "发送文本成功");
},
fail: (err) => {
console.log(err, '发送文本失败')
}
})
console.log(err, "发送文本失败");
},
});
},
handleDragStart(e, item, index) {
this.sortID._id = item._id
this.dragging = item
this.sortID._id = item._id;
this.dragging = item;
},
sortSkill() {
procedureSort(this.sortID).then((res) => {
if (res.status_code == 1) {
this.$message.success(res.msg)
this.$message.success(res.msg);
}
})
});
},
sortSkillGroup() {
if (this.sortID.before_id !== '' || this.sortID.after_id !== '') {
if (this.sortID.before_id !== "" || this.sortID.after_id !== "") {
procedureGroupSort(this.sortID).then((res) => {
if (res.status_code == 1) {
this.$message.success(res.msg)
this.$message.success(res.msg);
}
})
});
}
},
handleDragEnd(e, item, type) {
// type group 话术库排序 item 话术排序
console.log(type, 'type', this.sortID)
this.dragging = null
this.groupLastDataList = this.groupDataList
this.groupLastList = this.groupList
type === 'group' ? this.sortSkillGroup() : this.sortSkill()
console.log(type, "type", this.sortID);
this.dragging = null;
this.groupLastDataList = this.groupDataList;
this.groupLastList = this.groupList;
type === "group" ? this.sortSkillGroup() : this.sortSkill();
},
// 首先把div变成可以放置的元素,即重写dragenter/dragover
// DataTransfer 对象用来保存,通过拖放动作,拖动到浏览器的数据。
// 如果dropEffect 属性设定为none,则不允许被拖放到目标元素中。
handleDragOver(e) {
e.dataTransfer.dropEffect = 'move' // e.dataTransfer.dropEffect="move";//在dragenter中针对放置目标来设置!
e.dataTransfer.dropEffect = "move"; // e.dataTransfer.dropEffect="move";//在dragenter中针对放置目标来设置!
},
handleDragEnter(e, item, type) {
e.dataTransfer.effectAllowed = 'move' // 为需要移动的元素设置dragstart事件
e.dataTransfer.effectAllowed = "move"; // 为需要移动的元素设置dragstart事件
if (item === this.dragging) {
return
return;
}
if (type === 'group') {
if (type === "group") {
// 话术租排序
const newItems = [...this.groupList]
const src = newItems.indexOf(this.dragging)
const dst = newItems.indexOf(item)
const newItems = [...this.groupList];
const src = newItems.indexOf(this.dragging);
const dst = newItems.indexOf(item);
if (src > dst) {
// 往上拖动
this.sortID.after_id = this.groupLastList[dst]._id
this.groupLastList[dst - 1] ? (this.sortID.before_id = this.groupLastList[dst - 1]._id) : (this.sortID.before_id = '')
this.sortID.after_id = this.groupLastList[dst]._id;
this.groupLastList[dst - 1]
? (this.sortID.before_id = this.groupLastList[dst - 1]._id)
: (this.sortID.before_id = "");
// 替换
} else {
// 往下拖动
this.sortID.before_id = this.groupLastList[dst]._id
this.groupLastList[dst + 1] ? (this.sortID.after_id = this.groupLastList[dst + 1]._id) : (this.sortID.after_id = '')
this.sortID.before_id = this.groupLastList[dst]._id;
this.groupLastList[dst + 1]
? (this.sortID.after_id = this.groupLastList[dst + 1]._id)
: (this.sortID.after_id = "");
}
// 替换
newItems.splice(dst, 0, ...newItems.splice(src, 1))
newItems.splice(dst, 0, ...newItems.splice(src, 1));
// 让item的颜色等于新交换的颜色
this.groupList = newItems
this.groupList = newItems;
} else {
// 话术排序
const newItems = [...this.groupDataList]
const src = newItems.indexOf(this.dragging)
const dst = newItems.indexOf(item)
const newItems = [...this.groupDataList];
const src = newItems.indexOf(this.dragging);
const dst = newItems.indexOf(item);
if (src > dst) {
// 往上拖动
this.sortID.after_id = this.groupLastDataList[dst]._id
this.groupLastDataList[dst - 1] ? (this.sortID.before_id = this.groupLastDataList[dst - 1]._id) : (this.sortID.before_id = '')
this.sortID.after_id = this.groupLastDataList[dst]._id;
this.groupLastDataList[dst - 1]
? (this.sortID.before_id = this.groupLastDataList[dst - 1]._id)
: (this.sortID.before_id = "");
// 替换
} else {
// 往下拖动
this.sortID.before_id = this.groupLastDataList[dst]._id
this.groupLastDataList[dst + 1] ? (this.sortID.after_id = this.groupLastDataList[dst + 1]._id) : (this.sortID.after_id = '')
this.sortID.before_id = this.groupLastDataList[dst]._id;
this.groupLastDataList[dst + 1]
? (this.sortID.after_id = this.groupLastDataList[dst + 1]._id)
: (this.sortID.after_id = "");
}
newItems.splice(dst, 0, ...newItems.splice(src, 1))
newItems.splice(dst, 0, ...newItems.splice(src, 1));
// 让item的颜色等于新交换的颜色
this.groupDataList = newItems
this.groupDataList = newItems;
}
},
......@@ -289,82 +360,84 @@ export default {
this.pageInfo = {
page: 1,
page_size: 100,
total: 0
}
this.searchTable()
total: 0,
};
this.searchTable();
},
requestGroup() {
this.loading = true
this.loading = true;
const data = {
page: 1,
pageSize: 100,
type: this.activeName
}
type: this.activeName,
};
procedure_group(data).then((res) => {
this.loading = false
this.loading = false;
if (res.data.data && res.data.data.length > 0) {
this.groupList = res.data.data.map((item, index) => {
item.label = item.group_name
item.value = item._id
return item
})
this.groupLastList = this.groupList
this.groupFilter(this.groupList[0])
item.label = item.group_name;
item.value = item._id;
return item;
});
this.groupLastList = this.groupList;
this.groupFilter(this.groupList[0]);
} else {
this.groupList = []
this.groupLastList = []
this.groupList = [];
this.groupLastList = [];
}
})
});
},
// 62bd394d3747fe7c600a04f1
groupFilter(item, index) {
if (!item._id) {
this.requestData.second_group_id = ''
this.activeGroup = {}
this.requestData.second_group_id = "";
this.activeGroup = {};
}
this.groupActive = item.value
this.activeGroup = item
this.searchTable()
this.groupActive = item.value;
this.activeGroup = item;
this.searchTable();
},
// 搜索结果
async searchTable(msg) {
this.skillLoading = true
this.requestData.type = this.activeName
this.requestData.procedure_group_id = this.activeGroup._id || ''
const data = { ...this.requestData, ...this.pageInfo }
this.skillLoading = true;
this.requestData.type = this.activeName;
this.requestData.procedure_group_id = this.activeGroup._id || "";
const data = { ...this.requestData, ...this.pageInfo };
procedureList(data).then((res) => {
this.skillLoading = false
this.groupDataList = res.data.data
this.skillLoading = false;
this.groupDataList = res.data.data;
this.groupDataList.map((item, index) => {
const text = item.message.attachments.find((item) => item.msgtype === 'text')
const text = item.message.attachments.find(
(item) => item.msgtype === "text"
);
if (text) {
item.title = text.text.content
item.title = text.text.content;
} else {
item.title = ''
item.title = "";
}
})
this.groupLastDataList = this.groupDataList
})
});
this.groupLastDataList = this.groupDataList;
});
},
handleChange() { },
handleChange() {},
// 重置select
resizeSelect() {
this.groupActive = '0'
this.isResize = true
this.groupDataList = []
this.requestData.content = ''
this.pageInfo.page = 1
this.groupActive = "0";
this.isResize = true;
this.groupDataList = [];
this.requestData.content = "";
this.pageInfo.page = 1;
setTimeout(() => {
this.isResize = false
}, 2000)
this.isResize = false;
}, 2000);
},
handleClick(tab, event) {
// 切换table
this.resizeSelect()
this.requestGroup()
}
}
}
this.resizeSelect();
this.requestGroup();
},
},
};
</script>
<style lang="scss" scoped>
.details {
......@@ -422,7 +495,7 @@ export default {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #409EFF;
color: #409eff;
margin-right: 10px;
}
......@@ -608,7 +681,7 @@ export default {
}
.tagItemActive {
color: #409EFF;
color: #409eff;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
background: #e4fff1;
......@@ -682,8 +755,8 @@ export default {
}
.el-input-group__append {
background-color: #3491FA;
border-color: #3491FA;
background-color: #3491fa;
border-color: #3491fa;
color: #fff;
}
}
......@@ -701,16 +774,16 @@ export default {
}
.tagItemActive {
color: #3491FA !important;
background: #E8F7FF !important;
color: #3491fa !important;
background: #e8f7ff !important;
font-weight: 500 !important;
}
}
// 发送按钮样式
.sendButton {
background-color: #3491FA !important;
background-color: #3491fa !important;
color: white !important;
border-color: #3491FA !important;
border-color: #3491fa !important;
}
</style>
// UnifiedLogin.vue
<template>
<div class="loginContent">
<div class="p-[12px] flex flex-col h-screen">
<div class="text-[#131920] text-[13px] font-medium px-[10px]">登录</div>
<div class="flex-1 flex flex-col items-center justify-center px-[29px]">
<div class="h-[80px] w-[80px]">
<svg
width="80"
height="80"
viewBox="0 0 80 80"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clip-path="url(#a)">
<mask
id="b"
style="mask-type: alpha"
maskUnits="userSpaceOnUse"
x="14"
y="18"
width="38"
height="47"
>
<path
d="M50.522 64.389H16.588a1.78 1.78 0 0 1-1.78-1.653l-.004-.122v-1.866h33.61a12 12 0 0 0 2.108 3.641m-5.1-46.355c3.616 1.646 6.15 5.237 6.25 9.428l.004.257v5.914c0 3.057-1.296 5.813-3.37 7.755-1.312 1.708-1.509 3.928-.731 5.784l-1.262-.538c-3.59-1.53-4.617-5.959-2.369-8.886a10.6 10.6 0 0 0 3.37-7.754v-5.915c0-2.195-.668-4.235-1.812-5.93z"
fill="#fff"
/>
</mask>
<g mask="url(#b)">
<path
opacity=".2"
d="M50.522 64.389H16.588a1.78 1.78 0 0 1-1.78-1.653l-.004-.122v-1.866h33.61a12 12 0 0 0 2.108 3.641m-5.1-46.355c3.616 1.646 6.15 5.237 6.25 9.428l.004.257v5.914c0 3.057-1.296 5.813-3.37 7.755-1.312 1.708-1.509 3.928-.731 5.784l-1.262-.538c-3.59-1.53-4.617-5.959-2.369-8.886a10.6 10.6 0 0 0 3.37-7.754v-5.915c0-2.195-.668-4.235-1.812-5.93z"
fill="#338cff"
/>
</g>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M46.368 24.104v5.915a9.55 9.55 0 0 1-3.063 7.044l-.058.055-.048.063c-1.278 1.664-1.702 3.794-1.165 5.844a6.76 6.76 0 0 0 3.923 4.529l4.152 1.845.265.113.382-.894c-.903-.386-2.612-1.19-4.417-1.959-3.59-1.53-4.617-5.958-2.37-8.885a10.6 10.6 0 0 0 3.37-7.755v-5.915c0-5.88-4.792-10.646-10.704-10.646S25.93 18.224 25.93 24.104v5.915c0 3.076 1.31 5.848 3.409 7.791 2.208 2.928 1.173 7.323-2.4 8.846L13.35 52.449a4.73 4.73 0 0 0-2.884 4.349V59c0 .98.8 1.774 1.785 1.774h35.87v-.971h-35.87a.81.81 0 0 1-.813-.803v-2.203c0-1.506.9-2.861 2.293-3.455L27.32 47.55a6.76 6.76 0 0 0 3.916-4.5 6.73 6.73 0 0 0-1.12-5.825l-.052-.07-.064-.058a9.68 9.68 0 0 1-3.098-7.078v-5.915c0-5.334 4.366-9.673 9.733-9.673s9.733 4.34 9.733 9.673"
fill="#338cff"
/>
<mask
id="c"
style="mask-type: alpha"
maskUnits="userSpaceOnUse"
x="47"
y="46"
width="22"
height="22"
>
<path
d="M65.668 64.045c4.088-4.088 4.088-10.715 0-14.803-4.087-4.088-10.715-4.088-14.803 0-4.087 4.088-4.087 10.715 0 14.803 4.088 4.088 10.716 4.088 14.803 0"
fill="#fff"
/>
</mask>
<g mask="url(#c)">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="m65.86 64.237.67-.67-15.064-15.1-.67.67z"
fill="#338cff"
/>
</g>
<path
d="M66.012 64.388c4.278-4.277 4.278-11.212 0-15.49-4.277-4.277-11.212-4.277-15.49 0-4.277 4.278-4.277 11.213 0 15.49s11.213 4.278 15.49 0Z"
stroke="#338cff"
stroke-width=".963"
/>
</g>
<defs>
<clipPath id="a"><path fill="#fff" d="M0 0h80v80H0z" /></clipPath>
</defs>
</svg>
</div>
<div class="text-[#6D7176] text-[12px] mt-[8px] mb-[32px]">
暂无客服在线,请选择客服上线
</div>
<div class="w-full">
<el-select
v-model="cser_user_id"
filterable
placeholder="请选择客服"
style="width: 100%"
>
<el-option
v-for="item in userList"
:key="item.zq_user_id"
clearable
:label="item.name"
:value="item.zq_user_id"
>
</el-option>
</el-select>
</div>
<div class="mt-[16px] w-full mb-[228px]">
<el-button
type="primary"
size="small"
class="!w-full"
@click="loginConfirm"
>上线</el-button
>
</div>
</div>
</div>
<!-- <div class="loginContent">
<div class="loginContentContainer">
<p class="loginContentTitle">选择客服:</p>
<div class="loginContentInput rowFlex alignCenter">
......@@ -23,25 +126,25 @@
>
</div>
</div>
</div>
</div> -->
</template>
<script>
import * as ww from '@wecom/jssdk';
import * as ww from "@wecom/jssdk";
import {
getOrganization,
getAuthUser,
getSignature,
getUserList,
cserSelected,
} from '@/api/user';
import Cookies from 'js-cookie';
import { getParams } from '@/utils/index';
import { mapMutations, mapState } from 'vuex';
import { getToken, setToken } from '@/utils/auth';
import jsApiList from '@/utils/jsApiList';
} from "@/api/user";
import Cookies from "js-cookie";
import { getParams } from "@/utils/index";
import { mapMutations, mapState } from "vuex";
import { getToken, setToken } from "@/utils/auth";
import jsApiList from "@/utils/jsApiList";
export default {
name: 'login',
name: "login",
components: {},
data() {
return {
......@@ -57,10 +160,10 @@ export default {
showRefresh: false, // 控制刷新按钮显示
qrLoading: false, // 控制二维码 loading
redirectUri:
process.env.NODE_ENV === 'production'
? 'https://companywx.zwnet.cn/api/api/sidebar_login/ding'
: 'https://companywx.zwwlkj03.top/api/api/sidebar_login/ding',
DDTestUrl: '',
process.env.NODE_ENV === "production"
? "https://companywx.zwnet.cn/api/api/sidebar_login/ding"
: "https://companywx.zwwlkj03.top/api/api/sidebar_login/ding",
DDTestUrl: "",
token: getToken(),
userList: [],
cser_user_id: null,
......@@ -72,23 +175,23 @@ export default {
});
},
computed: {
...mapState('user', ['corp_id']),
...mapState("user", ["corp_id"]),
},
methods: {
...mapMutations('user', [
'set_corp_id',
'set_userid',
'set_userInfo',
'set_token',
'set_cser_info',
'set_signData',
'set_cser_id',
'set_cser_name',
'set_external_userid',
...mapMutations("user", [
"set_corp_id",
"set_userid",
"set_userInfo",
"set_token",
"set_cser_info",
"set_signData",
"set_cser_id",
"set_cser_name",
"set_external_userid",
]),
async initLogin() {
const urlParams = getParams();
const userid = Cookies.get('userid');
const userid = Cookies.get("userid");
if (this.token && userid) {
// 已经钉钉扫码过 重新获取授权 获取签名 注册企微js-sdk
this.getUserList(userid);
......@@ -101,20 +204,20 @@ export default {
},
async getUserList(userid) {
this.urlParams = getParams();
const corp_id = Cookies.get('corp_id') || this.urlParams.corp_id;
const corp_id = Cookies.get("corp_id") || this.urlParams.corp_id;
const res = await getUserList({ userid: userid, corp_id: corp_id });
this.userList = res.data;
},
async userStartLogin() {
if (!this.cser_user_id) {
this.$message.error('请选择客服人员');
this.$message.error("请选择客服人员");
return;
}
const cser_user = this.userList.find(
(item) => item.zq_user_id === this.cser_user_id
);
const corp_id = Cookies.get('corp_id');
const userid = Cookies.get('userid');
const corp_id = Cookies.get("corp_id");
const userid = Cookies.get("userid");
this.cacheCser(cser_user.zq_user_id, cser_user.name);
try {
const res = await cserSelected({
......@@ -122,10 +225,10 @@ export default {
corp_id: corp_id,
userid: userid,
});
console.log(res, '选择客服人员登录');
console.log(res, "选择客服人员登录");
if (res.status_code === 1 && res.data.tokens) {
this.$message({
type: 'warning',
type: "warning",
message: `当前【${cser_user.name}】已上线,下班后请记得点击下线哦~`,
duration: 3 * 1000,
});
......@@ -137,20 +240,20 @@ export default {
setTimeout(() => {
window.location.href =
window.location.origin +
'/company_app/index.html?corp_id=' +
"/company_app/index.html?corp_id=" +
corp_id +
'&msg=cser_error';
"&msg=cser_error";
}, 5000);
}
} catch (error) {
console.log(error, '选择客服人员登录失败');
console.log(error, "选择客服人员登录失败");
this.$message.error(error.msg);
setTimeout(() => {
window.location.href =
window.location.origin +
'/company_app/index.html?corp_id=' +
"/company_app/index.html?corp_id=" +
corp_id +
'&msg=cser_error';
"&msg=cser_error";
}, 5000);
}
},
......@@ -160,32 +263,32 @@ export default {
);
this.$confirm(
`确认登录上线吗,上线后所有会话都会归属到客服【${cser_user.name}】`,
'提示',
"提示",
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}
)
.then(() => {
this.userStartLogin();
})
.catch(() => {
this.$message.info('已取消登录');
this.$message.info("已取消登录");
});
},
// 设置缓存
cacheCorp_id(corp_id) {
Cookies.set('corp_id', corp_id, { expires: 30 });
Cookies.set("corp_id", corp_id, { expires: 30 });
this.set_corp_id(corp_id);
},
cacheuserid(userid) {
Cookies.set('userid', userid, { expires: 30 });
Cookies.set("userid", userid, { expires: 30 });
this.set_userid(userid);
},
cacheCser(cser_id, cser_name) {
Cookies.set('cser_id', cser_id, { expires: 30 });
Cookies.set('cser_name', cser_name, { expires: 30 });
Cookies.set("cser_id", cser_id, { expires: 30 });
Cookies.set("cser_name", cser_name, { expires: 30 });
this.set_cser_info({
cser_id: cser_id,
cser_name: cser_name,
......@@ -194,16 +297,16 @@ export default {
this.set_cser_name(cser_name);
},
cacheSignData(signData) {
Cookies.set('signData', JSON.stringify(signData), { expires: 30 });
Cookies.set("signData", JSON.stringify(signData), { expires: 30 });
this.set_signData(signData);
},
// 进入的页面地址是 https://companywx.jianshuwenhua.com/company_app/index.html?corp_id=wweaefe716636df3d1
// 1. 企微静默授权
async startWeComSilentAuth() {
this.urlParams = getParams();
const corp_id = Cookies.get('corp_id') || this.urlParams.corp_id;
const corp_id = Cookies.get("corp_id") || this.urlParams.corp_id;
if (!corp_id) {
this.$message.error('当前客服号信息异常,请切换会话后重试');
this.$message.error("当前客服号信息异常,请切换会话后重试");
return;
}
// 确定是第一次进入页面 没有 code 和 state
......@@ -225,17 +328,17 @@ export default {
this.cacheuserid(res.data.userid);
this.getUserList(res.data.userid);
} else {
this.$message.error('获取用户id失败');
this.$message.error("获取用户id失败");
return;
}
} else {
console.log('获取useid失败', res);
console.log("获取useid失败", res);
// 错误处理
}
},
async getSignature() {
console.log('获取签名', window.location.href);
const corp_id = Cookies.get('corp_id');
console.log("获取签名", window.location.href);
const corp_id = Cookies.get("corp_id");
try {
const res = await getSignature({
corp_id: corp_id,
......@@ -247,42 +350,42 @@ export default {
try {
this.registerWeComSDK();
} catch (err) {
console.log(err, '初始化sdk 失败');
console.log(err, "初始化sdk 失败");
}
}
} catch (err) {
console.log(err, '获取签名失败');
console.log(err, "获取签名失败");
window.location.href =
window.location.origin +
'/company_app/index.html?corp_id=' +
"/company_app/index.html?corp_id=" +
corp_id +
'&msg=signerror';
"&msg=signerror";
}
},
getCurExternalContact() {
this.$ww.getCurExternalContact({
success: (res) => {
if (res.err_msg === 'getCurExternalContact:ok') {
console.log(res, '重新进入获取企微外部联系人');
if (res.err_msg === "getCurExternalContact:ok") {
console.log(res, "重新进入获取企微外部联系人");
this.set_external_userid(res.userId);
// 确保 Vuex 状态更新后再跳转
this.$nextTick(() => {
this.$router.replace('/');
console.log(window.location.href, 'window.location.hrefuserInfo');
this.$router.replace("/");
console.log(window.location.href, "window.location.hrefuserInfo");
});
}
},
fail: (err) => {
console.log(err, '获取企微外部联系人失败');
console.log(err, "获取企微外部联系人失败");
// 错误处理
},
});
},
// 2. 注册企微JS-SDK
registerWeComSDK() {
console.log('删除企业签名', 1231);
console.log("删除企业签名", 1231);
this.$ww.register({
corpId: Cookies.get('corp_id'),
corpId: Cookies.get("corp_id"),
agentId: this.signData.agent_id,
jsApiList: jsApiList,
// getConfigSignature: () => Promise.resolve({
......@@ -298,12 +401,12 @@ export default {
signature: this.signData.agent_signature,
}),
onAgentConfigSuccess: (res) => {
console.log('注册成功可以调用企微 js-sdk', res);
console.log("注册成功可以调用企微 js-sdk", res);
// 注册成功后不立即获取外部联系人,等钉钉扫码后再获取
this.getCurExternalContact();
},
onAgentConfigFail: (err) => {
console.log('注册失败不能使用企微js-sdk', err);
console.log("注册失败不能使用企微js-sdk", err);
// 错误处理123
},
});
......@@ -322,15 +425,15 @@ export default {
},
initCurrentApp() {
const currentApp = this.orgList.find(
(item) => item.app_key === 'dingjigp0ksn9nbljdli'
(item) => item.app_key === "dingjigp0ksn9nbljdli"
);
this.$set(this, 'currentOrg', currentApp);
this.$set(this, "currentOrg", currentApp);
},
// 7. 钉钉扫码回调页面处理
async handleDingCallback(token) {
// 在这里处理钉钉扫码成功的回调
const corp_id = Cookies.get('corp_id');
if (token && token != 'undefined') {
const corp_id = Cookies.get("corp_id");
if (token && token != "undefined") {
setToken(token);
this.set_token(token);
// 获取签名
......@@ -338,9 +441,9 @@ export default {
} else {
window.location.href =
window.location.origin +
'/company_app/index.html?corp_id=' +
"/company_app/index.html?corp_id=" +
corp_id +
'&msg=notoken';
"&msg=notoken";
}
},
},
......
<template>
<div class="info-tab-content">
<div class="userDetailsPanel columnFlex">
<div class="content" v-loading="viewLoading">
<div class="content px-[10px]" v-loading="viewLoading">
<div v-if="chatUserDetails.is_phishing_account == 1" class="warnText">
<p>高风险玩家,请立即通知组长!!!!</p>
<p>
......
......@@ -11,7 +11,9 @@ module.exports = {
purge: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
darkMode: false,
theme: {
extend: {}
extend: {
}
},
variants: {
extend: {}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论