提交 c8006204 作者: 施汉文

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

上级 a21e58e2
...@@ -17,7 +17,7 @@ ...@@ -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"> --> <!-- <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0,shrink-to-fit=no,user-scalable=no"> -->
<script src="https://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script> <script src="https://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script>
<!-- iconpark CDN链接 --> <!-- 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> </head>
<body> <body>
<noscript> <noscript>
......
<template> <template>
<div id="app" class="mobile-app-wrapper"> <div id="app" class="mobile-app-wrapper">
<Debug /> <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> <router-view></router-view>
</div> </div>
</div>
<div <div
class="mobile-menu-bar w-[40px] overflow-hidden" class="mobile-menu-bar w-[40px] overflow-hidden"
v-if="token && external_userid && showMemberId" v-if="token && external_userid && showMemberId"
...@@ -40,8 +47,11 @@ ...@@ -40,8 +47,11 @@
<el-tooltip <el-tooltip
class="item" class="item"
effect="dark" effect="dark"
:disabled="item.path !== '/agentStatusManagement'" :content="
:content="'客服状态:' + csStatusInfo.text" item.path === '/agentStatusManagement'
? '客服状态:' + csStatusInfo.text
: item.label
"
placement="left" placement="left"
> >
<div <div
...@@ -63,18 +73,22 @@ ...@@ -63,18 +73,22 @@
</div> </div>
<!-- 普通菜单项 --> <!-- 普通菜单项 -->
<!-- <span >{{ item.label }}</span> --> <!-- <span >{{ item.label }}</span> -->
<iconpark-icon <el-tooltip
v-else v-else
class="item"
effect="dark"
:content="item.label"
placement="left"
>
<iconpark-icon
class="w-[14px] h-[14px]" class="w-[14px] h-[14px]"
:name="item.icon" :name="item.icon"
></iconpark-icon> ></iconpark-icon>
</el-tooltip>
</div> </div>
</el-menu-item> </el-menu-item>
</el-menu> </el-menu>
</div> </div>
<!-- 绑定的 w 账号 -->
<bindUserList />
</div> </div>
</div> </div>
</template> </template>
...@@ -85,6 +99,7 @@ import { mapState, mapMutations, mapActions } from "vuex"; ...@@ -85,6 +99,7 @@ import { mapState, mapMutations, mapActions } from "vuex";
import Cookies from "js-cookie"; import Cookies from "js-cookie";
import { getParams } from "@/utils/index"; import { getParams } from "@/utils/index";
import Debug from "@/components/debug.vue"; import Debug from "@/components/debug.vue";
import { getClientStatus } from "@/api/user";
export default { export default {
name: "App", name: "App",
...@@ -174,6 +189,7 @@ export default { ...@@ -174,6 +189,7 @@ export default {
"token", "token",
"userInfo", "userInfo",
"client_online_status", "client_online_status",
"userid",
]), ]),
...mapState("game", ["taskData"]), ...mapState("game", ["taskData"]),
// 计算任务列表是否需要显示红点 // 计算任务列表是否需要显示红点
...@@ -198,6 +214,10 @@ export default { ...@@ -198,6 +214,10 @@ export default {
}; };
return statusMap[this.client_online_status] || "未知"; return statusMap[this.client_online_status] || "未知";
}, },
title() {
return this.menuList.find((item) => item.path === this.$route.path)
?.label;
},
}, },
watch: { watch: {
"$route.path"(val) { "$route.path"(val) {
...@@ -258,6 +278,7 @@ export default { ...@@ -258,6 +278,7 @@ export default {
this.set_token(cookieToken); this.set_token(cookieToken);
console.log("从 Cookie 恢复 token:", cookieToken); console.log("从 Cookie 恢复 token:", cookieToken);
} }
// 初始化时处理路径 // 初始化时处理路径
const currentPath = this.$route.path; const currentPath = this.$route.path;
if ( if (
...@@ -277,6 +298,10 @@ export default { ...@@ -277,6 +298,10 @@ export default {
this.$nextTick(() => { this.$nextTick(() => {
this.checkMenuOverflow(); this.checkMenuOverflow();
this.initVuexValue(); this.initVuexValue();
// 获取客服状态和相关信息
if (this.userid && this.token) {
this.getInitialData();
}
}); });
}, },
beforeDestroy() { beforeDestroy() {
...@@ -291,6 +316,7 @@ export default { ...@@ -291,6 +316,7 @@ export default {
"set_cser_id", "set_cser_id",
"set_cser_name", "set_cser_name",
"set_userInfo", "set_userInfo",
"set_client_online_status",
]), ]),
...mapMutations("game", ["set_accountSelect"]), ...mapMutations("game", ["set_accountSelect"]),
...mapActions("game", ["getTaskUnReadData"]), ...mapActions("game", ["getTaskUnReadData"]),
...@@ -320,6 +346,25 @@ export default { ...@@ -320,6 +346,25 @@ export default {
handleSelect(key, keyPath) { handleSelect(key, keyPath) {
console.log("菜单选择:", key, keyPath, window.location.href); 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() { checkMenuOverflow() {
...@@ -442,8 +487,7 @@ export default { ...@@ -442,8 +487,7 @@ export default {
.mobile-content > div { .mobile-content > div {
background: #fff; background: #fff;
border-radius: 8px; border-radius: 8px;
min-height: 60vh; padding: 10px 0px;
padding: 10px;
} }
.el-menu--horizontal > .el-menu-item { .el-menu--horizontal > .el-menu-item {
...@@ -484,4 +528,7 @@ body { ...@@ -484,4 +528,7 @@ body {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.p-common {
padding: 0 10px;
}
</style> </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 @@ ...@@ -5,38 +5,36 @@
:current-page.sync="pageInfo.page" :current-page.sync="pageInfo.page"
:page-size="Number(pageInfo.page_size)" :page-size="Number(pageInfo.page_size)"
background background
layout="total,prev, pager, next, jumper" layout="prev, pager, next"
@current-change="handleCurrentChange" @current-change="handleCurrentChange"
> >
</el-pagination> </el-pagination>
</div> </div>
</template> </template>
<script type="text/javascript"> <script type="text/javascript">
export default { export default {
name: 'pageNum', name: "pageNum",
props: ['pageInfo'], props: ["pageInfo"],
data() { data() {
return {} return {};
},
mounted() {
}, },
mounted() {},
methods: { methods: {
handleCurrentChange(newPage) { handleCurrentChange(newPage) {
this.pageInfo.page = newPage this.pageInfo.page = newPage;
this.$emit('requestNextPage', this.pageInfo) this.$emit("requestNextPage", this.pageInfo);
} },
} },
} };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.newPage { .newPage {
width: 100%; width: 100%;
height: 60px; height: 60px;
background: #fff; background: #fff;
border-radius: 0 0 5px 5px; border-radius: 0 0 5px 5px;
padding-bottom: 20px; padding-bottom: 20px;
} }
</style> </style>
\ No newline at end of file
...@@ -80,6 +80,8 @@ const mutations = { ...@@ -80,6 +80,8 @@ const mutations = {
state.isWecomSDKReady = status state.isWecomSDKReady = status
}, },
set_client_online_status(state, status) { set_client_online_status(state, status) {
console.log('设置客服休息状态', status);
state.client_online_status = status state.client_online_status = status
} }
} }
......
<template> <template>
<div class="p-3 h-full"> <div class="!p-[12px] h-full">
<div class="text-[13px] text-[#131920] font-medium">在线客服</div>
<div class="px-[9px] pt-[60px] flex flex-col items-center justify-center"> <div class="px-[9px] pt-[60px] flex flex-col items-center justify-center">
<div class="h-[80px] w-[80px]"> <div class="h-[80px] w-[80px]">
<img :src="avatar" alt="" class="h-full w-full rounded-[6px]" /> <img :src="avatar" alt="" class="h-full w-full rounded-[6px]" />
...@@ -141,44 +140,11 @@ export default { ...@@ -141,44 +140,11 @@ export default {
return this.client_online_status; return this.client_online_status;
}, },
}, },
mounted() { mounted() {},
// 获取客服状态和相关信息
this.$nextTick(() => {
if (this.userid && this.token) {
this.getInitialData();
}
});
},
methods: { methods: {
...mapMutations("user", ["set_client_online_status"]), ...mapMutations("user", ["set_client_online_status"]),
...mapActions("user", ["initWecom"]), ...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() { logout() {
if (this.client_online_status === "rest") { if (this.client_online_status === "rest") {
......
<template> <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"> <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"> <div class="inputContent">
<el-form-item label="请输入w账号" prop="username"> <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-input>
</el-form-item> </el-form-item>
<el-form-item label="请输入主游戏名" prop="main_game_id"> <el-form-item label="请输入主游戏名" prop="main_game_id">
<el-select v-model="form.main_game_id" filterable remote clearable reserve-keyword placeholder="请输入主游戏名" <el-select
style="width: 100%;" :remote-method="remoteMethod" :loading="loading" @focus="gameNameList = optionsList"> v-model="form.main_game_id"
<el-option v-for="item in gameNameList" :key="item.value" :label="item.label" :value="item.value"> 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-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="请输入区服" prop="server_info"> <el-form-item label="请输入区服" prop="server_info">
<el-select v-model.trim="form.server_info" filterable remote :disabled="form.main_game_id == ''" clearable <el-select
style="width: 100%;" reserve-keyword placeholder="请先选择主游戏" :remote-method="remoteMethodServer" v-model.trim="form.server_info"
:loading="loading"> filterable
<el-option v-for="item in serverNameList" :key="item.id" :label="item.label" :value="item.value"> 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-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="请输入角色名" prop="role_name"> <el-form-item label="请输入角色名" prop="role_name">
<el-input 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-input>
</el-form-item> </el-form-item>
<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> </el-form-item>
</div> </div>
</el-form> </el-form>
<div class="table account_table"> <!-- <div class="table account_table">
<div class="bind-account-title"> <div class="bind-account-title">账号列表</div>
账号列表
</div>
<userTable :list="tableList" @checkedTag="checkedTag" /> <userTable :list="tableList" @checkedTag="checkedTag" />
</div> </div> -->
<!-- <div class="line"></div> w92865226508--> <!-- <div class="line"></div> w92865226508-->
<div v-if="userDetails.username" class="account_select_userInfo"> <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>
<div class="item rowFlex columnCenter"><span class="label">账号</span> <div class="item rowFlex columnCenter">
<p class="text">{{ userDetails.username }}</p> <span v-if="userDetails.account_type == 2" <span class="label">获客渠道</span>
class="account_type"></span>
</div>
<div class="item rowFlex columnCenter"><span class="label">获客渠道</span>
<p class="text">{{ userDetails.channel_name }}</p> <p class="text">{{ userDetails.channel_name }}</p>
</div> </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> <p class="text">{{ userDetails.register_channel_name }}</p>
</div> </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> <p class="text">{{ userDetails.operator_channel_name }}</p>
</div> </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> <p class="text">{{ userDetails.reg_game_name }}</p>
</div> </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> <p class="text">{{ userDetails.main_game_name }}</p>
</div> </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> <p class="text">{{ userDetails.real_name }}</p>
</div> </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> <p class="text">{{ userDetails.mobile }}</p>
</div> </div>
<div class="item rowFlex columnCenter"><span class="label">染色时间</span> <div class="item rowFlex columnCenter">
<p class="text">{{ moment(userDetails.seq_time * 1000).format('YYYY-MM-DD') }}</p> <span class="label">染色时间</span>
<p class="text">
{{ moment(userDetails.seq_time * 1000).format("YYYY-MM-DD") }}
</p>
</div> </div>
<div class="item rowFlex columnCenter"><span class="label">注册时间</span> <div class="item rowFlex columnCenter">
<p class="text">{{ moment(userDetails.reg_time * 1000).format('YYYY-MM-DD') }}</p> <span class="label">注册时间</span>
<p class="text">
{{ moment(userDetails.reg_time * 1000).format("YYYY-MM-DD") }}
</p>
</div> </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> <p class="text">{{ userDetails.last_login_os }}</p>
</div> </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> <p class="text">{{ userDetails.recharge_total }}</p>
</div> </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> <p class="text">{{ userDetails.wechat_add_status_text }}</p>
</div> </div>
</div> </div>
</div> </div>
<page class="pageInfo" :page-info="pageInfo" @requestNextPage="requestNextPage" /> <page
<span class="dialog-footer rowFlex"> class="pageInfo"
<el-button class="btn" type="primary" size="small" :disabled="!userDetails.id" @click="confirmSubmit"> :page-info="pageInfo"
</el-button> @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> <el-button class="btn" size="small" @click="close">取 消</el-button>
</span> </span> -->
</el-drawer> </Drawer>
</template> </template>
<script type="text/javascript"> <script type="text/javascript">
import moment from 'moment' import moment from "moment";
import userTable from './userTable.vue' import userTable from "./userTable.vue";
import { getRoleHoLo, memberView, selectSearch } from '@/api/game' import { getRoleHoLo, memberView, selectSearch } from "@/api/game";
import { checkZyouBind,zyouBind } from '@/api/works' import { checkZyouBind, zyouBind } from "@/api/works";
import { mapMutations, mapActions, mapState } from 'vuex' import { mapMutations, mapActions, mapState } from "vuex";
import page from '@/components/page/pageNum.vue' import page from "@/components/page/pageNum.vue";
export default { import Drawer from "@/components/common/Drawer.vue";
name: 'addUser', import { debounce } from "@/utils/index";
export default {
name: "addUser",
components: { components: {
userTable, userTable,
page page,
Drawer,
}, },
props: ['show'], props: ["show"],
data() { data() {
return { return {
moment, moment,
inputValue: "",
tableList: [], tableList: [],
checkoutUser: {}, checkoutUser: {},
userDetails: {}, userDetails: {},
...@@ -117,221 +314,246 @@ ...@@ -117,221 +314,246 @@
pageInfo: { pageInfo: {
page: 1, page: 1,
page_size: 20, page_size: 20,
total: 0 total: 0,
}, },
form: { form: {
member_id: '', member_id: "",
username: '', username: "",
role_name: '', role_name: "",
main_game_id: '', main_game_id: "",
server_info: '' server_info: "",
}, },
gameNameList: [], gameNameList: [],
optionsList: [], optionsList: [],
serverNameList: [], serverNameList: [],
rules: { rules: {},
};
}
}
}, },
computed: { computed: {
...mapState('game', ['chatUserInfo','userid','external_userid']), ...mapState("game", ["chatUserInfo", "userid", "external_userid"]),
}, },
watch: { watch: {
show(newVal, oldVal) { show(newVal, oldVal) {
if (newVal) { if (newVal) {
// this.requestRoleList() // this.requestRoleList()
this.requestGameList() this.requestGameList();
}
} }
}, },
mounted() {
}, },
mounted() {},
methods: { methods: {
...mapActions('game', ['gameBindUser']), ...mapActions("game", ["gameBindUser"]),
...mapMutations('game', ['set_accountSelect']), ...mapMutations("game", ["set_accountSelect"]),
requestRoleList() { requestRoleList() {
const data = { const data = {
member_id: this.form.member_id, member_id: this.form.member_id,
username: this.form.username.trim(), username: this.form.username.trim(),
role_name: this.form.role_name.trim(), role_name: this.form.role_name.trim(),
main_game_id: this.form.main_game_id !== '' ? [this.form.main_game_id] : [], main_game_id:
server_info: this.form.server_info !== '' ? [this.form.server_info] : [], this.form.main_game_id !== "" ? [this.form.main_game_id] : [],
search_type: 'bind', server_info:
...this.pageInfo this.form.server_info !== "" ? [this.form.server_info] : [],
} search_type: "bind",
getRoleHoLo(data).then(res => { ...this.pageInfo,
};
getRoleHoLo(data).then((res) => {
if (res.status_code == 1) { if (res.status_code == 1) {
if (res.data.data.length == 0) { if (res.data.data.length == 0) {
this.tableList = [] this.tableList = [];
this.$message.warning('暂无数据') this.$message.warning("暂无数据");
} else { } else {
this.tableList = res.data.data this.tableList = res.data.data;
this.pageInfo = res.data.page_info this.pageInfo = res.data.page_info;
} }
} }
}) });
}, },
// S181.啊呸¤可瑞 八荒181服 // S181.啊呸¤可瑞 八荒181服
// 分页 // 分页
requestNextPage(pageInfo) { requestNextPage(pageInfo) {
this.pageInfo.page = pageInfo.page this.pageInfo.page = pageInfo.page;
this.requestRoleList() this.requestRoleList();
}, },
remoteMethodServer(query) { remoteMethodServer(query) {
if (query !== '') { if (query !== "") {
this.loading = true this.loading = true;
const data = { const data = {
type: 'server_info', type: "server_info",
value: query, value: query,
main_game_ids: this.form.main_game_id main_game_ids: this.form.main_game_id,
} };
selectSearch(data).then(res => { selectSearch(data).then((res) => {
this.loading = false this.loading = false;
if (res.status_code == 1) { if (res.status_code == 1) {
this.serverNameList = res.data.data this.serverNameList = res.data.data;
} }
}) });
} }
}, },
remoteMethod(query) { remoteMethod(query) {
if (query !== '') { if (query !== "") {
this.gameNameList = this.optionsList.filter(item => { this.gameNameList = this.optionsList.filter((item) => {
return item.label.toLowerCase() return item.label.toLowerCase().indexOf(query.toLowerCase()) > -1;
.indexOf(query.toLowerCase()) > -1 });
})
} else { } else {
this.gameNameList = [] this.gameNameList = [];
} }
}, },
requestGameList() { requestGameList() {
const data = { const data = {
type: 'mainGameList', type: "mainGameList",
value: '', value: "",
weixin_blong_id: '' weixin_blong_id: "",
} };
selectSearch(data).then(res => { selectSearch(data).then((res) => {
this.loading = false this.loading = false;
if (res.status_code == 1) { if (res.status_code == 1) {
this.gameNameList = this.optionsList = res.data.data this.gameNameList = this.optionsList = res.data.data;
} }
}) });
}, },
close() { close() {
this.$emit('update:show', false) this.$emit("update:show", false);
this.resizeData() this.resizeData();
this.$emit('close') this.$emit("close");
}, },
// 防抖处理输入变化,300毫秒延迟
handleChange: debounce(function () {
if (this.inputValue == "") {
return;
}
this.onSubmit();
}, 300),
onSubmit() { onSubmit() {
this.$refs.form.validate((valid) => { this.$refs.form.validate((valid) => {
this.pageInfo = { this.pageInfo = {
page: 1, page: 1,
page_size: 20, page_size: 20,
total: 0 total: 0,
} };
if (valid) { if (valid) {
if (this.form.role_name == '' && this.form.username == '') { if (this.inputValue == "") {
this.$message.warning('请输入角色名或者w账号') this.$message.warning("请输入角色名或者w账号");
return 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 { } else {
console.log('error submit!!') console.log("error submit!!");
return false return false;
} }
}) });
},
expandTag(item) {
console.log(item);
}, },
resizeData() { resizeData() {
this.form = { this.form = {
member_id: '', member_id: "",
username: '', username: "",
role_name: '', role_name: "",
main_game_id: '', main_game_id: "",
server_info: '' server_info: "",
} };
this.tableList = [] this.inputValue = "";
this.checkoutUser = {} this.tableList = [];
this.userDetails = {} this.checkoutUser = {};
this.userDetails = {};
}, },
confirmSubmit() { confirmSubmit() {
const data = { const data = {
member_id: this.userDetails.id && this.userDetails.id != '' ? this.userDetails.id : this.checkoutUser.member_id, member_id:
username: this.userDetails.username this.userDetails.id && this.userDetails.id != ""
} ? this.userDetails.id
checkZyouBind(data).then(res => { : this.checkoutUser.member_id,
console.log(data) username: this.userDetails.username,
};
checkZyouBind(data).then((res) => {
console.log(data);
if (!res.data.has_bind) { if (!res.data.has_bind) {
this.submit() this.submit();
} else { } else {
this.$confirm(res.data.tip || '', { this.$confirm(res.data.tip || "", {
confirmButtonText: '确定', confirmButtonText: "确定",
cancelButtonText: '取消', cancelButtonText: "取消",
type: 'warning' type: "warning",
}) })
.then(() => { .then(() => {
this.submit() this.submit();
}) })
.catch((err) => { .catch((err) => {
console.log(err) console.log(err);
this.$message({ this.$message({
type: 'info', type: "info",
message: '已取消删除' message: "已取消删除",
}) });
}) });
} }
}) });
}, },
submit() { submit() {
const data = { const data = {
userid: this.chatUserInfo.userid || this.userid, userid: this.chatUserInfo.userid || this.userid,
external_userid: this.chatUserInfo.external_userid || this.external_userid, external_userid:
member_id: this.userDetails.id && this.userDetails.id != '' ? this.userDetails.id : this.checkoutUser.member_id, 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, username: this.userDetails.username,
reg_game_id: this.userDetails.reg_game_id, reg_game_id: this.userDetails.reg_game_id,
main_game_id: this.userDetails.main_game_id, main_game_id: this.userDetails.main_game_id,
recharge_total: this.userDetails.recharge_total, recharge_total: this.userDetails.recharge_total,
} };
// 绑定掌游账号 // 绑定掌游账号
zyouBind(data).then(res => { zyouBind(data).then((res) => {
if (res.status_code == 1) { if (res.status_code == 1) {
this.$message.success(res.msg) this.$message.success(res.msg);
this.updateData() this.updateData();
} }
}) });
}, },
// 更新列表数据 // 更新列表数据
updateData() { updateData() {
const data = { const data = {
userid: this.chatUserInfo.userid, userid: this.chatUserInfo.userid,
external_userid: this.chatUserInfo.external_userid external_userid: this.chatUserInfo.external_userid,
} };
this.gameBindUser(data).then(res => { this.gameBindUser(data).then((res) => {
this.set_accountSelect(this.userDetails.id) this.set_accountSelect(this.userDetails.id);
this.close() this.close();
}) });
}, },
// 勾选活码 // 勾选活码
checkedTag(value) { checkedTag(value) {
this.checkoutUser = value console.log(1);
this.checkoutUser = value;
const data = { const data = {
member_id: value.member_id, member_id: value.member_id,
need_channel: 1, need_channel: 1,
need_roleInfo: 1 need_roleInfo: 1,
} };
this.rquestUserInfo(data) this.rquestUserInfo(data);
}, },
rquestUserInfo(data) { rquestUserInfo(data) {
memberView(data).then(res => { memberView(data).then((res) => {
if (res.status_code == 1) { if (res.status_code == 1) {
this.userDetails = res.data this.userDetails = res.data;
} }
}) });
} },
} },
} };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
::v-deep .el-drawer { ::v-deep .el-drawer {
...@@ -410,7 +632,6 @@ ...@@ -410,7 +632,6 @@
} }
} }
} }
} }
.account_table { .account_table {
...@@ -429,7 +650,7 @@ ...@@ -429,7 +650,7 @@
} }
.pageInfo { .pageInfo {
width: calc(100% - 20px); width: 100%;
height: 82px; height: 82px;
position: absolute; position: absolute;
right: 20px; right: 20px;
...@@ -438,7 +659,7 @@ ...@@ -438,7 +659,7 @@
} }
.dialog-footer { .dialog-footer {
width: calc(100% - 20px); width: 100%;
position: absolute; position: absolute;
right: 20px; right: 20px;
bottom: 0; bottom: 0;
...@@ -454,9 +675,26 @@ ...@@ -454,9 +675,26 @@
height: 32px; height: 32px;
} }
} }
</style> ::v-deep .el-input-group--prepend .el-input__inner {
<style> border-top-left-radius: 4px;
::v-deep .el-select-dropdown { border-bottom-left-radius: 4px;
min-width: 210px !important; }
.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> </style>
<template> <template>
<div class="bindUserList rowFlex columnCenter"> <div class="bindUserList rowFlex columnCenter !pt-0 !px-[10px]">
<div class="select"> <div class="select">
<el-select <el-select
v-model="bindAccount" v-model="bindAccount"
placeholder="请选择关联账号" placeholder="请选择关联账号"
:clearable="false" :clearable="false"
class="w-[258px]"
:class="{ 'show-number': bindGameUserList.length > 0 }"
:style="{ '--number': `'${bindGameUserList.length}'` }"
@change="handleChange" @change="handleChange"
> >
<el-option label="新增关联账号" value="add" @click="addNewUser"> <!-- <el-option label="新增关联账号" value="add" @click="addNewUser">
</el-option> </el-option> -->
<el-option <el-option
v-for="(item, index) in bindGameUserList" v-for="(item, index) in bindGameUserList"
:key="index" :key="index"
...@@ -34,9 +37,15 @@ ...@@ -34,9 +37,15 @@
</el-option> </el-option>
</el-select> </el-select>
</div> </div>
<p v-if="bindGameUserList.length > 0" class="num"> <!-- <p v-if="bindGameUserList.length > 0" class="num">
总共{{ bindGameUserList.length }}个账号 总共{{ 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 <addUser
:show.sync="showLayer" :show.sync="showLayer"
title="选择玩家" title="选择玩家"
...@@ -102,11 +111,7 @@ export default { ...@@ -102,11 +111,7 @@ export default {
...mapMutations("user", ["set_avatar"]), ...mapMutations("user", ["set_avatar"]),
...mapActions("game", ["gameBindUser"]), ...mapActions("game", ["gameBindUser"]),
handleChange(value) { handleChange(value) {
if (value == "add") {
this.showLayer = true;
} else {
this.set_accountSelect(value); this.set_accountSelect(value);
}
}, },
close() { close() {
this.bindAccount = this.accountSelect; this.bindAccount = this.accountSelect;
...@@ -137,7 +142,7 @@ export default { ...@@ -137,7 +142,7 @@ export default {
} }
}, },
addNewUser() { addNewUser() {
console.log(11); this.showLayer = true;
}, },
async requestDetails() { async requestDetails() {
const data = { const data = {
...@@ -186,53 +191,24 @@ export default { ...@@ -186,53 +191,24 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.bindUserList { .show-number ::v-deep .el-input {
margin: 10px; position: relative;
&:after {
.select { display: flex;
::v-deep .el-input--small .el-input__inner { justify-content: center;
border-radius: 4px; align-items: center;
border: 1px solid #e4e7ed; content: var(--number);
min-width: 200px; height: 20px;
height: 32px; width: 20px;
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 {
font-size: 12px; font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC; color: #267ef0;
font-weight: 600; background: #e7f1fd;
margin-left: 10px; border-radius: 50%;
white-space: nowrap;
color: #f53f3f;
}
::v-deep .el-button--danger { position: absolute;
background-color: #f56c6c; top: 50%;
border-color: #f56c6c; transform: translateY(-50%);
right: 30px;
&:hover,
&:focus {
background-color: #f78989;
border-color: #f78989;
}
} }
} }
</style> </style>
<template> <template>
<div class="skillLibrary"> <div class="skillLibrary">
<div v-loading="loading" class="rowFlex skillBox"> <div v-loading="loading" class="rowFlex skillBox pl-[10px]">
<!-- 标签 --> <!-- 标签 -->
<el-collapse-transition> <el-collapse-transition>
<div v-if="groupList.length > 0" class="tagList columnFlex"> <div
<div v-for="(item, index) in groupList" :key="index" class="tagItem columnCenter" :draggable="false" 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' : ''" :class="groupActive == item.value ? 'tagItemActiveText' : ''"
@dragstart="handleDragStart($event, item, index)" @dragover.prevent="handleDragOver($event, item)" @dragstart="handleDragStart($event, item, index)"
@dragenter="handleDragEnter($event, item, 'group')" @dragend="handleDragEnd($event, item, 'group')"> @dragover.prevent="handleDragOver($event, item)"
<div class="rowFlex columnCenter spaceBetween tagItemGroup" @click="groupFilter(item, index)"> @dragenter="handleDragEnter($event, item, 'group')"
@dragend="handleDragEnd($event, item, 'group')"
>
<div
class="rowFlex columnCenter spaceBetween tagItemGroup"
@click="groupFilter(item, index)"
>
<div class="rowFlex columnCenter"> <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> <p class="text hidden">{{ item.name }}</p>
</el-tooltip> </el-tooltip>
<p v-else class="text hidden">{{ item.name }}</p> <p v-else class="text hidden">{{ item.name }}</p>
</div> </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>
<!-- 二级分组 --> <!-- 二级分组 -->
<div v-if="item.child.length > 0 && groupActive == item.value" class="childGroup"> <div
<div v-for="child in item.child" :key="child._id" class="childGroupText" v-if="item.child.length > 0 && groupActive == item.value"
:class="[groupActiveChild == child._id ? 'tagItemActive' : '']" @click.stop="groupFilterChild(child)"> 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> <p class="text hidden">{{ child.name }}</p>
</div> </div>
</div> </div>
...@@ -33,27 +62,67 @@ ...@@ -33,27 +62,67 @@
<!-- 话术 --> <!-- 话术 -->
<div class="libraryListContent"> <div class="libraryListContent">
<div class="inputContent"> <div class="inputContent">
<el-input v-model="requestData.title" placeholder="请输入话术内容" class="input-with-select"> <el-input
<el-button slot="append" icon="el-icon-search" @click="contentSearch"></el-button> v-model="requestData.title"
placeholder="请输入话术内容"
class="input-with-select"
>
<el-button
slot="append"
icon="el-icon-search"
@click="contentSearch"
></el-button>
</el-input> </el-input>
</div> </div>
<div ref="skillLibrary" v-loading="skillLoading" @scroll="paperScroll" class="scrollList"> <div
<div v-for="(items, indexs) in groupDataList" :key="indexs" class="answerContent"> ref="skillLibrary"
<div class="question"><span class="title">Q:</span>{{ items.question }}</div> v-loading="skillLoading"
<div v-for="(answer, answerIndex) in items.answer" :key="answerIndex" class="answerItem" @scroll="paperScroll"
style="width: 100%"> 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> --> <!-- <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> <span class="title rowFlex">A{{ answerIndex + 1 }}:</span>
<p v-if="answer.msgtype == 'text'" class="rowFlex textAnswer flex1"> <p
{{ answer.text.content || '' }} v-if="answer.msgtype == 'text'"
class="rowFlex textAnswer flex1 break-all"
>
{{ answer.text.content || "" }}
</p> </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>
<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> <span class="title rowFlex">A{{ answerIndex + 1 }}:</span>
<el-image style="max-width: 200px" :src="answer.image.picurl" <el-image
@click="sendMessageImage(answer, items._id)" :preview-src-list="[answer.image.picurl]"> </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> </div>
</div> </div>
...@@ -65,26 +134,34 @@ ...@@ -65,26 +134,34 @@
<script> <script>
// procedure_group, procedureList, procedureSort, procedureGroupSort, skillQuote, // procedure_group, procedureList, procedureSort, procedureGroupSort, skillQuote,
import { cross_corp_robot_knowledge_group_index, cross_corp_robot_knowledge_group_getList } from '@/api/skill' import {
import { mapState, mapMutations, mapActions } from 'vuex' cross_corp_robot_knowledge_group_index,
import { throttle, debounce, copyToClipboard, sendChatMessage } from '@/utils/index' cross_corp_robot_knowledge_group_getList,
import noContent from '@/components/noContent.vue' } 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 { export default {
name: 'skillLibrary', name: "skillLibrary",
components: { components: {
noContent noContent,
}, },
props: { props: {
activeName: { activeName: {
default: '', default: "",
type: String type: String,
} },
}, },
data() { data() {
return { return {
collapseActive: '', collapseActive: "",
groupActive: '0', groupActive: "0",
groupActiveChild: '0', groupActiveChild: "0",
activeGroup: {}, activeGroup: {},
groupList: [], groupList: [],
groupLastList: [], groupLastList: [],
...@@ -93,93 +170,93 @@ export default { ...@@ -93,93 +170,93 @@ export default {
pageInfo: { pageInfo: {
page: 1, page: 1,
page_size: 20, page_size: 20,
total: 0 total: 0,
}, },
skillLoading: false, skillLoading: false,
loading: false, loading: false,
requestData: { requestData: {
title: '', title: "",
first_group_id: '', first_group_id: "",
second_group_id: '' second_group_id: "",
}, },
sortType: '', sortType: "",
sortID: { sortID: {
_id: '', _id: "",
before_id: '', before_id: "",
after_id: '' after_id: "",
}, },
filterText: {}, filterText: {},
dragging: null, dragging: null,
orderList: [ orderList: [
{ label: '知识库', type: 'library' }, { label: "知识库", type: "library" },
{ label: '个人话术', type: 'personal' }, { label: "个人话术", type: "personal" },
{ label: '企业话术', type: 'company' } { label: "企业话术", type: "company" },
] ],
} };
}, },
computed: { computed: {
...mapState('game', ['accountSelect', 'chatUserInfo']), ...mapState("game", ["accountSelect", "chatUserInfo"]),
}, },
watch: { watch: {
accountSelect(newVal, oldVal) { accountSelect(newVal, oldVal) {
if (newVal && newVal !== '') { if (newVal && newVal !== "") {
this.pageInfo = { this.pageInfo = {
page: 1, page: 1,
page_size: 20, page_size: 20,
total: 0 total: 0,
} };
} }
}, },
activeName(newVal, oldVal) { activeName(newVal, oldVal) {
if (newVal == 'library' && newVal != oldVal) { if (newVal == "library" && newVal != oldVal) {
this.resizeSelect() this.resizeSelect();
this.requestLibraryData() this.requestLibraryData();
}
} }
}, },
},
mounted() { mounted() {
this.requestLibraryData() this.requestLibraryData();
}, },
methods: { methods: {
sendMessage: throttle(function (item, id) { sendMessage: throttle(function (item, id) {
console.log(item, id) console.log(item, id);
// this.skillQuote(id, item.length) // this.skillQuote(id, item.length)
}, 500), }, 500),
handleDragStart(e, item, index) { handleDragStart(e, item, index) {
this.sortID._id = item._id this.sortID._id = item._id;
this.dragging = item this.dragging = item;
}, },
paperScroll: debounce(function () { paperScroll: debounce(function () {
const el = this.$refs.skillLibrary const el = this.$refs.skillLibrary;
if (el.offsetHeight + el.scrollTop + 10 >= el.scrollHeight) { if (el.offsetHeight + el.scrollTop + 10 >= el.scrollHeight) {
console.log('下一页') console.log("下一页");
this.pageInfo.page++ this.pageInfo.page++;
this.searchTable() this.searchTable();
} }
}, 500), }, 500),
skillQuote(id, num) { skillQuote(id, num) {
const data = { const data = {
type: this.activeName, type: this.activeName,
procedure_id: id, procedure_id: id,
quote_count: num || 1 quote_count: num || 1,
} };
skillQuote(data).then((res) => { skillQuote(data).then((res) => {
console.log(res) console.log(res);
}) });
}, },
sortSkill() { sortSkill() {
procedureSort(this.sortID).then((res) => { procedureSort(this.sortID).then((res) => {
if (res.status_code == 1) { if (res.status_code == 1) {
this.$message.success(res.msg) this.$message.success(res.msg);
} }
}) });
}, },
sortSkillGroup() { sortSkillGroup() {
procedureGroupSort(this.sortID).then((res) => { procedureGroupSort(this.sortID).then((res) => {
if (res.status_code == 1) { if (res.status_code == 1) {
this.$message.success(res.msg) this.$message.success(res.msg);
} }
}) });
}, },
// 发送语音的时候 先编辑再发送 // 发送语音的时候 先编辑再发送
sendMessageEdit(item, id) { sendMessageEdit(item, id) {
...@@ -189,98 +266,107 @@ export default { ...@@ -189,98 +266,107 @@ export default {
item.text.content, item.text.content,
(message) => this.$message.success(message), (message) => this.$message.success(message),
(message) => this.$message.error(message) (message) => this.$message.error(message)
) );
} }
this.sendChatMessage(item.text.content || '', 'text') this.sendChatMessage(item.text.content || "", "text");
}, },
sendMessageImage(item) { sendMessageImage(item) {
console.log(item, 'item') console.log(item, "item");
this.sendChatMessage(item.image.picurl || '', 'image') this.sendChatMessage(item.image.picurl || "", "image");
}, },
contentSearch() { contentSearch() {
this.pageInfo = { this.pageInfo = {
page: 1, page: 1,
page_size: 20, page_size: 20,
total: 0 total: 0,
} };
this.searchTable('msg') this.searchTable("msg");
}, },
// 知识库话术 // 知识库话术
requestLibraryData() { requestLibraryData() {
console.log(this.chatUserInfo, 'chatUserInfo') console.log(this.chatUserInfo, "chatUserInfo");
this.loading = true this.loading = true;
const data = { const data = {
page: 1, page: 1,
page_size: 100, page_size: 100,
userid: this.chatUserInfo.userid userid: this.chatUserInfo.userid,
} };
cross_corp_robot_knowledge_group_index(data).then((res) => { cross_corp_robot_knowledge_group_index(data).then((res) => {
this.loading = false this.loading = false;
if (res.data.data) { if (res.data.data) {
res.data.data.unshift({ res.data.data.unshift({
name: '全部分组', name: "全部分组",
value: '', value: "",
child: [] child: [],
}) });
this.groupList = res.data.data.map((item, index) => { this.groupList = res.data.data.map((item, index) => {
item.label = item.name item.label = item.name;
item.value = item._id item.value = item._id;
return item return item;
}) });
this.groupLastList = this.groupList this.groupLastList = this.groupList;
this.groupFilter(this.groupList[0]) this.groupFilter(this.groupList[0]);
} else { } else {
this.groupList = [] this.groupList = [];
this.groupLastList = [] this.groupLastList = [];
} }
}) });
}, },
groupFilter(item, index) { groupFilter(item, index) {
if (!item._id) { if (!item._id) {
this.requestData.second_group_id = '' this.requestData.second_group_id = "";
this.activeGroup = {} this.activeGroup = {};
} }
this.groupActive = item.value this.groupActive = item.value;
item.child && item.child[0] ? ((this.activeGroup = item.child[0]), (this.groupActiveChild = item.child[0]._id)) : '' item.child && item.child[0]
this.searchTable() ? ((this.activeGroup = item.child[0]),
(this.groupActiveChild = item.child[0]._id))
: "";
this.searchTable();
}, },
groupFilterChild(child) { groupFilterChild(child) {
this.groupActiveChild = 0 this.groupActiveChild = 0;
this.activeGroup = child this.activeGroup = child;
this.groupActiveChild = child._id this.groupActiveChild = child._id;
this.searchTable() this.searchTable();
this.$forceUpdate() this.$forceUpdate();
}, },
// 搜索结果 // 搜索结果
async searchTable(msg) { async searchTable(msg) {
this.skillLoading = true this.skillLoading = true;
this.requestData.second_group_id = this.activeGroup._id || '' this.requestData.second_group_id = this.activeGroup._id || "";
this.requestData.title = this.requestData.title.trim() this.requestData.title = this.requestData.title.trim();
const data = { ...this.requestData, ...this.pageInfo, log_scan: msg ? 1 : 0, userid: this.chatUserInfo.userid } const data = {
...this.requestData,
...this.pageInfo,
log_scan: msg ? 1 : 0,
userid: this.chatUserInfo.userid,
};
cross_corp_robot_knowledge_group_getList(data).then((res) => { cross_corp_robot_knowledge_group_getList(data).then((res) => {
this.skillLoading = false this.skillLoading = false;
this.pageInfo.page === 1 ? this.groupDataList = res.data.data : this.groupDataList = this.groupDataList.concat(res.data.data) this.pageInfo.page === 1
this.groupLastDataList = this.groupDataList ? (this.groupDataList = res.data.data)
}) : (this.groupDataList = this.groupDataList.concat(res.data.data));
this.groupLastDataList = this.groupDataList;
});
}, },
handleChange() { }, handleChange() {},
// 重置select // 重置select
resizeSelect() { resizeSelect() {
this.groupActive = '0' this.groupActive = "0";
this.isResize = true this.isResize = true;
this.groupDataList = [] this.groupDataList = [];
this.requestData.content = '' this.requestData.content = "";
this.pageInfo.page = 1 this.pageInfo.page = 1;
setTimeout(() => { setTimeout(() => {
this.isResize = false this.isResize = false;
}, 2000) }, 2000);
}, },
sendChatMessage(content, type) { sendChatMessage(content, type) {
sendChatMessage(content, type) sendChatMessage(content, type);
}, },
} },
} };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.skillLibrary { .skillLibrary {
...@@ -321,7 +407,7 @@ export default { ...@@ -321,7 +407,7 @@ export default {
font-size: 14px; font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC; font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400; font-weight: 400;
color: #409EFF; color: #409eff;
margin-right: 10px; margin-right: 10px;
} }
...@@ -457,8 +543,8 @@ export default { ...@@ -457,8 +543,8 @@ export default {
.inputContent { .inputContent {
width: 100%; width: 100%;
margin-bottom: 20px; margin-bottom: 20px;
margin-left: 20px; margin-left: 10px;
margin-right: 10px;
::v-deep .el-input { ::v-deep .el-input {
width: 90%; width: 90%;
} }
...@@ -467,7 +553,6 @@ export default { ...@@ -467,7 +553,6 @@ export default {
.skillBox { .skillBox {
width: 100%; width: 100%;
height: calc(100% - 20px); height: calc(100% - 20px);
} }
.tagList { .tagList {
...@@ -513,14 +598,14 @@ export default { ...@@ -513,14 +598,14 @@ export default {
} }
.tagItemActive { .tagItemActive {
color: #409EFF !important; color: #409eff !important;
font-family: PingFangSC-Regular, PingFang SC; font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400; font-weight: 400;
background: #e4fff1; background: #e4fff1;
} }
.tagItemActiveText { .tagItemActiveText {
color: #409EFF; color: #409eff;
} }
} }
...@@ -555,7 +640,7 @@ export default { ...@@ -555,7 +640,7 @@ export default {
.scrollList { .scrollList {
width: 100%; width: 100%;
height: 100%; height: 100%;
padding-left: 20px; padding-left: 10px;
.answerContent { .answerContent {
width: 100%; width: 100%;
...@@ -607,7 +692,7 @@ export default { ...@@ -607,7 +692,7 @@ export default {
.copyIcon { .copyIcon {
width: 20px; width: 20px;
color: #409EFF; color: #409eff;
font-size: 16px; font-size: 16px;
position: relative; position: relative;
top: 2px; top: 2px;
...@@ -619,7 +704,7 @@ export default { ...@@ -619,7 +704,7 @@ export default {
} }
.scrollList::-webkit-scrollbar { .scrollList::-webkit-scrollbar {
display: none display: none;
} }
.container { .container {
...@@ -676,7 +761,7 @@ export default { ...@@ -676,7 +761,7 @@ export default {
} }
.skillLibrary::-webkit-scrollbar { .skillLibrary::-webkit-scrollbar {
display: none display: none;
} }
::v-deep .el-icon-circle-close { ::v-deep .el-icon-circle-close {
......
<template> <template>
<div class="skillTab"> <div class="skillTab">
<div class="inputContent"> <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-button slot="append" icon="el-icon-search"></el-button>
</el-input> </el-input>
</div> </div>
<div v-loading="loading" class="rowFlex skillBox"> <div v-loading="loading" class="rowFlex skillBox pl-[10px]">
<!-- 标签 --> <!-- 标签 -->
<el-collapse-transition> <el-collapse-transition>
<div v-if="groupList.length > 0" class="tagList columnFlex"> <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" :draggable="activeName == 'personal' ? true : false"
:class="groupActive == item.value ? 'tagItemActive' : ''" @dragstart="handleDragStart($event, item, index)" :class="groupActive == item.value ? 'tagItemActive' : ''"
@dragover.prevent="handleDragOver($event, item)" @dragenter="handleDragEnter($event, item, 'group')" @dragstart="handleDragStart($event, item, index)"
@dragend="handleDragEnd($event, item, 'group')"> @dragover.prevent="handleDragOver($event, item)"
<el-tooltip effect="dark" placement="top" :content="item.group_name" v-if="item.group_name.length >= 6"> @dragenter="handleDragEnter($event, item, 'group')"
<p class="text hidden" @click="groupFilter(item, index)">{{ item.group_name }}</p> @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> </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> </div>
<div v-else>暂无话术内容</div> <div v-else>暂无话术内容</div>
</el-collapse-transition> </el-collapse-transition>
<!-- 话术 --> <!-- 话术 -->
<div v-loading="skillLoading" class="scrollList"> <div v-loading="skillLoading" class="scrollList px-[10px]">
<el-collapse v-model="collapseActive" @change="handleChange"> <el-collapse v-model="collapseActive" @change="handleChange">
<transition-group v-if="groupDataList.length > 0" tag="div" class="container"> <transition-group
<div v-for="(items, indexs) in groupDataList" :key="indexs" v-if="groupDataList.length > 0"
:draggable="activeName == 'personal' ? true : false" class="draggable" tag="div"
@dragstart="handleDragStart($event, items, indexs)" @dragover.prevent="handleDragOver($event, items)" class="container"
@dragenter="handleDragEnter($event, items, 'item')" @dragend="handleDragEnd($event, items, 'item')"> >
<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"> <el-popover placement="top" width="300" trigger="hover">
<p>{{ items.title }}</p> <p>{{ items.title }}</p>
<div slot="reference" class="contentItemTitle allCenter" <div
:style="{ top: items.title.length > 8 ? '5px' : '13px' }">{{ items.title }}</div> slot="reference"
class="contentItemTitle allCenter"
:style="{ top: items.title.length > 8 ? '5px' : '13px' }"
>
{{ items.title }}
</div>
</el-popover> </el-popover>
<div class="rowFlex titleFixed columnCenter"> <div class="rowFlex titleFixed columnCenter">
<div class="num">{{ items.message && items.message.attachments && items.message.attachments.length > 1 ? <div class="num">
`+${items.message.attachments.length - 1}条` : '' }}</div> {{
items.message &&
items.message.attachments &&
items.message.attachments.length > 1
? `+${items.message.attachments.length - 1}条`
: ""
}}
</div>
</div> </div>
<el-collapse-item title="" :name="items._id" class="contentItem"> <el-collapse-item title="" :name="items._id" class="contentItem">
<div v-for="(i, j) in items.message.attachments" :key="j"> <div v-for="(i, j) in items.message.attachments" :key="j">
<div> <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> <div class="text">{{ i.text.content }}</div>
<el-button class="sendButton rowFlex allCenter" <el-button
@click.stop="sendMessageEdit(i, items._id)">发送</el-button> class="sendButton rowFlex allCenter"
@click.stop="sendMessageEdit(i, items._id)"
>发送</el-button
>
</div> </div>
<div v-if="i.msgtype == 'image'" class="contentItemDetails rowFlex spaceBetween columnCenter"> <div
<el-image class="image" :src="i.image.picurl" :preview-src-list="[i.image.picurl]" v-if="i.msgtype == 'image'"
fit="contain"></el-image> class="contentItemDetails rowFlex spaceBetween columnCenter"
<el-button class="sendButton rowFlex allCenter" >
@click.stop="sendMessageEdit(i, items._id)">发送</el-button> <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> </div>
</div> </div>
...@@ -67,23 +124,29 @@ ...@@ -67,23 +124,29 @@
</div> </div>
</template> </template>
<script> <script>
import { procedure_group, procedureList, procedureSort, procedureGroupSort, skillQuote } from '@/api/skill' import {
import { mapState, mapMutations, mapActions } from 'vuex' procedure_group,
import { throttle, copyToClipboard } from '@/utils/index' procedureList,
import { getMediaId } from '@/api/works' 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 { export default {
name: 'skillCompany', name: "skillCompany",
components: {}, components: {},
props: { props: {
activeName: { activeName: {
default: '', default: "",
type: String type: String,
} },
}, },
data() { data() {
return { return {
collapseActive: '', collapseActive: "",
groupActive: '0', groupActive: "0",
activeGroup: {}, activeGroup: {},
groupList: [], groupList: [],
groupLastList: [], groupLastList: [],
...@@ -92,282 +155,294 @@ export default { ...@@ -92,282 +155,294 @@ export default {
pageInfo: { pageInfo: {
page: 1, page: 1,
page_size: 100, page_size: 100,
total: 0 total: 0,
}, },
skillLoading: false, skillLoading: false,
loading: false, loading: false,
requestData: { requestData: {
content: '', content: "",
type: '', type: "",
procedure_group_id: '' procedure_group_id: "",
}, },
sortType: '', sortType: "",
sortID: { sortID: {
_id: '', _id: "",
before_id: '', before_id: "",
after_id: '' after_id: "",
}, },
filterText: {}, filterText: {},
dragging: null, dragging: null,
orderList: [ orderList: [
{ label: '个人话术', type: 'personal' }, { label: "个人话术", type: "personal" },
{ label: '企业话术', type: 'company' } { label: "企业话术", type: "company" },
] ],
} };
}, },
computed: { computed: {
...mapState('game', ['accountSelect']), ...mapState("game", ["accountSelect"]),
}, },
watch: { watch: {
accountSelect(newVal, oldVal) { accountSelect(newVal, oldVal) {
if (newVal && newVal !== '') { if (newVal && newVal !== "") {
this.pageInfo = { this.pageInfo = {
page: 1, page: 1,
page_size: 100, page_size: 100,
total: 0 total: 0,
} };
} }
}, },
activeName(newVal, oldVal) { activeName(newVal, oldVal) {
if (newVal == 'company' && newVal != oldVal) { if (newVal == "company" && newVal != oldVal) {
this.resizeSelect() this.resizeSelect();
this.requestGroup() this.requestGroup();
}
} }
}, },
},
mounted() { mounted() {
// this.requestGroup() // this.requestGroup()
}, },
methods: { methods: {
handleDragStart(e, item, index) { handleDragStart(e, item, index) {
this.sortID._id = item._id this.sortID._id = item._id;
this.dragging = item this.dragging = item;
}, },
skillQuote(id, num) { skillQuote(id, num) {
const data = { const data = {
type: this.activeName, type: this.activeName,
procedure_id: id, procedure_id: id,
quote_count: num || 1 quote_count: num || 1,
} };
skillQuote(data).then((res) => { skillQuote(data).then((res) => {
console.log(res) console.log(res);
}) });
}, },
sortSkill() { sortSkill() {
procedureSort(this.sortID).then((res) => { procedureSort(this.sortID).then((res) => {
if (res.status_code == 1) { if (res.status_code == 1) {
this.$message.success(res.msg) this.$message.success(res.msg);
} }
}) });
}, },
sortSkillGroup() { sortSkillGroup() {
procedureGroupSort(this.sortID).then((res) => { procedureGroupSort(this.sortID).then((res) => {
if (res.status_code == 1) { if (res.status_code == 1) {
this.$message.success(res.msg) this.$message.success(res.msg);
} }
}) });
}, },
handleDragEnd(e, item, type) { handleDragEnd(e, item, type) {
// type group 话术库排序 item 话术排序 // type group 话术库排序 item 话术排序
console.log(type, 'type', this.sortID) console.log(type, "type", this.sortID);
this.dragging = null this.dragging = null;
this.groupLastDataList = this.groupDataList this.groupLastDataList = this.groupDataList;
this.groupLastList = this.groupList this.groupLastList = this.groupList;
type === 'group' ? this.sortSkillGroup() : this.sortSkill() type === "group" ? this.sortSkillGroup() : this.sortSkill();
}, },
// 首先把div变成可以放置的元素,即重写dragenter/dragover // 首先把div变成可以放置的元素,即重写dragenter/dragover
// DataTransfer 对象用来保存,通过拖放动作,拖动到浏览器的数据。 // DataTransfer 对象用来保存,通过拖放动作,拖动到浏览器的数据。
// 如果dropEffect 属性设定为none,则不允许被拖放到目标元素中。 // 如果dropEffect 属性设定为none,则不允许被拖放到目标元素中。
handleDragOver(e) { handleDragOver(e) {
e.dataTransfer.dropEffect = 'move' // e.dataTransfer.dropEffect="move";//在dragenter中针对放置目标来设置! e.dataTransfer.dropEffect = "move"; // e.dataTransfer.dropEffect="move";//在dragenter中针对放置目标来设置!
}, },
handleDragEnter(e, item, type) { handleDragEnter(e, item, type) {
e.dataTransfer.effectAllowed = 'move' // 为需要移动的元素设置dragstart事件 e.dataTransfer.effectAllowed = "move"; // 为需要移动的元素设置dragstart事件
if (item === this.dragging) { if (item === this.dragging) {
return return;
} }
if (type === 'group') { if (type === "group") {
// 话术租排序 // 话术租排序
const newItems = [...this.groupList] const newItems = [...this.groupList];
const src = newItems.indexOf(this.dragging) const src = newItems.indexOf(this.dragging);
const dst = newItems.indexOf(item) const dst = newItems.indexOf(item);
if (src > dst) { if (src > dst) {
// 往上拖动 // 往上拖动
this.sortID.after_id = this.groupLastList[dst]._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 = '') this.groupLastList[dst - 1]
? (this.sortID.before_id = this.groupLastList[dst - 1]._id)
: (this.sortID.before_id = "");
// 替换 // 替换
} else { } else {
// 往下拖动 // 往下拖动
this.sortID.before_id = this.groupLastList[dst]._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 = '') 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的颜色等于新交换的颜色 // 让item的颜色等于新交换的颜色
this.groupList = newItems this.groupList = newItems;
} else { } else {
// 话术排序 // 话术排序
const newItems = [...this.groupDataList] const newItems = [...this.groupDataList];
const src = newItems.indexOf(this.dragging) const src = newItems.indexOf(this.dragging);
const dst = newItems.indexOf(item) const dst = newItems.indexOf(item);
if (src > dst) { if (src > dst) {
// 往上拖动 // 往上拖动
this.sortID.after_id = this.groupLastDataList[dst]._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 = '') this.groupLastDataList[dst - 1]
? (this.sortID.before_id = this.groupLastDataList[dst - 1]._id)
: (this.sortID.before_id = "");
// 替换 // 替换
} else { } else {
// 往下拖动 // 往下拖动
this.sortID.before_id = this.groupLastDataList[dst]._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 = '') 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的颜色等于新交换的颜色 // 让item的颜色等于新交换的颜色
this.groupDataList = newItems this.groupDataList = newItems;
} }
}, },
// 发送语音的时候 先编辑再发送 // 发送语音的时候 先编辑再发送
// 发送语音的时候 先编辑再发送 // 发送语音的时候 先编辑再发送
sendMessageEdit(item, id) { sendMessageEdit(item, id) {
// 复制内容到粘贴板 // 复制内容到粘贴板
if (item.msgtype == 'text') { if (item.msgtype == "text") {
if (item && item.text && item.text.content) { if (item && item.text && item.text.content) {
// copyToClipboard( // copyToClipboard(
// item.text.content, // item.text.content,
// (message) => this.$message.success(message), // (message) => this.$message.success(message),
// (message) => this.$message.error(message) // (message) => this.$message.error(message)
// ) // )
this.sendChatMessage(item.text.content) this.sendChatMessage(item.text.content);
} }
} else if (item.msgtype == 'image' && item.image.picurl) { } else if (item.msgtype == "image" && item.image.picurl) {
this.sendMessageImage(item) this.sendMessageImage(item);
} }
}, },
async sendMessageImage(item, id) { async sendMessageImage(item, id) {
// 发送图片作为链接消息 // 发送图片作为链接消息
if (item.image && item.image.picurl) { 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) { if (res.status_code == 1) {
this.sendImageAsMedia(res.data.media_id) this.sendImageAsMedia(res.data.media_id);
} }
} else { } else {
// 如果没有图片URL,提示用户 // 如果没有图片URL,提示用户
this.$message.error('图片链接不存在,无法发送') this.$message.error("图片链接不存在,无法发送");
} }
}, },
// 发送图片作为链接消息 // 发送图片作为链接消息
sendImageAsMedia(media_id) { sendImageAsMedia(media_id) {
this.$ww.sendChatMessage({ this.$ww.sendChatMessage({
msgtype: 'image', msgtype: "image",
image: { image: {
mediaid: media_id mediaid: media_id,
}, },
success: (res) => { success: (res) => {
console.log(res, '发送图片链接成功') console.log(res, "发送图片链接成功");
this.$message.success('图片发送成功') this.$message.success("图片发送成功");
}, },
fail: (err) => { fail: (err) => {
console.log(err, '发送图片链接失败') console.log(err, "发送图片链接失败");
this.$message.error('图片发送失败:' + (err.errMsg || err.message || '未知错误')) this.$message.error(
} "图片发送失败:" + (err.errMsg || err.message || "未知错误")
}) );
},
});
}, },
// 发送文本消息 // 发送文本消息
sendChatMessage(text) { sendChatMessage(text) {
this.$ww.sendChatMessage({ this.$ww.sendChatMessage({
msgtype: 'text', msgtype: "text",
text: { text: {
content: text content: text,
}, },
success: (res) => { success: (res) => {
console.log(res, '发送文本成功') console.log(res, "发送文本成功");
}, },
fail: (err) => { fail: (err) => {
console.log(err, '发送文本失败') console.log(err, "发送文本失败");
} },
}) });
}, },
contentSearch() { contentSearch() {
this.pageInfo = { this.pageInfo = {
page: 1, page: 1,
page_size: 100, page_size: 100,
total: 0 total: 0,
} };
this.searchTable() this.searchTable();
}, },
requestGroup() { requestGroup() {
this.loading = true this.loading = true;
const data = { const data = {
page: 1, page: 1,
pageSize: 100, pageSize: 100,
type: this.activeName type: this.activeName,
} };
procedure_group(data).then((res) => { procedure_group(data).then((res) => {
this.loading = false this.loading = false;
if (res.data && res.data.data && res.data.data.length > 0) { if (res.data && res.data.data && res.data.data.length > 0) {
this.groupList = res.data.data.map((item, index) => { this.groupList = res.data.data.map((item, index) => {
item.label = item.group_name item.label = item.group_name;
item.value = item._id item.value = item._id;
return item return item;
}) });
this.groupLastList = this.groupList this.groupLastList = this.groupList;
this.groupFilter(this.groupList[0]) this.groupFilter(this.groupList[0]);
} else { } else {
this.groupList = [] this.groupList = [];
this.groupLastList = [] this.groupLastList = [];
} }
}) });
}, },
// 62bd394d3747fe7c600a04f1 // 62bd394d3747fe7c600a04f1
groupFilter(item, index) { groupFilter(item, index) {
if (!item._id) { if (!item._id) {
this.requestData.second_group_id = '' this.requestData.second_group_id = "";
this.activeGroup = {} this.activeGroup = {};
} }
this.groupActive = item.value this.groupActive = item.value;
this.activeGroup = item this.activeGroup = item;
this.searchTable() this.searchTable();
}, },
// 搜索结果 // 搜索结果
async searchTable(msg) { async searchTable(msg) {
this.skillLoading = true this.skillLoading = true;
this.requestData.type = this.activeName this.requestData.type = this.activeName;
this.requestData.procedure_group_id = this.activeGroup._id || '' this.requestData.procedure_group_id = this.activeGroup._id || "";
const data = { ...this.requestData, ...this.pageInfo } const data = { ...this.requestData, ...this.pageInfo };
procedureList(data).then((res) => { procedureList(data).then((res) => {
this.skillLoading = false this.skillLoading = false;
this.groupDataList = res.data.data this.groupDataList = res.data.data;
this.groupDataList.map((item, index) => { this.groupDataList.map((item, index) => {
const text = item.message.attachments.find((item) => item.msgtype === 'text') const text = item.message.attachments.find(
(item) => item.msgtype === "text"
);
if (text) { if (text) {
item.title = text.text.content item.title = text.text.content;
} else { } else {
item.title = '' item.title = "";
} }
}) });
this.groupLastDataList = this.groupDataList this.groupLastDataList = this.groupDataList;
}) });
}, },
handleChange() { }, handleChange() {},
// 重置select // 重置select
resizeSelect() { resizeSelect() {
this.groupActive = '0' this.groupActive = "0";
this.isResize = true this.isResize = true;
this.groupDataList = [] this.groupDataList = [];
this.requestData.content = '' this.requestData.content = "";
this.pageInfo.page = 1 this.pageInfo.page = 1;
setTimeout(() => { setTimeout(() => {
this.isResize = false this.isResize = false;
}, 2000) }, 2000);
}, },
handleClick(tab, event) { handleClick(tab, event) {
// 切换table // 切换table
this.resizeSelect() this.resizeSelect();
this.requestGroup() this.requestGroup();
} },
} },
} };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.details { .details {
...@@ -425,7 +500,7 @@ export default { ...@@ -425,7 +500,7 @@ export default {
font-size: 14px; font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC; font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400; font-weight: 400;
color: #409EFF; color: #409eff;
margin-right: 10px; margin-right: 10px;
} }
...@@ -611,7 +686,7 @@ export default { ...@@ -611,7 +686,7 @@ export default {
} }
.tagItemActive { .tagItemActive {
color: #409EFF; color: #409eff;
font-family: PingFangSC-Regular, PingFang SC; font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400; font-weight: 400;
background: #e4fff1; background: #e4fff1;
......
<template> <template>
<div class="skillLibrary"> <div class="skillLibrary">
<div v-loading="loading" class="rowFlex skillBox"> <div v-loading="loading" class="rowFlex skillBox pl-[10px]">
<!-- 标签 --> <!-- 标签 -->
<el-collapse-transition> <el-collapse-transition>
<div v-if="groupList.length > 0" class="tagList columnFlex"> <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' : ''" :class="groupActive == item.value ? 'tagItemActiveText' : ''"
@dragstart="handleDragStart($event, item, index)" @dragover.prevent="handleDragOver($event, item)" @dragstart="handleDragStart($event, item, index)"
@dragenter="handleDragEnter($event, item, 'group')" @dragend="handleDragEnd($event, item, 'group')"> @dragover.prevent="handleDragOver($event, item)"
<div class="rowFlex columnCenter spaceBetween tagItemGroup" @click="groupFilter(item, index)"> @dragenter="handleDragEnter($event, item, 'group')"
@dragend="handleDragEnd($event, item, 'group')"
>
<div
class="rowFlex columnCenter spaceBetween tagItemGroup"
@click="groupFilter(item, index)"
>
<div class="rowFlex columnCenter"> <div class="rowFlex columnCenter">
<el-tooltip effect="dark" placement="top" :content="item.name" v-if="item.name.length >= 6"> <el-tooltip
<p class="text hidden" @click="groupFilter(item, index)">{{ item.name }}</p> 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> </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> </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>
<!-- 二级分组 --> <!-- 二级分组 -->
<div v-if="item.child.length > 0 && groupActive == item.value" class="childGroup"> <div
<div v-for="child in item.child" :key="child._id" class="childGroupText" v-if="item.child.length > 0 && groupActive == item.value"
:class="[groupActiveChild == child._id ? 'tagItemActive' : '']" @click.stop="groupFilterChild(child)"> 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> <p class="text hidden">{{ child.name }}</p>
</div> </div>
</div> </div>
...@@ -33,27 +63,67 @@ ...@@ -33,27 +63,67 @@
<!-- 话术 --> <!-- 话术 -->
<div class="libraryListContent"> <div class="libraryListContent">
<div class="inputContent"> <div class="inputContent">
<el-input v-model="requestData.title" placeholder="请输入话术内容" class="input-with-select"> <el-input
<el-button slot="append" icon="el-icon-search" @click="contentSearch"></el-button> v-model="requestData.title"
placeholder="请输入话术内容"
class="input-with-select"
>
<el-button
slot="append"
icon="el-icon-search"
@click="contentSearch"
></el-button>
</el-input> </el-input>
</div> </div>
<div ref="skillLibrary" v-loading="skillLoading" @scroll="paperScroll" class="scrollList"> <div
<div v-for="(items, indexs) in groupDataList" :key="indexs" class="answerContent"> ref="skillLibrary"
<div class="question"><span class="title">Q:</span>{{ items.name }}</div> v-loading="skillLoading"
<div v-for="(answer, answerIndex) in items.answer" :key="answerIndex" class="answerItem" @scroll="paperScroll"
style="width: 100%"> 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> --> <!-- <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> <span class="title rowFlex">A{{ answerIndex + 1 }}:</span>
<p v-if="answer.msgtype == 'text'" class="rowFlex textAnswer flex1"> <p
{{ answer.text.content || '' }} v-if="answer.msgtype == 'text'"
class="rowFlex textAnswer flex1"
>
{{ answer.text.content || "" }}
</p> </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>
<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> <span class="title rowFlex">A{{ answerIndex + 1 }}:</span>
<el-image style="max-width: 200px" :src="answer.image.picurl" <el-image
@click="sendMessageImage(answer, items._id)" :preview-src-list="[answer.image.picurl]"> </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> </div>
</div> </div>
...@@ -65,26 +135,31 @@ ...@@ -65,26 +135,31 @@
<script> <script>
// procedure_group, procedureList, procedureSort, procedureGroupSort, skillQuote, // procedure_group, procedureList, procedureSort, procedureGroupSort, skillQuote,
import { groupList, libraryIndex, logClickTime } from '@/api/skill' import { groupList, libraryIndex, logClickTime } from "@/api/skill";
import { mapState, mapMutations, mapActions } from 'vuex' import { mapState, mapMutations, mapActions } from "vuex";
import { throttle, debounce, copyToClipboard, sendChatMessage } from '@/utils/index' import {
import noContent from '@/components/noContent.vue' throttle,
debounce,
copyToClipboard,
sendChatMessage,
} from "@/utils/index";
import noContent from "@/components/noContent.vue";
export default { export default {
name: 'skillLibrary', name: "skillLibrary",
components: { components: {
noContent noContent,
}, },
props: { props: {
activeName: { activeName: {
default: '', default: "",
type: String type: String,
} },
}, },
data() { data() {
return { return {
collapseActive: '', collapseActive: "",
groupActive: '0', groupActive: "0",
groupActiveChild: '0', groupActiveChild: "0",
activeGroup: {}, activeGroup: {},
groupList: [], groupList: [],
groupLastList: [], groupLastList: [],
...@@ -93,93 +168,93 @@ export default { ...@@ -93,93 +168,93 @@ export default {
pageInfo: { pageInfo: {
page: 1, page: 1,
page_size: 20, page_size: 20,
total: 0 total: 0,
}, },
skillLoading: false, skillLoading: false,
loading: false, loading: false,
requestData: { requestData: {
title: '', title: "",
first_group_id: '', first_group_id: "",
second_group_id: '' second_group_id: "",
}, },
sortType: '', sortType: "",
sortID: { sortID: {
_id: '', _id: "",
before_id: '', before_id: "",
after_id: '' after_id: "",
}, },
filterText: {}, filterText: {},
dragging: null, dragging: null,
orderList: [ orderList: [
{ label: '知识库', type: 'library' }, { label: "知识库", type: "library" },
{ label: '个人话术', type: 'personal' }, { label: "个人话术", type: "personal" },
{ label: '企业话术', type: 'company' } { label: "企业话术", type: "company" },
] ],
} };
}, },
computed: { computed: {
...mapState('game', ['accountSelect', 'chatUserInfo']), ...mapState("game", ["accountSelect", "chatUserInfo"]),
}, },
watch: { watch: {
accountSelect(newVal, oldVal) { accountSelect(newVal, oldVal) {
if (newVal && newVal !== '') { if (newVal && newVal !== "") {
this.pageInfo = { this.pageInfo = {
page: 1, page: 1,
page_size: 20, page_size: 20,
total: 0 total: 0,
} };
} }
}, },
activeName(newVal, oldVal) { activeName(newVal, oldVal) {
if (newVal == 'library' && newVal != oldVal) { if (newVal == "library" && newVal != oldVal) {
this.resizeSelect() this.resizeSelect();
this.requestLibraryData() this.requestLibraryData();
}
} }
}, },
},
mounted() { mounted() {
this.requestLibraryData() this.requestLibraryData();
}, },
methods: { methods: {
sendMessage: throttle(function (item, id) { sendMessage: throttle(function (item, id) {
console.log(item, id) console.log(item, id);
// this.skillQuote(id, item.length) // this.skillQuote(id, item.length)
}, 500), }, 500),
handleDragStart(e, item, index) { handleDragStart(e, item, index) {
this.sortID._id = item._id this.sortID._id = item._id;
this.dragging = item this.dragging = item;
}, },
paperScroll: debounce(function () { paperScroll: debounce(function () {
const el = this.$refs.skillLibrary const el = this.$refs.skillLibrary;
if (el.offsetHeight + el.scrollTop + 10 >= el.scrollHeight) { if (el.offsetHeight + el.scrollTop + 10 >= el.scrollHeight) {
console.log('下一页') console.log("下一页");
this.pageInfo.page++ this.pageInfo.page++;
this.searchTable() this.searchTable();
} }
}, 500), }, 500),
skillQuote(id, num) { skillQuote(id, num) {
const data = { const data = {
type: this.activeName, type: this.activeName,
procedure_id: id, procedure_id: id,
quote_count: num || 1 quote_count: num || 1,
} };
skillQuote(data).then((res) => { skillQuote(data).then((res) => {
console.log(res) console.log(res);
}) });
}, },
sortSkill() { sortSkill() {
procedureSort(this.sortID).then((res) => { procedureSort(this.sortID).then((res) => {
if (res.status_code == 1) { if (res.status_code == 1) {
this.$message.success(res.msg) this.$message.success(res.msg);
} }
}) });
}, },
sortSkillGroup() { sortSkillGroup() {
procedureGroupSort(this.sortID).then((res) => { procedureGroupSort(this.sortID).then((res) => {
if (res.status_code == 1) { if (res.status_code == 1) {
this.$message.success(res.msg) this.$message.success(res.msg);
} }
}) });
}, },
// 发送语音的时候 先编辑再发送 // 发送语音的时候 先编辑再发送
sendMessageEdit(item, id) { sendMessageEdit(item, id) {
...@@ -189,98 +264,107 @@ export default { ...@@ -189,98 +264,107 @@ export default {
item.text.content, item.text.content,
(message) => this.$message.success(message), (message) => this.$message.success(message),
(message) => this.$message.error(message) (message) => this.$message.error(message)
) );
} }
this.sendChatMessage(item.text.content || '', 'text') this.sendChatMessage(item.text.content || "", "text");
}, },
sendMessageImage(item) { sendMessageImage(item) {
console.log(item, 'item') console.log(item, "item");
this.sendChatMessage(item.image.picurl || '', 'image') this.sendChatMessage(item.image.picurl || "", "image");
}, },
contentSearch() { contentSearch() {
this.pageInfo = { this.pageInfo = {
page: 1, page: 1,
page_size: 20, page_size: 20,
total: 0 total: 0,
} };
this.searchTable('msg') this.searchTable("msg");
}, },
// 知识库话术 // 知识库话术
requestLibraryData() { requestLibraryData() {
console.log(this.chatUserInfo, 'chatUserInfo') console.log(this.chatUserInfo, "chatUserInfo");
this.loading = true this.loading = true;
const data = { const data = {
page: 1, page: 1,
page_size: 100, page_size: 100,
userid: this.chatUserInfo.userid userid: this.chatUserInfo.userid,
} };
groupList(data).then((res) => { groupList(data).then((res) => {
this.loading = false this.loading = false;
if (res.data.data) { if (res.data.data) {
res.data.data.unshift({ res.data.data.unshift({
name: '全部分组', name: "全部分组",
value: '', value: "",
child: [] child: [],
}) });
this.groupList = res.data.data.map((item, index) => { this.groupList = res.data.data.map((item, index) => {
item.label = item.name item.label = item.name;
item.value = item._id item.value = item._id;
return item return item;
}) });
this.groupLastList = this.groupList this.groupLastList = this.groupList;
this.groupFilter(this.groupList[0]) this.groupFilter(this.groupList[0]);
} else { } else {
this.groupList = [] this.groupList = [];
this.groupLastList = [] this.groupLastList = [];
} }
}) });
}, },
groupFilter(item, index) { groupFilter(item, index) {
if (!item._id) { if (!item._id) {
this.requestData.second_group_id = '' this.requestData.second_group_id = "";
this.activeGroup = {} this.activeGroup = {};
} }
this.groupActive = item.value this.groupActive = item.value;
item.child && item.child[0] ? ((this.activeGroup = item.child[0]), (this.groupActiveChild = item.child[0]._id)) : '' item.child && item.child[0]
this.searchTable() ? ((this.activeGroup = item.child[0]),
(this.groupActiveChild = item.child[0]._id))
: "";
this.searchTable();
}, },
groupFilterChild(child) { groupFilterChild(child) {
this.groupActiveChild = 0 this.groupActiveChild = 0;
this.activeGroup = child this.activeGroup = child;
this.groupActiveChild = child._id this.groupActiveChild = child._id;
this.searchTable() this.searchTable();
this.$forceUpdate() this.$forceUpdate();
}, },
// 搜索结果 // 搜索结果
async searchTable(msg) { async searchTable(msg) {
this.skillLoading = true this.skillLoading = true;
this.requestData.second_group_id = this.activeGroup._id || '' this.requestData.second_group_id = this.activeGroup._id || "";
this.requestData.title = this.requestData.title.trim() this.requestData.title = this.requestData.title.trim();
const data = { ...this.requestData, ...this.pageInfo, log_scan: msg ? 1 : 0, userid: this.chatUserInfo.userid } const data = {
...this.requestData,
...this.pageInfo,
log_scan: msg ? 1 : 0,
userid: this.chatUserInfo.userid,
};
libraryIndex(data).then((res) => { libraryIndex(data).then((res) => {
this.skillLoading = false this.skillLoading = false;
this.pageInfo.page === 1 ? this.groupDataList = res.data.data : this.groupDataList = this.groupDataList.concat(res.data.data) this.pageInfo.page === 1
this.groupLastDataList = this.groupDataList ? (this.groupDataList = res.data.data)
}) : (this.groupDataList = this.groupDataList.concat(res.data.data));
this.groupLastDataList = this.groupDataList;
});
}, },
handleChange() { }, handleChange() {},
// 重置select // 重置select
resizeSelect() { resizeSelect() {
this.groupActive = '0' this.groupActive = "0";
this.isResize = true this.isResize = true;
this.groupDataList = [] this.groupDataList = [];
this.requestData.content = '' this.requestData.content = "";
this.pageInfo.page = 1 this.pageInfo.page = 1;
setTimeout(() => { setTimeout(() => {
this.isResize = false this.isResize = false;
}, 2000) }, 2000);
}, },
sendChatMessage(content, type) { sendChatMessage(content, type) {
sendChatMessage(content, type) sendChatMessage(content, type);
}, },
} },
} };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.skillLibrary { .skillLibrary {
...@@ -321,7 +405,7 @@ export default { ...@@ -321,7 +405,7 @@ export default {
font-size: 14px; font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC; font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400; font-weight: 400;
color: #409EFF; color: #409eff;
margin-right: 10px; margin-right: 10px;
} }
...@@ -467,7 +551,6 @@ export default { ...@@ -467,7 +551,6 @@ export default {
.skillBox { .skillBox {
width: 100%; width: 100%;
height: calc(100% - 20px); height: calc(100% - 20px);
} }
.tagList { .tagList {
...@@ -513,14 +596,14 @@ export default { ...@@ -513,14 +596,14 @@ export default {
} }
.tagItemActive { .tagItemActive {
color: #409EFF !important; color: #409eff !important;
font-family: PingFangSC-Regular, PingFang SC; font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400; font-weight: 400;
background: #e4fff1; background: #e4fff1;
} }
.tagItemActiveText { .tagItemActiveText {
color: #409EFF; color: #409eff;
} }
} }
...@@ -607,7 +690,7 @@ export default { ...@@ -607,7 +690,7 @@ export default {
.copyIcon { .copyIcon {
width: 20px; width: 20px;
color: #409EFF; color: #409eff;
font-size: 16px; font-size: 16px;
position: relative; position: relative;
top: 2px; top: 2px;
...@@ -619,7 +702,7 @@ export default { ...@@ -619,7 +702,7 @@ export default {
} }
.scrollList::-webkit-scrollbar { .scrollList::-webkit-scrollbar {
display: none display: none;
} }
.container { .container {
...@@ -676,7 +759,7 @@ export default { ...@@ -676,7 +759,7 @@ export default {
} }
.skillLibrary::-webkit-scrollbar { .skillLibrary::-webkit-scrollbar {
display: none display: none;
} }
::v-deep .el-icon-circle-close { ::v-deep .el-icon-circle-close {
......
<template> <template>
<div class="skillTab"> <div class="skillTab">
<div class="inputContent"> <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-button slot="append" icon="el-icon-search"></el-button>
</el-input> </el-input>
</div> </div>
<div v-loading="loading" class="rowFlex skillBox"> <div v-loading="loading" class="rowFlex skillBox pl-[10px]">
<!-- 标签 --> <!-- 标签 -->
<el-collapse-transition> <el-collapse-transition>
<div v-if="groupList.length > 0" class="tagList columnFlex"> <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" :draggable="activeName == 'personal' ? true : false"
:class="groupActive == item.value ? 'tagItemActive' : ''" @dragstart="handleDragStart($event, item, index)" :class="groupActive == item.value ? 'tagItemActive' : ''"
@dragover.prevent="handleDragOver($event, item)" @dragenter="handleDragEnter($event, item, 'group')" @dragstart="handleDragStart($event, item, index)"
@dragend="handleDragEnd($event, item, 'group')"> @dragover.prevent="handleDragOver($event, item)"
<el-tooltip effect="dark" placement="top" :content="item.group_name" v-if="item.group_name.length >= 6"> @dragenter="handleDragEnter($event, item, 'group')"
<p class="text hidden" @click="groupFilter(item, index)">{{ item.group_name }}</p> @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> </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> </div>
<div v-else>暂无话术内容</div> <div v-else>暂无话术内容</div>
</el-collapse-transition> </el-collapse-transition>
<!-- 话术 --> <!-- 话术 -->
<div v-loading="skillLoading" class="scrollList"> <div v-loading="skillLoading" class="scrollList px-[10px]">
<el-collapse v-model="collapseActive" @change="handleChange"> <el-collapse v-model="collapseActive" @change="handleChange">
<transition-group v-if="groupDataList.length > 0" tag="div" class="container"> <transition-group
<div v-for="(items, indexs) in groupDataList" :key="indexs" v-if="groupDataList.length > 0"
:draggable="activeName == 'personal' ? true : false" class="draggable" tag="div"
@dragstart="handleDragStart($event, items, indexs)" @dragover.prevent="handleDragOver($event, items)" class="container"
@dragenter="handleDragEnter($event, items, 'item')" @dragend="handleDragEnd($event, items, 'item')"> >
<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"> <el-popover placement="top" width="300" trigger="hover">
<p>{{ items.title }}</p> <p>{{ items.title }}</p>
<div slot="reference" class="contentItemTitle allCenter" <div
:style="{ top: items.title.length > 8 ? '5px' : '13px' }">{{ items.title }}</div> slot="reference"
class="contentItemTitle allCenter"
:style="{ top: items.title.length > 8 ? '5px' : '13px' }"
>
{{ items.title }}
</div>
</el-popover> </el-popover>
<div class="rowFlex titleFixed columnCenter"> <div class="rowFlex titleFixed columnCenter">
<div class="num">{{ items.message.attachments.length > 1 ? `+${items.message.attachments.length - 1}条` : <div class="num">
'' }}</div> {{
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> --> <!-- <el-button class="button rowFlex allCenter" @click.stop="sendMessage(items.message.attachments, items._id)">发送</el-button> -->
</div> </div>
<el-collapse-item title="" :name="items._id" class="contentItem"> <el-collapse-item title="" :name="items._id" class="contentItem">
<div v-for="(i, j) in items.message.attachments" :key="j"> <div v-for="(i, j) in items.message.attachments" :key="j">
<div> <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> <div class="text">{{ i.text.content }}</div>
<el-button class="sendButton rowFlex allCenter" <el-button
@click.stop="sendMessageEdit(i, items._id)">发送</el-button> class="sendButton rowFlex allCenter"
@click.stop="sendMessageEdit(i, items._id)"
>发送</el-button
>
</div> </div>
<div v-if="i.msgtype == 'image'" class="contentItemDetails rowFlex spaceBetween columnCenter"> <div
<el-image class="image" :src="i.image.picurl" :preview-src-list="[i.image.picurl]" v-if="i.msgtype == 'image'"
fit="contain"></el-image> class="contentItemDetails rowFlex spaceBetween columnCenter"
<el-button class="sendButton rowFlex allCenter" >
@click.stop="sendMessageEdit(i, items._id)">发送</el-button> <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> </div>
</div> </div>
...@@ -67,23 +123,28 @@ ...@@ -67,23 +123,28 @@
</div> </div>
</template> </template>
<script> <script>
import { procedure_group, procedureList, procedureSort, procedureGroupSort } from '@/api/skill' import {
import { getMediaId } from '@/api/works' procedure_group,
import { mapState, mapMutations, mapActions } from 'vuex' procedureList,
import { debounce, copyToClipboard } from '@/utils/index' procedureSort,
procedureGroupSort,
} from "@/api/skill";
import { getMediaId } from "@/api/works";
import { mapState, mapMutations, mapActions } from "vuex";
import { debounce, copyToClipboard } from "@/utils/index";
export default { export default {
name: 'skillPersonal', name: "skillPersonal",
components: {}, components: {},
props: { props: {
activeName: { activeName: {
default: '', default: "",
type: String type: String,
} },
}, },
data() { data() {
return { return {
collapseActive: '', collapseActive: "",
groupActive: '0', groupActive: "0",
activeGroup: {}, activeGroup: {},
groupList: [], groupList: [],
groupLastList: [], groupLastList: [],
...@@ -92,196 +153,206 @@ export default { ...@@ -92,196 +153,206 @@ export default {
pageInfo: { pageInfo: {
page: 1, page: 1,
page_size: 100, page_size: 100,
total: 0 total: 0,
}, },
skillLoading: false, skillLoading: false,
loading: false, loading: false,
requestData: { requestData: {
content: '', content: "",
type: '', type: "",
procedure_group_id: '' procedure_group_id: "",
}, },
sortType: '', sortType: "",
sortID: { sortID: {
_id: '', _id: "",
before_id: '', before_id: "",
after_id: '' after_id: "",
}, },
filterText: {}, filterText: {},
dragging: null, dragging: null,
orderList: [ orderList: [
{ label: '个人话术', type: 'personal' }, { label: "个人话术", type: "personal" },
{ label: '企业话术', type: 'company' } { label: "企业话术", type: "company" },
] ],
} };
}, },
computed: { computed: {
...mapState('game', ['accountSelect']), ...mapState("game", ["accountSelect"]),
...mapState('user', ['userid', 'external_userid']), ...mapState("user", ["userid", "external_userid"]),
}, },
watch: { watch: {
accountSelect(newVal, oldVal) { accountSelect(newVal, oldVal) {
if (newVal && newVal !== '') { if (newVal && newVal !== "") {
this.pageInfo = { this.pageInfo = {
page: 1, page: 1,
page_size: 100, page_size: 100,
total: 0 total: 0,
} };
} }
}, },
activeName(newVal, oldVal) { activeName(newVal, oldVal) {
if (newVal == 'personal' && newVal != oldVal) { if (newVal == "personal" && newVal != oldVal) {
this.resizeSelect() this.resizeSelect();
this.requestGroup() this.requestGroup();
}
} }
}, },
},
mounted() { mounted() {
this.requestGroup() this.requestGroup();
}, },
methods: { methods: {
// ...mapMutations('common', ['set_sendSkillMessage', 'set_isEditSkill']), // ...mapMutations('common', ['set_sendSkillMessage', 'set_isEditSkill']),
sendMessage: debounce(function (item, id) { sendMessage: debounce(function (item, id) {
console.log(item, id, 'sendMessage') console.log(item, id, "sendMessage");
}, 500), }, 500),
// 发送语音的时候 先编辑再发送 // 发送语音的时候 先编辑再发送
sendMessageEdit(item, id) { sendMessageEdit(item, id) {
console.log(item) console.log(item);
// 复制内容到粘贴板 // 复制内容到粘贴板
if (item.msgtype == 'text') { if (item.msgtype == "text") {
if (item && item.text && item.text.content) { if (item && item.text && item.text.content) {
// copyToClipboard( // copyToClipboard(
// item.text.content, // item.text.content,
// (message) => this.$message.success(message), // (message) => this.$message.success(message),
// (message) => this.$message.error(message) // (message) => this.$message.error(message)
// ) // )
this.sendChatMessage(item.text.content) this.sendChatMessage(item.text.content);
} }
} else if (item.msgtype == 'image' && item.image.picurl) { } else if (item.msgtype == "image" && item.image.picurl) {
this.sendMessageImage(item) this.sendMessageImage(item);
} }
}, },
async sendMessageImage(item, id) { async sendMessageImage(item, id) {
// 发送图片作为链接消息 // 发送图片作为链接消息
if (item.image && item.image.picurl) { 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) { if (res.status_code == 1) {
this.sendImageAsMedia(res.data.media_id) this.sendImageAsMedia(res.data.media_id);
} }
} else { } else {
// 如果没有图片URL,提示用户 // 如果没有图片URL,提示用户
this.$message.error('图片链接不存在,无法发送') this.$message.error("图片链接不存在,无法发送");
} }
}, },
// 发送图片作为链接消息 // 发送图片作为链接消息
sendImageAsMedia(media_id) { sendImageAsMedia(media_id) {
this.$ww.sendChatMessage({ this.$ww.sendChatMessage({
msgtype: 'image', msgtype: "image",
image: { image: {
mediaid: media_id mediaid: media_id,
}, },
success: (res) => { success: (res) => {
console.log(res, '发送图片链接成功') console.log(res, "发送图片链接成功");
this.$message.success('图片发送成功') this.$message.success("图片发送成功");
}, },
fail: (err) => { fail: (err) => {
console.log(err, '发送图片链接失败') console.log(err, "发送图片链接失败");
this.$message.error('图片发送失败:' + (err.errMsg || err.message || '未知错误')) this.$message.error(
} "图片发送失败:" + (err.errMsg || err.message || "未知错误")
}) );
},
});
}, },
// 发送文本消息 // 发送文本消息
sendChatMessage(text) { sendChatMessage(text) {
this.$ww.sendChatMessage({ this.$ww.sendChatMessage({
msgtype: 'text', msgtype: "text",
text: { text: {
content: text content: text,
}, },
success: (res) => { success: (res) => {
console.log(res, '发送文本成功') console.log(res, "发送文本成功");
}, },
fail: (err) => { fail: (err) => {
console.log(err, '发送文本失败') console.log(err, "发送文本失败");
} },
}) });
}, },
handleDragStart(e, item, index) { handleDragStart(e, item, index) {
this.sortID._id = item._id this.sortID._id = item._id;
this.dragging = item this.dragging = item;
}, },
sortSkill() { sortSkill() {
procedureSort(this.sortID).then((res) => { procedureSort(this.sortID).then((res) => {
if (res.status_code == 1) { if (res.status_code == 1) {
this.$message.success(res.msg) this.$message.success(res.msg);
} }
}) });
}, },
sortSkillGroup() { sortSkillGroup() {
if (this.sortID.before_id !== '' || this.sortID.after_id !== '') { if (this.sortID.before_id !== "" || this.sortID.after_id !== "") {
procedureGroupSort(this.sortID).then((res) => { procedureGroupSort(this.sortID).then((res) => {
if (res.status_code == 1) { if (res.status_code == 1) {
this.$message.success(res.msg) this.$message.success(res.msg);
} }
}) });
} }
}, },
handleDragEnd(e, item, type) { handleDragEnd(e, item, type) {
// type group 话术库排序 item 话术排序 // type group 话术库排序 item 话术排序
console.log(type, 'type', this.sortID) console.log(type, "type", this.sortID);
this.dragging = null this.dragging = null;
this.groupLastDataList = this.groupDataList this.groupLastDataList = this.groupDataList;
this.groupLastList = this.groupList this.groupLastList = this.groupList;
type === 'group' ? this.sortSkillGroup() : this.sortSkill() type === "group" ? this.sortSkillGroup() : this.sortSkill();
}, },
// 首先把div变成可以放置的元素,即重写dragenter/dragover // 首先把div变成可以放置的元素,即重写dragenter/dragover
// DataTransfer 对象用来保存,通过拖放动作,拖动到浏览器的数据。 // DataTransfer 对象用来保存,通过拖放动作,拖动到浏览器的数据。
// 如果dropEffect 属性设定为none,则不允许被拖放到目标元素中。 // 如果dropEffect 属性设定为none,则不允许被拖放到目标元素中。
handleDragOver(e) { handleDragOver(e) {
e.dataTransfer.dropEffect = 'move' // e.dataTransfer.dropEffect="move";//在dragenter中针对放置目标来设置! e.dataTransfer.dropEffect = "move"; // e.dataTransfer.dropEffect="move";//在dragenter中针对放置目标来设置!
}, },
handleDragEnter(e, item, type) { handleDragEnter(e, item, type) {
e.dataTransfer.effectAllowed = 'move' // 为需要移动的元素设置dragstart事件 e.dataTransfer.effectAllowed = "move"; // 为需要移动的元素设置dragstart事件
if (item === this.dragging) { if (item === this.dragging) {
return return;
} }
if (type === 'group') { if (type === "group") {
// 话术租排序 // 话术租排序
const newItems = [...this.groupList] const newItems = [...this.groupList];
const src = newItems.indexOf(this.dragging) const src = newItems.indexOf(this.dragging);
const dst = newItems.indexOf(item) const dst = newItems.indexOf(item);
if (src > dst) { if (src > dst) {
// 往上拖动 // 往上拖动
this.sortID.after_id = this.groupLastList[dst]._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 = '') this.groupLastList[dst - 1]
? (this.sortID.before_id = this.groupLastList[dst - 1]._id)
: (this.sortID.before_id = "");
// 替换 // 替换
} else { } else {
// 往下拖动 // 往下拖动
this.sortID.before_id = this.groupLastList[dst]._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 = '') 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的颜色等于新交换的颜色 // 让item的颜色等于新交换的颜色
this.groupList = newItems this.groupList = newItems;
} else { } else {
// 话术排序 // 话术排序
const newItems = [...this.groupDataList] const newItems = [...this.groupDataList];
const src = newItems.indexOf(this.dragging) const src = newItems.indexOf(this.dragging);
const dst = newItems.indexOf(item) const dst = newItems.indexOf(item);
if (src > dst) { if (src > dst) {
// 往上拖动 // 往上拖动
this.sortID.after_id = this.groupLastDataList[dst]._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 = '') this.groupLastDataList[dst - 1]
? (this.sortID.before_id = this.groupLastDataList[dst - 1]._id)
: (this.sortID.before_id = "");
// 替换 // 替换
} else { } else {
// 往下拖动 // 往下拖动
this.sortID.before_id = this.groupLastDataList[dst]._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 = '') 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的颜色等于新交换的颜色 // 让item的颜色等于新交换的颜色
this.groupDataList = newItems this.groupDataList = newItems;
} }
}, },
...@@ -289,82 +360,84 @@ export default { ...@@ -289,82 +360,84 @@ export default {
this.pageInfo = { this.pageInfo = {
page: 1, page: 1,
page_size: 100, page_size: 100,
total: 0 total: 0,
} };
this.searchTable() this.searchTable();
}, },
requestGroup() { requestGroup() {
this.loading = true this.loading = true;
const data = { const data = {
page: 1, page: 1,
pageSize: 100, pageSize: 100,
type: this.activeName type: this.activeName,
} };
procedure_group(data).then((res) => { procedure_group(data).then((res) => {
this.loading = false this.loading = false;
if (res.data.data && res.data.data.length > 0) { if (res.data.data && res.data.data.length > 0) {
this.groupList = res.data.data.map((item, index) => { this.groupList = res.data.data.map((item, index) => {
item.label = item.group_name item.label = item.group_name;
item.value = item._id item.value = item._id;
return item return item;
}) });
this.groupLastList = this.groupList this.groupLastList = this.groupList;
this.groupFilter(this.groupList[0]) this.groupFilter(this.groupList[0]);
} else { } else {
this.groupList = [] this.groupList = [];
this.groupLastList = [] this.groupLastList = [];
} }
}) });
}, },
// 62bd394d3747fe7c600a04f1 // 62bd394d3747fe7c600a04f1
groupFilter(item, index) { groupFilter(item, index) {
if (!item._id) { if (!item._id) {
this.requestData.second_group_id = '' this.requestData.second_group_id = "";
this.activeGroup = {} this.activeGroup = {};
} }
this.groupActive = item.value this.groupActive = item.value;
this.activeGroup = item this.activeGroup = item;
this.searchTable() this.searchTable();
}, },
// 搜索结果 // 搜索结果
async searchTable(msg) { async searchTable(msg) {
this.skillLoading = true this.skillLoading = true;
this.requestData.type = this.activeName this.requestData.type = this.activeName;
this.requestData.procedure_group_id = this.activeGroup._id || '' this.requestData.procedure_group_id = this.activeGroup._id || "";
const data = { ...this.requestData, ...this.pageInfo } const data = { ...this.requestData, ...this.pageInfo };
procedureList(data).then((res) => { procedureList(data).then((res) => {
this.skillLoading = false this.skillLoading = false;
this.groupDataList = res.data.data this.groupDataList = res.data.data;
this.groupDataList.map((item, index) => { this.groupDataList.map((item, index) => {
const text = item.message.attachments.find((item) => item.msgtype === 'text') const text = item.message.attachments.find(
(item) => item.msgtype === "text"
);
if (text) { if (text) {
item.title = text.text.content item.title = text.text.content;
} else { } else {
item.title = '' item.title = "";
} }
}) });
this.groupLastDataList = this.groupDataList this.groupLastDataList = this.groupDataList;
}) });
}, },
handleChange() { }, handleChange() {},
// 重置select // 重置select
resizeSelect() { resizeSelect() {
this.groupActive = '0' this.groupActive = "0";
this.isResize = true this.isResize = true;
this.groupDataList = [] this.groupDataList = [];
this.requestData.content = '' this.requestData.content = "";
this.pageInfo.page = 1 this.pageInfo.page = 1;
setTimeout(() => { setTimeout(() => {
this.isResize = false this.isResize = false;
}, 2000) }, 2000);
}, },
handleClick(tab, event) { handleClick(tab, event) {
// 切换table // 切换table
this.resizeSelect() this.resizeSelect();
this.requestGroup() this.requestGroup();
} },
} },
} };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.details { .details {
...@@ -422,7 +495,7 @@ export default { ...@@ -422,7 +495,7 @@ export default {
font-size: 14px; font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC; font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400; font-weight: 400;
color: #409EFF; color: #409eff;
margin-right: 10px; margin-right: 10px;
} }
...@@ -608,7 +681,7 @@ export default { ...@@ -608,7 +681,7 @@ export default {
} }
.tagItemActive { .tagItemActive {
color: #409EFF; color: #409eff;
font-family: PingFangSC-Regular, PingFang SC; font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400; font-weight: 400;
background: #e4fff1; background: #e4fff1;
...@@ -682,8 +755,8 @@ export default { ...@@ -682,8 +755,8 @@ export default {
} }
.el-input-group__append { .el-input-group__append {
background-color: #3491FA; background-color: #3491fa;
border-color: #3491FA; border-color: #3491fa;
color: #fff; color: #fff;
} }
} }
...@@ -701,16 +774,16 @@ export default { ...@@ -701,16 +774,16 @@ export default {
} }
.tagItemActive { .tagItemActive {
color: #3491FA !important; color: #3491fa !important;
background: #E8F7FF !important; background: #e8f7ff !important;
font-weight: 500 !important; font-weight: 500 !important;
} }
} }
// 发送按钮样式 // 发送按钮样式
.sendButton { .sendButton {
background-color: #3491FA !important; background-color: #3491fa !important;
color: white !important; color: white !important;
border-color: #3491FA !important; border-color: #3491fa !important;
} }
</style> </style>
// UnifiedLogin.vue // UnifiedLogin.vue
<template> <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"> <div class="loginContentContainer">
<p class="loginContentTitle">选择客服:</p> <p class="loginContentTitle">选择客服:</p>
<div class="loginContentInput rowFlex alignCenter"> <div class="loginContentInput rowFlex alignCenter">
...@@ -23,25 +126,25 @@ ...@@ -23,25 +126,25 @@
> >
</div> </div>
</div> </div>
</div> </div> -->
</template> </template>
<script> <script>
import * as ww from '@wecom/jssdk'; import * as ww from "@wecom/jssdk";
import { import {
getOrganization, getOrganization,
getAuthUser, getAuthUser,
getSignature, getSignature,
getUserList, getUserList,
cserSelected, cserSelected,
} from '@/api/user'; } from "@/api/user";
import Cookies from 'js-cookie'; import Cookies from "js-cookie";
import { getParams } from '@/utils/index'; import { getParams } from "@/utils/index";
import { mapMutations, mapState } from 'vuex'; import { mapMutations, mapState } from "vuex";
import { getToken, setToken } from '@/utils/auth'; import { getToken, setToken } from "@/utils/auth";
import jsApiList from '@/utils/jsApiList'; import jsApiList from "@/utils/jsApiList";
export default { export default {
name: 'login', name: "login",
components: {}, components: {},
data() { data() {
return { return {
...@@ -57,10 +160,10 @@ export default { ...@@ -57,10 +160,10 @@ export default {
showRefresh: false, // 控制刷新按钮显示 showRefresh: false, // 控制刷新按钮显示
qrLoading: false, // 控制二维码 loading qrLoading: false, // 控制二维码 loading
redirectUri: redirectUri:
process.env.NODE_ENV === 'production' process.env.NODE_ENV === "production"
? 'https://companywx.zwnet.cn/api/api/sidebar_login/ding' ? "https://companywx.zwnet.cn/api/api/sidebar_login/ding"
: 'https://companywx.zwwlkj03.top/api/api/sidebar_login/ding', : "https://companywx.zwwlkj03.top/api/api/sidebar_login/ding",
DDTestUrl: '', DDTestUrl: "",
token: getToken(), token: getToken(),
userList: [], userList: [],
cser_user_id: null, cser_user_id: null,
...@@ -72,23 +175,23 @@ export default { ...@@ -72,23 +175,23 @@ export default {
}); });
}, },
computed: { computed: {
...mapState('user', ['corp_id']), ...mapState("user", ["corp_id"]),
}, },
methods: { methods: {
...mapMutations('user', [ ...mapMutations("user", [
'set_corp_id', "set_corp_id",
'set_userid', "set_userid",
'set_userInfo', "set_userInfo",
'set_token', "set_token",
'set_cser_info', "set_cser_info",
'set_signData', "set_signData",
'set_cser_id', "set_cser_id",
'set_cser_name', "set_cser_name",
'set_external_userid', "set_external_userid",
]), ]),
async initLogin() { async initLogin() {
const urlParams = getParams(); const urlParams = getParams();
const userid = Cookies.get('userid'); const userid = Cookies.get("userid");
if (this.token && userid) { if (this.token && userid) {
// 已经钉钉扫码过 重新获取授权 获取签名 注册企微js-sdk // 已经钉钉扫码过 重新获取授权 获取签名 注册企微js-sdk
this.getUserList(userid); this.getUserList(userid);
...@@ -101,20 +204,20 @@ export default { ...@@ -101,20 +204,20 @@ export default {
}, },
async getUserList(userid) { async getUserList(userid) {
this.urlParams = getParams(); 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 }); const res = await getUserList({ userid: userid, corp_id: corp_id });
this.userList = res.data; this.userList = res.data;
}, },
async userStartLogin() { async userStartLogin() {
if (!this.cser_user_id) { if (!this.cser_user_id) {
this.$message.error('请选择客服人员'); this.$message.error("请选择客服人员");
return; return;
} }
const cser_user = this.userList.find( const cser_user = this.userList.find(
(item) => item.zq_user_id === this.cser_user_id (item) => item.zq_user_id === this.cser_user_id
); );
const corp_id = Cookies.get('corp_id'); const corp_id = Cookies.get("corp_id");
const userid = Cookies.get('userid'); const userid = Cookies.get("userid");
this.cacheCser(cser_user.zq_user_id, cser_user.name); this.cacheCser(cser_user.zq_user_id, cser_user.name);
try { try {
const res = await cserSelected({ const res = await cserSelected({
...@@ -122,10 +225,10 @@ export default { ...@@ -122,10 +225,10 @@ export default {
corp_id: corp_id, corp_id: corp_id,
userid: userid, userid: userid,
}); });
console.log(res, '选择客服人员登录'); console.log(res, "选择客服人员登录");
if (res.status_code === 1 && res.data.tokens) { if (res.status_code === 1 && res.data.tokens) {
this.$message({ this.$message({
type: 'warning', type: "warning",
message: `当前【${cser_user.name}】已上线,下班后请记得点击下线哦~`, message: `当前【${cser_user.name}】已上线,下班后请记得点击下线哦~`,
duration: 3 * 1000, duration: 3 * 1000,
}); });
...@@ -137,20 +240,20 @@ export default { ...@@ -137,20 +240,20 @@ export default {
setTimeout(() => { setTimeout(() => {
window.location.href = window.location.href =
window.location.origin + window.location.origin +
'/company_app/index.html?corp_id=' + "/company_app/index.html?corp_id=" +
corp_id + corp_id +
'&msg=cser_error'; "&msg=cser_error";
}, 5000); }, 5000);
} }
} catch (error) { } catch (error) {
console.log(error, '选择客服人员登录失败'); console.log(error, "选择客服人员登录失败");
this.$message.error(error.msg); this.$message.error(error.msg);
setTimeout(() => { setTimeout(() => {
window.location.href = window.location.href =
window.location.origin + window.location.origin +
'/company_app/index.html?corp_id=' + "/company_app/index.html?corp_id=" +
corp_id + corp_id +
'&msg=cser_error'; "&msg=cser_error";
}, 5000); }, 5000);
} }
}, },
...@@ -160,32 +263,32 @@ export default { ...@@ -160,32 +263,32 @@ export default {
); );
this.$confirm( this.$confirm(
`确认登录上线吗,上线后所有会话都会归属到客服【${cser_user.name}】`, `确认登录上线吗,上线后所有会话都会归属到客服【${cser_user.name}】`,
'提示', "提示",
{ {
confirmButtonText: '确定', confirmButtonText: "确定",
cancelButtonText: '取消', cancelButtonText: "取消",
type: 'warning', type: "warning",
} }
) )
.then(() => { .then(() => {
this.userStartLogin(); this.userStartLogin();
}) })
.catch(() => { .catch(() => {
this.$message.info('已取消登录'); this.$message.info("已取消登录");
}); });
}, },
// 设置缓存 // 设置缓存
cacheCorp_id(corp_id) { 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); this.set_corp_id(corp_id);
}, },
cacheuserid(userid) { cacheuserid(userid) {
Cookies.set('userid', userid, { expires: 30 }); Cookies.set("userid", userid, { expires: 30 });
this.set_userid(userid); this.set_userid(userid);
}, },
cacheCser(cser_id, cser_name) { cacheCser(cser_id, cser_name) {
Cookies.set('cser_id', cser_id, { expires: 30 }); Cookies.set("cser_id", cser_id, { expires: 30 });
Cookies.set('cser_name', cser_name, { expires: 30 }); Cookies.set("cser_name", cser_name, { expires: 30 });
this.set_cser_info({ this.set_cser_info({
cser_id: cser_id, cser_id: cser_id,
cser_name: cser_name, cser_name: cser_name,
...@@ -194,16 +297,16 @@ export default { ...@@ -194,16 +297,16 @@ export default {
this.set_cser_name(cser_name); this.set_cser_name(cser_name);
}, },
cacheSignData(signData) { cacheSignData(signData) {
Cookies.set('signData', JSON.stringify(signData), { expires: 30 }); Cookies.set("signData", JSON.stringify(signData), { expires: 30 });
this.set_signData(signData); this.set_signData(signData);
}, },
// 进入的页面地址是 https://companywx.jianshuwenhua.com/company_app/index.html?corp_id=wweaefe716636df3d1 // 进入的页面地址是 https://companywx.jianshuwenhua.com/company_app/index.html?corp_id=wweaefe716636df3d1
// 1. 企微静默授权 // 1. 企微静默授权
async startWeComSilentAuth() { async startWeComSilentAuth() {
this.urlParams = getParams(); 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) { if (!corp_id) {
this.$message.error('当前客服号信息异常,请切换会话后重试'); this.$message.error("当前客服号信息异常,请切换会话后重试");
return; return;
} }
// 确定是第一次进入页面 没有 code 和 state // 确定是第一次进入页面 没有 code 和 state
...@@ -225,17 +328,17 @@ export default { ...@@ -225,17 +328,17 @@ export default {
this.cacheuserid(res.data.userid); this.cacheuserid(res.data.userid);
this.getUserList(res.data.userid); this.getUserList(res.data.userid);
} else { } else {
this.$message.error('获取用户id失败'); this.$message.error("获取用户id失败");
return; return;
} }
} else { } else {
console.log('获取useid失败', res); console.log("获取useid失败", res);
// 错误处理 // 错误处理
} }
}, },
async getSignature() { async getSignature() {
console.log('获取签名', window.location.href); console.log("获取签名", window.location.href);
const corp_id = Cookies.get('corp_id'); const corp_id = Cookies.get("corp_id");
try { try {
const res = await getSignature({ const res = await getSignature({
corp_id: corp_id, corp_id: corp_id,
...@@ -247,42 +350,42 @@ export default { ...@@ -247,42 +350,42 @@ export default {
try { try {
this.registerWeComSDK(); this.registerWeComSDK();
} catch (err) { } catch (err) {
console.log(err, '初始化sdk 失败'); console.log(err, "初始化sdk 失败");
} }
} }
} catch (err) { } catch (err) {
console.log(err, '获取签名失败'); console.log(err, "获取签名失败");
window.location.href = window.location.href =
window.location.origin + window.location.origin +
'/company_app/index.html?corp_id=' + "/company_app/index.html?corp_id=" +
corp_id + corp_id +
'&msg=signerror'; "&msg=signerror";
} }
}, },
getCurExternalContact() { getCurExternalContact() {
this.$ww.getCurExternalContact({ this.$ww.getCurExternalContact({
success: (res) => { success: (res) => {
if (res.err_msg === 'getCurExternalContact:ok') { if (res.err_msg === "getCurExternalContact:ok") {
console.log(res, '重新进入获取企微外部联系人'); console.log(res, "重新进入获取企微外部联系人");
this.set_external_userid(res.userId); this.set_external_userid(res.userId);
// 确保 Vuex 状态更新后再跳转 // 确保 Vuex 状态更新后再跳转
this.$nextTick(() => { this.$nextTick(() => {
this.$router.replace('/'); this.$router.replace("/");
console.log(window.location.href, 'window.location.hrefuserInfo'); console.log(window.location.href, "window.location.hrefuserInfo");
}); });
} }
}, },
fail: (err) => { fail: (err) => {
console.log(err, '获取企微外部联系人失败'); console.log(err, "获取企微外部联系人失败");
// 错误处理 // 错误处理
}, },
}); });
}, },
// 2. 注册企微JS-SDK // 2. 注册企微JS-SDK
registerWeComSDK() { registerWeComSDK() {
console.log('删除企业签名', 1231); console.log("删除企业签名", 1231);
this.$ww.register({ this.$ww.register({
corpId: Cookies.get('corp_id'), corpId: Cookies.get("corp_id"),
agentId: this.signData.agent_id, agentId: this.signData.agent_id,
jsApiList: jsApiList, jsApiList: jsApiList,
// getConfigSignature: () => Promise.resolve({ // getConfigSignature: () => Promise.resolve({
...@@ -298,12 +401,12 @@ export default { ...@@ -298,12 +401,12 @@ export default {
signature: this.signData.agent_signature, signature: this.signData.agent_signature,
}), }),
onAgentConfigSuccess: (res) => { onAgentConfigSuccess: (res) => {
console.log('注册成功可以调用企微 js-sdk', res); console.log("注册成功可以调用企微 js-sdk", res);
// 注册成功后不立即获取外部联系人,等钉钉扫码后再获取 // 注册成功后不立即获取外部联系人,等钉钉扫码后再获取
this.getCurExternalContact(); this.getCurExternalContact();
}, },
onAgentConfigFail: (err) => { onAgentConfigFail: (err) => {
console.log('注册失败不能使用企微js-sdk', err); console.log("注册失败不能使用企微js-sdk", err);
// 错误处理123 // 错误处理123
}, },
}); });
...@@ -322,15 +425,15 @@ export default { ...@@ -322,15 +425,15 @@ export default {
}, },
initCurrentApp() { initCurrentApp() {
const currentApp = this.orgList.find( 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. 钉钉扫码回调页面处理 // 7. 钉钉扫码回调页面处理
async handleDingCallback(token) { async handleDingCallback(token) {
// 在这里处理钉钉扫码成功的回调 // 在这里处理钉钉扫码成功的回调
const corp_id = Cookies.get('corp_id'); const corp_id = Cookies.get("corp_id");
if (token && token != 'undefined') { if (token && token != "undefined") {
setToken(token); setToken(token);
this.set_token(token); this.set_token(token);
// 获取签名 // 获取签名
...@@ -338,9 +441,9 @@ export default { ...@@ -338,9 +441,9 @@ export default {
} else { } else {
window.location.href = window.location.href =
window.location.origin + window.location.origin +
'/company_app/index.html?corp_id=' + "/company_app/index.html?corp_id=" +
corp_id + corp_id +
'&msg=notoken'; "&msg=notoken";
} }
}, },
}, },
......
<template> <template>
<div class="info-tab-content"> <div class="info-tab-content">
<div class="userDetailsPanel columnFlex"> <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"> <div v-if="chatUserDetails.is_phishing_account == 1" class="warnText">
<p>高风险玩家,请立即通知组长!!!!</p> <p>高风险玩家,请立即通知组长!!!!</p>
<p> <p>
......
...@@ -11,7 +11,9 @@ module.exports = { ...@@ -11,7 +11,9 @@ module.exports = {
purge: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'], purge: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
darkMode: false, darkMode: false,
theme: { theme: {
extend: {} extend: {
}
}, },
variants: { variants: {
extend: {} extend: {}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论