提交 adecf774 作者: 施汉文

feat: 新增营销模块

上级 ded7e8cc
import request from '@/utils/request'
import store from '@/store/index'
import request from '@/utils/request';
import store from '@/store/index';
// 所属分组下拉
function returnApi(api){
return '/sidebar' + api
function returnApi(api) {
return '/sidebar' + api;
}
export function procedure_group(data) {
return request({
url: returnApi('/procedure_group/index'),
method: 'post',
data
})
data,
});
}
// 话术列表
export function procedureList(data) {
return request({
url: returnApi('/procedure/index'),
method: 'post',
data
})
data,
});
}
// 删除话术
......@@ -25,8 +25,8 @@ export function proceduredel(data) {
return request({
url: returnApi('/procedure/del'),
method: 'post',
data
})
data,
});
}
// 批量移动
......@@ -34,8 +34,8 @@ export function proceduremove(data) {
return request({
url: returnApi('/procedure/move'),
method: 'post',
data
})
data,
});
}
// 新增话术
......@@ -43,8 +43,8 @@ export function procedureadd(data) {
return request({
url: returnApi('/procedure/add'),
method: 'post',
data
})
data,
});
}
// 分组添加/修改
......@@ -52,8 +52,8 @@ export function procedure_groupAdd(data) {
return request({
url: returnApi('/procedure_group/add'),
method: 'post',
data
})
data,
});
}
// 分组删除
......@@ -61,8 +61,8 @@ export function procedure_groupDel(data) {
return request({
url: returnApi('/procedure_group/del'),
method: 'post',
data
})
data,
});
}
// 个人话术移到企业库
......@@ -70,8 +70,8 @@ export function addCompany(data) {
return request({
url: returnApi('/procedure/addCompany'),
method: 'post',
data
})
data,
});
}
// 个人话术详情
......@@ -79,8 +79,8 @@ export function procedureInfo(data) {
return request({
url: returnApi('/procedure/info'),
method: 'post',
data
})
data,
});
}
// 个人话术排序
......@@ -88,8 +88,8 @@ export function procedureSort(data) {
return request({
url: returnApi('/procedure/sort'),
method: 'post',
data
})
data,
});
}
// 个人话术租排序
......@@ -97,8 +97,8 @@ export function procedureGroupSort(data) {
return request({
url: returnApi('/procedure_group/sort'),
method: 'post',
data
})
data,
});
}
// 企业话术增至个人
......@@ -106,8 +106,8 @@ export function addToPersonal(data) {
return request({
url: returnApi('/procedure/addToPersonal'),
method: 'post',
data
})
data,
});
}
// 话术使用次数
......@@ -115,8 +115,8 @@ export function skillQuote(data) {
return request({
url: '/admin/procedure/quote',
method: 'post',
data
})
data,
});
}
/* ----------- 知识库的接口 ---------- */
......@@ -125,16 +125,16 @@ export function groupList(data) {
return request({
url: returnApi('/knowledge_group/index'),
method: 'post',
data
})
data,
});
}
// 知识库分组下拉
export function libraryIndex(data) {
return request({
url: returnApi('/knowledge_base/index'),
method: 'post',
data
})
data,
});
}
// 新增和编辑
......@@ -142,8 +142,8 @@ export function groupHandle(data) {
return request({
url: returnApi('/knowledge_group/add'),
method: 'post',
data
})
data,
});
}
// 删除分组
......@@ -151,63 +151,63 @@ export function groupDel(data) {
return request({
url: returnApi('/knowledge_group/del'),
method: 'post',
data
})
data,
});
}
// 新增知识库任务
export function addLibraryTask(data) {
return request({
url: returnApi('/knowledge_base/add'),
method: 'post',
data
})
data,
});
}
// 详情
export function libraryTaskView(data) {
return request({
url: returnApi('/knowledge_base/view'),
method: 'post',
data
})
data,
});
}
// 编辑
export function libraryTaskEdit(data) {
return request({
url: returnApi('/knowledge_base/edit'),
method: 'post',
data
})
data,
});
}
// 删除
export function libraryTaskDel(data) {
return request({
url: returnApi('/knowledge_base/del'),
method: 'post',
data
})
data,
});
}
// 批量删除
export function multipleDel(data) {
return request({
url: returnApi('/knowledge_base/batchDel'),
method: 'post',
data
})
data,
});
} // 导入
export function importData(data) {
return request({
url: returnApi('/knowledge_base/importKnowledgeBase'),
method: 'post',
data
})
data,
});
}
// 知识库计数
export function logClickTime(data) {
return request({
url: returnApi('/knowledge_base/logClickTime'),
method: 'post',
data
})
data,
});
}
// 问答模块
......@@ -215,18 +215,17 @@ export function Aihistory(data) {
return request({
url: returnApi('/corp_beta_question_log/history'),
method: 'post',
data
})
data,
});
}
// 同步知识库
export function asyncKnowledge(data) {
return request({
url: returnApi('/knowledge_base/syncToCorp'),
method: 'post',
data
})
data,
});
}
/* -------------------- 机器人知识库 ----------------------- */
......@@ -235,8 +234,8 @@ export function corp_robot_knowledge_add(data) {
return request({
url: returnApi('/corp_robot_knowledge_base/add'),
method: 'post',
data
})
data,
});
}
// 机器人知识库列表
......@@ -244,48 +243,48 @@ export function corp_robot_knowledge_list(data) {
return request({
url: returnApi('/corp_robot_knowledge_base/index'),
method: 'post',
data
})
data,
});
}
// 机器人知识库编辑
export function corp_robot_knowledge_edit(data) {
return request({
url: returnApi('/corp_robot_knowledge_base/edit'),
method: 'post',
data
})
data,
});
}
// 机器人知识库详情
export function corp_robot_knowledge_view(data) {
return request({
url: returnApi('/corp_robot_knowledge_base/view'),
method: 'post',
data
})
data,
});
}
// 机器人知识库删除
export function corp_robot_knowledge_del(data) {
return request({
url: returnApi('/corp_robot_knowledge_base/delete'),
method: 'post',
data
})
data,
});
}
// 机器人知识库批量删除
export function corp_robot_knowledge_batchDelete(data) {
return request({
url: returnApi('/corp_robot_knowledge_base/batchDelete'),
method: 'post',
data
})
data,
});
}
// 机器人知识库批量导入
export function corp_robot_knowledge_import(data) {
return request({
url: returnApi('/corp_robot_knowledge_base/import'),
method: 'post',
data
})
data,
});
}
/* --------------------机器人知识库分组-----------------------*/
// 知识库分组列表
......@@ -293,32 +292,32 @@ export function corp_robot_knowledge_group_index(data) {
return request({
url: returnApi('/corp_robot_knowledge_group/index'),
method: 'post',
data
})
data,
});
}
// 知识库分组新增
export function corp_robot_knowledge_group_add(data) {
return request({
url: returnApi('/corp_robot_knowledge_group/add'),
method: 'post',
data
})
data,
});
}
// 知识库分组编辑
export function corp_robot_knowledge_group_edit(data) {
return request({
url: returnApi('/corp_robot_knowledge_group/edit'),
method: 'post',
data
})
data,
});
}
// 知识库分组删除
export function corp_robot_knowledge_group_del(data) {
return request({
url: returnApi('/corp_robot_knowledge_group/delete'),
method: 'post',
data
})
data,
});
}
// AI问答对列表
......@@ -326,8 +325,8 @@ export function AI_list(data) {
return request({
url: returnApi('/corp_ai_question_answer/index'),
method: 'post',
data
})
data,
});
}
// 业务下拉
......@@ -335,8 +334,8 @@ export function search_condition(data) {
return request({
url: '/admin/search_condition',
method: 'post',
data
})
data,
});
}
// 智能体列表
......@@ -344,8 +343,8 @@ export function corp_beta_config(data) {
return request({
url: '/admin/corp_beta_config/index',
method: 'post',
data
})
data,
});
}
// 标记有用/无用
......@@ -353,22 +352,30 @@ export function markUseful(data) {
return request({
url: returnApi('/corp_ai_question_answer/markUseful'),
method: 'post',
data
})
data,
});
}
// 跨主体分组列表
export function cross_corp_robot_knowledge_group_index(data) {
return request({
url: returnApi('/corp_cross_knowledge_group/index'),
method: 'post',
data
})
data,
});
}
// 跨主体知识库分组列表
export function cross_corp_robot_knowledge_group_getList(data) {
return request({
url: returnApi('/corp_cross_knowledge_base/getList'),
method: 'post',
data
})
}
\ No newline at end of file
data,
});
}
// 营销面板-话术生成
export function getGenerateProcedureApi(data) {
return request({
url: returnApi('/corp_activity_procedure/generateProcedure'),
method: 'post',
data,
});
}
......@@ -2,19 +2,76 @@
<div class="details-user-info-role columnFlex">
<div v-loading="loading" class="detailsContent">
<div v-if="roleList.length > 0">
<p class="textInfo">角色充值金额信息会有5-10分钟延迟,请以订单信息为准</p>
<p class="textInfo">
角色充值金额信息会有5-10分钟延迟,请以订单信息为准
</p>
<el-collapse v-model="collapseActive" @change="handleChange">
<div v-for="(items, indexs) in roleList" :key="indexs" class="contentItem mb-[10px]">
<div
v-for="(items, indexs) in roleList"
:key="indexs"
class="contentItem mb-[10px]"
>
<div class="title"></div>
<el-collapse-item :name="items.id">
<template slot="title">
<div class="collapseTitle rowFlex columnCenter spaceBetween">
<!-- <div class="collapseTitle rowFlex columnCenter spaceBetween">
<p class="hidden">
{{ items.role_name }} - {{ items.server_name }} - {{
items.recharge_total ? items.recharge_total + '元' : '0元' }}
</p>
<el-button type="primary" size="mini" class="collapseTitleBtn"
@click.stop="appealLayer(items)">申诉</el-button>
</div> -->
<div class="flex w-[100%] justify-between">
<div>
<div>
<span>角色名:</span><span>{{ items.role_name }}</span>
</div>
<div>
<span>区服:</span><span>{{ items.server_name }}</span>
</div>
<div>
<span>充值金额:</span
><span>{{
items.recharge_total
? items.recharge_total + '元'
: '0元'
}}</span>
</div>
</div>
<div
class="flex-1 h-0 flex justify-end items-start pt-[10px]"
>
<el-button
type="primary"
size="mini"
class="collapseTitleBtn"
@click.stop="appealLayer(items)"
>申诉</el-button
>
<el-badge
:value="
roleRecentActivityNotPushNumInstance?.getNumByRoleId(
items.role_id
)
"
class="text-center leading-[0] ml-[8px]"
>
<el-button
type="primary"
size="mini"
@click.stop="
() =>
recentActivitiesPopupInstance.instance.open(
items.role_id,
`${items.role_name}-${items.server_name}-${items.recharge_total}元`
)
"
>
近期要开</el-button
>
</el-badge>
</div>
</div>
</template>
<div class="item rowFlex columnCenter spaceBetween">
......@@ -68,13 +125,25 @@
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">最近活跃时间:</span>
<p class="text">{{ $moment(items.last_login_time * 1000).format('YYYY-MM-DD HH:mm:ss') }}</p>
<p class="text">
{{
$moment(items.last_login_time * 1000).format(
'YYYY-MM-DD HH:mm:ss'
)
}}
</p>
</div>
</div>
<div class="item rowFlex columnCenter spaceBetween">
<div class="rowFlex columnCenter">
<span class="label">创建时间:</span>
<p class="text">{{ $moment(items.create_time * 1000).format('YYYY-MM-DD HH:mm:ss') }}</p>
<p class="text">
{{
$moment(items.create_time * 1000).format(
'YYYY-MM-DD HH:mm:ss'
)
}}
</p>
</div>
</div>
<div class="item rowFlex columnCenter spaceBetween">
......@@ -87,25 +156,37 @@
</div>
</el-collapse>
</div>
<div v-else-if="!loading && roleList.length == 0" class="noContent rowFlex allCenter">
<noContent title="暂无数据" description="当前没有任何数据,请稍后再试或联系管理员" />
<div
v-else-if="!loading && roleList.length == 0"
class="noContent rowFlex allCenter"
>
<noContent
title="暂无数据"
description="当前没有任何数据,请稍后再试或联系管理员"
/>
</div>
</div>
<appeal v-if="showAppeal" :show.sync="showAppeal" :appeal-info="appealInfo" />
<appeal
v-if="showAppeal"
:show.sync="showAppeal"
:appeal-info="appealInfo"
/>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex'
import { getRoleHoLo } from '@/api/game'
import noContent from '@/components/noContent.vue'
import appeal from './layer/appeal.vue'
import watchMember from '@/mixins/watchMember'
import { mapState, mapMutations, mapActions } from 'vuex';
import { getRoleHoLo } from '@/api/game';
import noContent from '@/components/noContent.vue';
import appeal from './layer/appeal.vue';
import watchMember from '@/mixins/watchMember';
import { createDetails } from '@/views/popup/RecentActivitiesPopup/index.js';
import { createRoleRecentActivityNotPushNum } from '@/views/hooks/useGetCount.js';
export default {
name: 'roleInfo',
components: {
noContent,
appeal
appeal,
},
data() {
return {
......@@ -118,58 +199,75 @@ export default {
pageInfo: {
page_size: 100,
page: 1,
total: 0
total: 0,
},
infoList: []
}
infoList: [],
recentActivitiesPopupInstance: null, //近期要开模块弹框
roleRecentActivityNotPushNumInstance: null, //侧边栏计数弹框
};
},
computed: {
...mapState('game', ['accountSelect'])
...mapState('game', ['accountSelect']),
},
mixins: [watchMember],
mounted() {
this.requestRoleList()
this.nowTime = new Date().getTime()
this.requestRoleList();
this.nowTime = new Date().getTime();
// 初始化创建角色最近活动未推送数量
this.initInstance();
},
methods: {
handleChange() {
//初始化创建模块
async initInstance() {
this.recentActivitiesPopupInstance = createDetails();
this.roleRecentActivityNotPushNumInstance =
await createRoleRecentActivityNotPushNum(this.accountSelect);
},
handleChange() {},
memberChange() {
this.requestRoleList()
this.requestRoleList();
},
// 申诉
appealLayer(item) {
this.appealInfo = item
this.showAppeal = true
this.appealInfo = item;
this.showAppeal = true;
},
requestRoleList() {
if (this.accountSelect === '') {
this.$message.warning('暂无关联的账号,请先去关联账号!')
return false
this.$message.warning('暂无关联的账号,请先去关联账号!');
return false;
}
this.loading = true
this.loading = true;
const data = {
api_search_name: '',
member_id: this.accountSelect,
search_type: 'list',
...this.pageInfo
}
getRoleHoLo(data).then(res => {
this.loading = false
if (res.status_code == 1) {
if (res.data.data.length > 0) {
this.roleList = res.data.data.sort((a, b) => { return Number(b.recharge_total) - Number(a.recharge_total) })
} else {
this.roleList = []
...this.pageInfo,
};
getRoleHoLo(data).then(
(res) => {
this.loading = false;
if (res.status_code == 1) {
if (res.data.data.length > 0) {
this.roleList = res.data.data.sort((a, b) => {
return Number(b.recharge_total) - Number(a.recharge_total);
});
} else {
this.roleList = [];
}
}
},
(err) => {
this.loading = false;
}
}, err => {
this.loading = false
})
}
}
}
);
},
},
beforeDestroy() {
this.recentActivitiesPopupInstance.destroy();
this.roleRecentActivityNotPushNumInstance?.destroy();
},
};
</script>
<style lang="scss" scoped>
.details-user-info-role {
......@@ -291,7 +389,26 @@ export default {
display: block;
}
}
::v-deep .el-collapse-item {
margin-bottom: 20px;
}
::v-deep .el-collapse-item__content {
padding-bottom: 10px;
}
::v-deep .el-collapse {
border: none;
}
::v-deep .el-collapse-item__header {
width: 100%;
height: auto;
background: #f9faff;
color: #333333;
padding-left: 10px;
font-size: 14px;
font-weight: 400;
}
/* 已移除局部 el-collapse 样式,使用全局样式 */
}
</style>
\ No newline at end of file
</style>
import { getRoleRecentActivityNotPushNumApi } from '@/api/game';
// 账号近期要开活动数
let roleRecentActivityNotPushNum = null;
let cacheMemberId = null;
function setCacheMemberId(member_id) {
cacheMemberId = member_id;
}
export async function queryRoleRecentActivityNotPushNum(member_id) {
const { data } = await getRoleRecentActivityNotPushNumApi({
member_id: member_id,
});
roleRecentActivityNotPushNum = data.data;
}
function validate(v) {
if (!roleRecentActivityNotPushNum)
throw new Error(`执行${v}前请先调用createRoleRecentActivityNotPushNum方法`);
}
export function getTotalNum() {
validate('getTotalNum');
return roleRecentActivityNotPushNum?.totalNum || null;
}
export function getNumByRoleId(role_id) {
validate('getNumByRoleId');
return (
roleRecentActivityNotPushNum?.roleNum.find(
(item) => item.role_id == role_id
)?.num || null
);
}
export function destroy() {
roleRecentActivityNotPushNum = null;
cacheMemberId = null;
}
export async function createRoleRecentActivityNotPushNum(member_id) {
if (member_id || member_id !== cacheMemberId) {
setCacheMemberId(member_id);
await queryRoleRecentActivityNotPushNum(member_id);
}
return {
queryRoleRecentActivityNotPushNum,
getTotalNum,
getNumByRoleId,
destroy,
};
}
<template>
<div v-loading="loading">
<div class="px-[20px] h-full space-y-[8px] rounded-[4px] overflow-y-auto">
<template v-if="list.length">
<div
class="bg-[#F7F8FA] min-h-[99px] p-[8px]"
v-for="item in list"
:key="item.id"
>
<div
class="text-[#131920] pb-[8px] text-[14px] border-b-[1px] border-solid border-[#E5E5E6]"
>
主服 {{ item.main_server_day }} 天开启{{ item.name }}活动
</div>
<div class="text-[13px] flex pt-[8px]">
<div class="text-[#6D7176] mr-[16px] flex-shrink-0">活动详情</div>
<div class="text-[#131920]">{{ item.detail }}</div>
</div>
</div>
</template>
<svg-icon v-else icon-class="noContent" class="text-[280px]" />
</div>
</div>
</template>
<script>
import { mapState } from 'vuex';
import { getRecentActivityListApi } from '@/api/game';
export default {
name: 'ActivityConfigurationList',
components: {},
props: ['role_id'],
data() {
return {
list: [],
loading: false,
};
},
computed: {
...mapState('game', ['gameUserInfo']),
},
methods: {
async getRecentActivityList() {
try {
this.loading = true;
const { data } = await getRecentActivityListApi({
role_id: this.role_id,
main_game_id: this.gameUserInfo.main_game_id,
weixin_blongs_id: this.gameUserInfo.weixin_blongs_id,
});
this.list = data.data;
} catch (error) {
} finally {
this.loading = false;
}
},
},
created() {
this.getRecentActivityList();
},
};
</script>
<style lang="scss" scoped></style>
<template>
<div v-loading="loading">
<div class="px-[20px] h-full gap-y-[8px] overflow-y-auto">
<template v-if="list.length">
<RecentActivities
@handleUpdate="query"
:item="item"
v-for="item in list"
:key="item.activity_rule_id"
/>
</template>
<svg-icon v-else icon-class="noContent" class="text-[280px]" />
</div>
</div>
</template>
<script>
import RecentActivities from '@/views/popup/RecentActivitiesPopup/templates/RecentActivities.vue';
import { getRoleRecentActivityListApi } from '@/api/game';
export default {
name: 'RecentActivitiesList',
components: { RecentActivities },
props: ['role_id'],
data() {
return {
list: [],
loading: false,
};
},
methods: {
async query() {
try {
this.loading = true;
const { data } = await getRoleRecentActivityListApi({
role_id: this.role_id,
});
this.list = data.data;
} catch (error) {
} finally {
this.loading = false;
}
},
},
created() {
this.query();
},
};
</script>
<style lang="scss" scoped></style>
// utils/componentHelper.js 或 useCreatePlayerDetails.js
import Vue from 'vue'
import RecentActivitiesPopup from './index.vue'
import store from '@/store' // 导入你的 Vuex store
export function createDetails(propsData = {}) {
const ComponentConstructor = Vue.extend(RecentActivitiesPopup)
const instance = new ComponentConstructor({
propsData,
// 手动注入 store
store
})
const mountNode = document.createElement('div')
document.querySelector('#recentActivitiesPopup').appendChild(mountNode)
instance.$mount(mountNode)
return {
instance,
destroy: () => {
instance.$destroy()
if (instance.$el && instance.$el.parentNode) {
instance.$el.parentNode.removeChild(instance.$el)
}
}
}
}
\ No newline at end of file
<template>
<div class="absolute z-10 top-0 left-0 h-full w-full bg-white" v-if="show">
<div
class="h-[60px] relative px-[18px] flex items-center border-b-[1px] border-solid border-[#e5e6eb]"
>
<i
class="el-icon-arrow-left text-[25px] hover:cursor-pointer"
@click="close"
></i>
<span
class="absolute left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2 text-[#323335] font-bold"
>{{ title }}</span
>
</div>
<el-tabs class="h-[40px]" v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="近期要开" name="0"> </el-tab-pane>
<el-tab-pane label="活动配置" name="1"> </el-tab-pane>
</el-tabs>
<RecentActivitiesList v-if="activeName === '0'" :role_id="role_id" />
<ActivityConfigurationList v-if="activeName === '1'" :role_id="role_id" />
</div>
</template>
<script>
import RecentActivitiesList from './components/RecentActivitiesList.vue';
import ActivityConfigurationList from './components/ActivityConfigurationList.vue';
export default {
name: 'RecentActivitiesPopup',
components: { RecentActivitiesList, ActivityConfigurationList },
data() {
return {
show: false,
activeName: '0',
role_id: '',
title: '',
};
},
methods: {
open(role_id, title) {
this.show = true;
this.role_id = role_id;
this.title = title;
},
handleClick() {},
close() {
this.show = false;
this.activeName = '0';
},
},
created() {},
};
</script>
<style lang="scss" scoped>
::v-deep .el-tabs__item {
padding: 0 20px !important;
}
</style>
<template>
<div
class="space-y-[12px] mt-[10px] !p-[8px] bg-[#F7F8FA] rounded-[4px] item"
>
<div>
<span class="label">近期要开:</span>
<el-popover
placement="top-start"
width="250"
trigger="hover"
:content="item.activity_rule_detail"
>
<span slot="reference">{{ item.activity_rule_name }}</span>
</el-popover>
</div>
<div>
<span class="label">开启时间:</span
><span>{{ item.open_activity_time }}</span>
</div>
<div>
<span class="label">关联客服:</span><span>{{ item.cser_name }}</span>
</div>
<div class="group">
<span class="label">备注:</span
><span v-show="!editShow">{{ item.remark }}</span>
<el-input
@blur="updated"
v-show="editShow"
type="textarea"
:rows="2"
placeholder="请输入内容"
v-model.trim="textarea"
>
</el-input>
<svg-icon
icon-class="edit"
class="icon invisible group-hover:visible"
style="font-size: 14px"
@click="editRemark"
/>
</div>
<div class="flex items-center">
<span class="label flex-shrink-0">推送状态:</span>
<span v-if="item.is_push === '2'">已推送</span>
<el-select
v-else
class="w-[70px]"
:clearable="false"
:value="item.is_push"
@change="handleChange"
>
<el-option label="未推送" value="1"> </el-option>
<el-option label="已推送" value="2"> </el-option>
</el-select>
</div>
<div class="flex items-center">
<span class="label flex-shrink-0">推送话术:</span>
<span
class="group flex-1 w-0 flex items-center"
v-if="pushLanguageTechnique"
>
<span class="truncate flex-1">{{ pushLanguageTechnique }}</span>
<i
class="el-icon-refresh mr-[8px] refreshList invisible group-hover:visible"
:class="isRefresh ? 'refreshListActive' : ''"
@click="refreshTag"
></i>
<svg-icon
icon-class="fuzhi"
class="icon invisible group-hover:visible"
style="font-size: 14px"
@click="copyText"
/>
</span>
<el-button
v-else
size="mini"
@click="queryGenerateProcedure"
:loading="isRefresh"
>生成话术</el-button
>
</div>
<slot></slot>
</div>
</template>
<script>
import { getRoleRecentActivityEditApi } from '@/api/game.js';
import { getGenerateProcedureApi } from '@/api/skill';
import { mapState } from 'vuex';
const UpdateType = {
PUSH: 1, //修改推送
REMARK: 2, //修改备注
};
export default {
name: 'RecentActivitiesTemplate',
emits: ['handleUpdate'],
components: {},
props: ['item'],
data() {
return {
editShow: false,
textarea: '',
isRefresh: false,
pushLanguageTechnique: '', //推送话术
};
},
computed: {
...mapState('common', ['zqUserInfo']),
...mapState('game', ['accountSelect', 'bindGameUserList']),
nowGameUserInfo() {
return {
member_id: this.accountSelect,
username: this.bindGameUserList.find(
(item) => item.member_id == this.accountSelect
)?.username,
};
},
},
methods: {
editRemark() {
this.editShow = true;
this.textarea = this.item.remark;
},
async updated() {
this.editShow = false;
if (this.textarea === this.item.remark) return;
this.edit(UpdateType.REMARK);
},
handleChange() {
this.edit(UpdateType.PUSH);
},
async edit(type) {
try {
await getRoleRecentActivityEditApi({
type,
role_id: this.item.role_id,
open_activity_time: this.item.open_activity_time,
remark: this.textarea,
activity_rule_id: this.item.activity_rule_id,
is_push: 2,
user_id: this.zqUserInfo.zq_user_id,
user_name: this.zqUserInfo.name,
});
this.$message.success('修改成功');
this.$emit('handleUpdate');
} catch (error) {
this.$message.error(error);
}
},
async queryGenerateProcedure() {
try {
this.isRefresh = true;
const { data } = await getGenerateProcedureApi({
...this.item,
...this.nowGameUserInfo,
});
this.pushLanguageTechnique = data.content;
} catch (error) {
} finally {
this.isRefresh = false;
}
},
async copyText() {
try {
await navigator.clipboard.writeText(this.pushLanguageTechnique);
this.$message.success('复制成功');
} catch (err) {
console.error('复制失败:', err);
}
},
refreshTag() {
this.queryGenerateProcedure();
},
},
created() {
console.log(this.nowGameUserInfo, 1111111);
},
};
</script>
<style lang="scss" scoped>
.item {
width: 100%;
height: auto;
font-size: 14px;
font-weight: 400;
color: #333333;
transition: all 0.5s;
position: relative;
cursor: pointer;
.label {
font-size: 14px;
color: #999999;
font-weight: 500;
margin-right: 8px;
}
.tag-icon {
cursor: pointer;
font-size: 14px;
color: #333333;
margin-right: 8px;
}
}
.refreshListActive {
animation: rotate 0.5s linear infinite;
}
.refreshList {
color: #00bf8a;
cursor: pointer;
font-size: 18px;
}
::v-deep .el-input__inner {
background-color: transparent;
border: 0;
box-shadow: none;
padding: 0;
}
::v-deep .el-select .el-input.is-focus .el-input__inner {
border-color: transparent !important;
box-shadow: none;
}
</style>
<template>
<!-- 营销面板组件 -->
<div class="item">
<div class="rowFlex columnCenter">
<span class="label">营销面板:</span>
<i
v-if="recentInfo.role_id"
:class="['el-icon-arrow-' + (active ? 'down' : 'right'), 'tag-icon']"
@click="handleClick"
></i>
</div>
<RecentActivities
v-if="recentInfo.role_id"
:item="recentInfo"
v-show="active"
@handleUpdate="getRoleData"
>
<el-button
type="text"
size="mini"
@click="
() =>
recentActivitiesPopupInstance.instance.open(
recentInfo.role_id,
popupTitle
)
"
>
查看更多 >
</el-button>
</RecentActivities>
</div>
</template>
<script>
import RecentActivities from '@/views/popup/RecentActivitiesPopup/templates/RecentActivities.vue';
import { createDetails } from '@/views/popup/RecentActivitiesPopup/index.js';
import { getRoleRecentActivityOneApi } from '@/api/game';
import { getRoleHoLo } from '@/api/game';
import { mapState } from 'vuex';
export default {
name: 'MarketingPanel',
components: { RecentActivities },
data() {
return {
active: true,
recentActivitiesPopupInstance: null, //近期要开模块弹框
recentInfo: {},
roleInfoList: [],
};
},
computed: {
...mapState('game', ['accountSelect']),
popupTitle() {
const findItem = this.roleInfoList.find(
(item) => item.role_id == this.recentInfo.role_id
);
if (findItem) {
return `${findItem.role_name}-${findItem.server_name}-${findItem.recharge_total}元`;
}
return;
},
},
methods: {
async queryGetRoleHoLo() {
const { data } = await getRoleHoLo({
page_size: 100,
page: 1,
member_id: this.accountSelect,
search_type: 'list',
});
this.roleInfoList = data.data;
},
handleClick() {
this.active = !this.active;
},
async getRoleData() {
const { data } = await getRoleRecentActivityOneApi({
member_id: this.accountSelect,
});
this.recentInfo = data.data;
},
},
created() {
this.getRoleData();
this.queryGetRoleHoLo();
},
mounted() {
this.recentActivitiesPopupInstance = createDetails({
gameUserInfoInject: this.gameUserInfoInject,
});
},
beforeDestroy() {
this.recentActivitiesPopupInstance.destroy();
},
};
</script>
<style lang="scss" scoped>
.item {
width: 100%;
height: auto;
font-size: 14px;
padding: 16px;
font-weight: 400;
color: #333333;
padding: 10px 0;
transition: all 0.5s;
position: relative;
cursor: pointer;
.label {
font-size: 14px;
color: #999999;
font-weight: 500;
margin-right: 8px;
}
.tag-icon {
cursor: pointer;
font-size: 14px;
color: #333333;
margin-right: 8px;
}
}
.refreshListActive {
animation: rotate 0.5s linear infinite;
}
.refreshList {
color: #3491fa;
cursor: pointer;
font-size: 18px;
}
</style>
<template>
<div class="userInfo-content">
<div class="userInfo-content relative" id="recentActivitiesPopup">
<el-tabs v-model="activeTab" class="user-tabs">
<el-tab-pane label="客户信息" name="info">
<Info :chatUserDetails="chatUserInfo"/>
<Info :chatUserDetails="chatUserInfo" />
</el-tab-pane>
<el-tab-pane label="角色信息" name="role">
<template #label v-if="totalNum">
<el-badge :value="totalNum" class="text-center">
<p>角色信息</p>
</el-badge>
</template>
<roleInfo v-if="activeTab === 'role'" />
</el-tab-pane>
<el-tab-pane label="订单信息" name="order">
......@@ -17,52 +22,68 @@
</div>
</template>
<script>
import Info from './components/Info.vue'
import roleInfo from '@/views/roleInfo.vue'
import orderList from '@/views/orderList.vue'
import violationRecord from '@/views/ViolationRecord.vue'
import { mapState, mapMutations } from 'vuex'
import Cookies from 'js-cookie'
import Info from './components/Info.vue';
import roleInfo from '@/views/roleInfo.vue';
import orderList from '@/views/orderList.vue';
import violationRecord from '@/views/ViolationRecord.vue';
import { mapState, mapMutations } from 'vuex';
import { createRoleRecentActivityNotPushNum } from '@/views/hooks/useGetCount';
import Cookies from 'js-cookie';
export default {
name: 'userInfo',
components: {
Info,
roleInfo,
orderList,
violationRecord
violationRecord,
},
mounted() {
mounted() {},
watch: {
async accountSelect(newVal) {
await this.initInstance();
console.log(this.instance.getTotalNum(), '+++++++++++++++++++++++');
this.totalNum = this.instance.getTotalNum();
},
},
data() {
return {
activeTab: 'info'
}
activeTab: 'info',
instance: null,
totalNum: 0,
};
},
computed: {
...mapState('game', ['chatUserInfo']),
...mapState('game', ['chatUserInfo', 'accountSelect']),
},
created() {
// 初始化 vuex 中的值
},
mounted() {
this.$nextTick(() => {
this.initVuexValue()
})
this.initVuexValue();
});
},
methods: {
...mapMutations('user', ['set_userInfo']),
initVuexValue(){
async initInstance() {
this.instance = await createRoleRecentActivityNotPushNum(
this.accountSelect
);
},
initVuexValue() {
const userinfo = {
cser_id: Cookies.get('cser_id'),
cser_name: Cookies.get('cser_name'),
username: Cookies.get('cser_name'),
id: Cookies.get('cser_id'),
}
this.set_userInfo(userinfo)
}
}
}
};
this.set_userInfo(userinfo);
},
},
beforeDestroy() {
this.instance.destroy();
},
};
</script>
<style lang="scss" scoped>
......@@ -74,29 +95,33 @@ export default {
.user-tabs {
width: 100%;
::v-deep .el-tabs__header {
margin-bottom: 15px;
padding: 0 10px;
}
::v-deep .el-tabs__nav-wrap::after {
height: 1px;
}
::v-deep .el-tabs__item {
height: 40px;
line-height: 40px;
font-size: 14px;
}
::v-deep .el-tabs__active-bar {
height: 2px;
}
::v-deep .el-tabs__content {
height: calc(100% - 55px);
}
}
}
::v-deep .el-badge__content.is-fixed {
top: 8px;
right: 6px;
}
</style>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论