提交 aa6c25af 作者: 毛细亚

更新代码

上级 2867edc8
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
<script> <script>
import bindUserList from '@/views/components/bindGameAccount/bindUserList.vue' import bindUserList from '@/views/components/bindGameAccount/bindUserList.vue'
import { getToken } from '@/utils/auth' import { getToken } from '@/utils/auth'
import { mapState } from 'vuex' import { mapState, mapMutations } from 'vuex'
import Cookies from 'js-cookie' import Cookies from 'js-cookie'
export default { export default {
name: 'App', name: 'App',
...@@ -40,14 +40,14 @@ export default { ...@@ -40,14 +40,14 @@ export default {
label: '客户信息', label: '客户信息',
path: '/userInfo' path: '/userInfo'
}, },
// { {
// label: '快捷回复', label: '快捷回复',
// path: '/quickReply' path: '/quickReply'
// }, },
// { {
// label: '礼包记录', label: '礼包记录',
// path: '/giftRecord' path: '/giftRecord'
// }, },
// { // {
// label: '申请记录', // label: '申请记录',
// path: '/applyRecord' // path: '/applyRecord'
...@@ -94,6 +94,23 @@ export default { ...@@ -94,6 +94,23 @@ export default {
} }
}, },
mounted() { mounted() {
// 页面刷新时从 Cookie 恢复 token 到 store
const cookieToken = Cookies.get('token')
if (cookieToken && !this.token) {
this.set_token(cookieToken)
console.log('从 Cookie 恢复 token:', cookieToken)
}
// 调试信息:检查所有关键状态
console.log('App mounted - 关键状态检查:', {
token: this.token,
external_userid: this.external_userid,
showMemberId: this.showMemberId,
cookieToken: Cookies.get('token'),
cookieExternalUserId: Cookies.get('external_userid'),
currentPath: this.$route.path
})
// 初始化时处理路径 // 初始化时处理路径
const currentPath = this.$route.path const currentPath = this.$route.path
if (currentPath === '/' || currentPath === '' || currentPath === '/index.html') { if (currentPath === '/' || currentPath === '' || currentPath === '/index.html') {
...@@ -104,6 +121,7 @@ export default { ...@@ -104,6 +121,7 @@ export default {
console.log('创建时路径:', currentPath, '选中路径:', this.selectedPath) console.log('创建时路径:', currentPath, '选中路径:', this.selectedPath)
}, },
methods:{ methods:{
...mapMutations('user', ['set_token']),
handleSelect(key, keyPath) { handleSelect(key, keyPath) {
console.log('菜单选择:', key, keyPath, window.location.href) console.log('菜单选择:', key, keyPath, window.location.href)
} }
......
import request from '@/utils/request'
import store from '@/store/index'
// 所属分组下拉
function returnApi(api){
return '/sidebar' + api
}
export function procedure_group(data) {
return request({
url: returnApi('/procedure_group/index'),
method: 'post',
data
})
}
// 话术列表
export function procedureList(data) {
return request({
url: returnApi('/procedure/index'),
method: 'post',
data
})
}
// 删除话术
export function proceduredel(data) {
return request({
url: returnApi('/procedure/del'),
method: 'post',
data
})
}
// 批量移动
export function proceduremove(data) {
return request({
url: returnApi('/procedure/move'),
method: 'post',
data
})
}
// 新增话术
export function procedureadd(data) {
return request({
url: returnApi('/procedure/add'),
method: 'post',
data
})
}
// 分组添加/修改
export function procedure_groupAdd(data) {
return request({
url: returnApi('/procedure_group/add'),
method: 'post',
data
})
}
// 分组删除
export function procedure_groupDel(data) {
return request({
url: returnApi('/procedure_group/del'),
method: 'post',
data
})
}
// 个人话术移到企业库
export function addCompany(data) {
return request({
url: returnApi('/procedure/addCompany'),
method: 'post',
data
})
}
// 个人话术详情
export function procedureInfo(data) {
return request({
url: returnApi('/procedure/info'),
method: 'post',
data
})
}
// 个人话术排序
export function procedureSort(data) {
return request({
url: returnApi('/procedure/sort'),
method: 'post',
data
})
}
// 个人话术租排序
export function procedureGroupSort(data) {
return request({
url: returnApi('/procedure_group/sort'),
method: 'post',
data
})
}
// 企业话术增至个人
export function addToPersonal(data) {
return request({
url: returnApi('/procedure/addToPersonal'),
method: 'post',
data
})
}
// 话术使用次数
export function skillQuote(data) {
return request({
url: '/admin/procedure/quote',
method: 'post',
data
})
}
/* ----------- 知识库的接口 ---------- */
// 知识库分组列表
export function groupList(data) {
return request({
url: returnApi('/knowledge_group/index'),
method: 'post',
data
})
}
// 知识库分组下拉
export function libraryIndex(data) {
return request({
url: returnApi('/knowledge_base/index'),
method: 'post',
data
})
}
// 新增和编辑
export function groupHandle(data) {
return request({
url: returnApi('/knowledge_group/add'),
method: 'post',
data
})
}
// 删除分组
export function groupDel(data) {
return request({
url: returnApi('/knowledge_group/del'),
method: 'post',
data
})
}
// 新增知识库任务
export function addLibraryTask(data) {
return request({
url: returnApi('/knowledge_base/add'),
method: 'post',
data
})
}
// 详情
export function libraryTaskView(data) {
return request({
url: returnApi('/knowledge_base/view'),
method: 'post',
data
})
}
// 编辑
export function libraryTaskEdit(data) {
return request({
url: returnApi('/knowledge_base/edit'),
method: 'post',
data
})
}
// 删除
export function libraryTaskDel(data) {
return request({
url: returnApi('/knowledge_base/del'),
method: 'post',
data
})
}
// 批量删除
export function multipleDel(data) {
return request({
url: returnApi('/knowledge_base/batchDel'),
method: 'post',
data
})
} // 导入
export function importData(data) {
return request({
url: returnApi('/knowledge_base/importKnowledgeBase'),
method: 'post',
data
})
}
// 知识库计数
export function logClickTime(data) {
return request({
url: returnApi('/knowledge_base/logClickTime'),
method: 'post',
data
})
}
// 大模型 ai
export function getCorpBetaConfig(data) {
return request({
url: '/admin/corp_beta_config/getCorpBetaConfig',
method: 'post',
data
})
}
// 问答模块
export function getAiResponse(data) {
return request({
url: returnApi('/corp_beta_question_log/getAiResponse'),
method: 'post',
data
})
}
// 问答模块
export function Aihistory(data) {
return request({
url: returnApi('/corp_beta_question_log/history'),
method: 'post',
data
})
}
// 赞同模块
export function answerComment(data) {
return request({
url: returnApi('/corp_beta_question_log/answerComment'),
method: 'post',
data
})
}
// 复制次数统计
export function calAnswerClickTime(data) {
return request({
url: returnApi('/corp_beta_question_log/calAnswerClickTime'),
method: 'post',
data
})
}
// 获取来源
export function getQuoteData(data) {
return request({
url: returnApi('/corp_beta_question_log/getQuoteData'),
method: 'post',
data
})
}
// 同步知识库
export function asyncKnowledge(data) {
return request({
url: returnApi('/knowledge_base/syncToCorp'),
method: 'post',
data
})
}
/* -------------------- 机器人知识库 ----------------------- */
// 新增机器人知识库任务
export function corp_robot_knowledge_add(data) {
return request({
url: returnApi('/corp_robot_knowledge_base/add'),
method: 'post',
data
})
}
// 机器人知识库列表
export function corp_robot_knowledge_list(data) {
return request({
url: returnApi('/corp_robot_knowledge_base/index'),
method: 'post',
data
})
}
// 机器人知识库编辑
export function corp_robot_knowledge_edit(data) {
return request({
url: returnApi('/corp_robot_knowledge_base/edit'),
method: 'post',
data
})
}
// 机器人知识库详情
export function corp_robot_knowledge_view(data) {
return request({
url: returnApi('/corp_robot_knowledge_base/view'),
method: 'post',
data
})
}
// 机器人知识库删除
export function corp_robot_knowledge_del(data) {
return request({
url: returnApi('/corp_robot_knowledge_base/delete'),
method: 'post',
data
})
}
// 机器人知识库批量删除
export function corp_robot_knowledge_batchDelete(data) {
return request({
url: returnApi('/corp_robot_knowledge_base/batchDelete'),
method: 'post',
data
})
}
// 机器人知识库批量导入
export function corp_robot_knowledge_import(data) {
return request({
url: returnApi('/corp_robot_knowledge_base/import'),
method: 'post',
data
})
}
/* --------------------机器人知识库分组-----------------------*/
// 知识库分组列表
export function corp_robot_knowledge_group_index(data) {
return request({
url: returnApi('/corp_robot_knowledge_group/index'),
method: 'post',
data
})
}
// 知识库分组新增
export function corp_robot_knowledge_group_add(data) {
return request({
url: returnApi('/corp_robot_knowledge_group/add'),
method: 'post',
data
})
}
// 知识库分组编辑
export function corp_robot_knowledge_group_edit(data) {
return request({
url: returnApi('/corp_robot_knowledge_group/edit'),
method: 'post',
data
})
}
// 知识库分组删除
export function corp_robot_knowledge_group_del(data) {
return request({
url: returnApi('/corp_robot_knowledge_group/delete'),
method: 'post',
data
})
}
// AI问答对列表
export function AI_list(data) {
return request({
url: returnApi('/corp_ai_question_answer/index'),
method: 'post',
data
})
}
// 业务下拉
export function search_condition(data) {
return request({
url: '/admin/search_condition',
method: 'post',
data
})
}
// 智能体列表
export function corp_beta_config(data) {
return request({
url: '/admin/corp_beta_config/index',
method: 'post',
data
})
}
// 标记有用/无用
export function markUseful(data) {
return request({
url: returnApi('/corp_ai_question_answer/markUseful'),
method: 'post',
data
})
}
...@@ -90,3 +90,12 @@ export function zyouUnBind(data) { ...@@ -90,3 +90,12 @@ export function zyouUnBind(data) {
data data
}) })
} }
// 获取礼包码列表
export function getSendingCodeList(data) {
return request({
url: returnApi('/corp_gift_package_list/getSendingCodeList'),
method: 'post',
data
})
}
\ No newline at end of file
// 引入所有需要注册的全局组件
import noContent from '@/components/noContent.vue'
const globalComponents = [
noContent
]
export default {
install(Vue) {
globalComponents.forEach((component) => {
Vue.component(component.name, component)
})
}
}
<template>
<div class="search-item">
<div v-if=" label&& label.length<6" class="item-label">{{ label }}</div>
<div v-else-if="label &&label.length>=6 " class="item-label">
{{ label.slice(0,4) }} <br> {{ label.slice(4,label.length) }}
</div>
<div v-else class="item-label"></div>
<div class="item-content selectUser">
<BiDatePicker
v-model="dateValue"
:disabled="disabled"
:style="{'width':width ||''}"
:type="type?'datetimerange':'daterange'"
:format="type?'yyyy-MM-dd HH:mm:ss':'yyyy-MM-dd'"
:value-format="type?'yyyy-MM-dd HH:mm:ss':'yyyy-MM-dd'"
:default-time="['00:00:00','23:59:59']"
range-separator="~"
start-placeholder="开始日期"
end-placeholder="结束日期"
:clearable="noClearable?!noClearable:true"
@change="selectChange"
/>
</div>
</div>
</template>
<script>
export default {
name: 'SelectDate',
// noClearable 默认 clearable : true 特殊的关闭
props: ['label', 'width', 'isResize', 'defaultValue', 'pickerOptions', 'index', 'type', 'noClearable', 'disabled'],
data() {
return {
dateValue: []
}
},
watch: {
// 监听是否重置
isResize(newVal, oldVal) {
if (newVal) {
if (this.defaultValue) {
this.dateValue = this.defaultValue
} else {
this.dateValue = ''
}
}
},
defaultValue(newVal) {
if (newVal) {
this.dateValue = newVal
}
}
},
mounted() {
this.defaultValue ? this.dateValue = this.defaultValue : ''
},
methods: {
selectChange(value) {
console.log(value, 'value')
if (this.dateValue) {
this.$emit('result', { start_date: this.dateValue[0], end_date: this.dateValue[1], index: this.index || null })
} else {
this.$emit('result', { start_date: '', end_date: '', index: this.index || null })
}
}
}
}
</script>
<style lang="scss" scoped>
</style>
\ No newline at end of file
...@@ -21,17 +21,21 @@ import uploading from '@/utils/cos-upload' ...@@ -21,17 +21,21 @@ import uploading from '@/utils/cos-upload'
import 'element-ui/lib/theme-chalk/index.css'; import 'element-ui/lib/theme-chalk/index.css';
import errorHandle from '@/utils/errorHandle' import errorHandle from '@/utils/errorHandle'
import { getParams } from '@/utils/index' import { getParams } from '@/utils/index'
import globalComponent from '@/components/register.js'
Vue.use(globalComponent)
if(isTest()){ if(isTest()){
new VConsole(); new VConsole();
} }
function isTest(){ function isTest(){
return process.env.NODE_ENV !== 'production' return process.env.NODE_ENV !== 'production'
} }
// 开发环境不收集日志
if (process.env.NODE_ENV !== 'development') {
errorHandle.onload()
}
errorHandle.onload()
// // 开发环境不收集日志
// if (process.env.NODE_ENV !== 'development') {
// errorHandle.onload()
// }
// 测试一下 // 测试一下
Vue.use(uploading) Vue.use(uploading)
......
...@@ -69,7 +69,7 @@ const router = new VueRouter({ ...@@ -69,7 +69,7 @@ const router = new VueRouter({
用 hash 模式不用修改 nginx 配置 直接用就行了 用 hash 模式不用修改 nginx 配置 直接用就行了
如果用 history 需要在 vue.config.js 中配置 historyApiFallback: true, 解决404问题 如果用 history 需要在 vue.config.js 中配置 historyApiFallback: true, 解决404问题
*/ */
mode: 'history', mode: process.env.NODE_ENV === 'development' ? 'hash' : 'history',
base:process.env.NODE_ENV === 'development' ? '/' : '/company_app', base:process.env.NODE_ENV === 'development' ? '/' : '/company_app',
routes routes
}) })
......
...@@ -26,8 +26,7 @@ const state = { ...@@ -26,8 +26,7 @@ const state = {
corp_signature:'', corp_signature:'',
time:'' time:''
}, },
weixin_blongs_id_list:[], weixin_blongs_id_list:[]
external_userid:''
// 六子的 用户id wm5rUgMgAAjqjOcqp8i3lEhFZDQieWug // 六子的 用户id wm5rUgMgAAjqjOcqp8i3lEhFZDQieWug
// 我的 userid JinDuoXia cser_id 4090 corp_id wweaefe716636df3d1 cser_id 4090 token token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJpc3MiOjQwOTAsImlhdCI6MTc0NzgxMjMxMiwiZXhwIjoxNzQ4NDE3MTEyLCJuYmYiOjE3NDc4MTIzMTIsInN1YiI6InRva2Vu6K6k6K-BIiwianRpIjoiMjBkOTY3MDZiYzI1MDdmY2MxOWI2MjU1YTM0YWQ3M2YifQ.yX7E7QHV7x2ubpa8iK3Avy794EiHNCaW2CtB4A4UQWo // 我的 userid JinDuoXia cser_id 4090 corp_id wweaefe716636df3d1 cser_id 4090 token token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJpc3MiOjQwOTAsImlhdCI6MTc0NzgxMjMxMiwiZXhwIjoxNzQ4NDE3MTEyLCJuYmYiOjE3NDc4MTIzMTIsInN1YiI6InRva2Vu6K6k6K-BIiwianRpIjoiMjBkOTY3MDZiYzI1MDdmY2MxOWI2MjU1YTM0YWQ3M2YifQ.yX7E7QHV7x2ubpa8iK3Avy794EiHNCaW2CtB4A4UQWo
} }
......
...@@ -49,31 +49,31 @@ export default { ...@@ -49,31 +49,31 @@ export default {
}, 3000) }, 3000)
} }
// 由于errorHandler是全局配置的,因此window.onerror将会“失效”,即errorHandler能捕获的错误,onerror将不能捕获;errorHandler不能捕获的异常,onerror将捕获错误。如果errorCaptured函数返回为false,那么此error将不会传到errorHandler // 由于errorHandler是全局配置的,因此window.onerror将会“失效”,即errorHandler能捕获的错误,onerror将不能捕获;errorHandler不能捕获的异常,onerror将捕获错误。如果errorCaptured函数返回为false,那么此error将不会传到errorHandler
// window.onerror = (message, source, lineno, colno, error) => { window.onerror = (message, source, lineno, colno, error) => {
// // message: 错误信息 // message: 错误信息
// // source:发生错误的资源 // source:发生错误的资源
// // line:发生错误的行号 // line:发生错误的行号
// // column:发生错误的列数 // column:发生错误的列数
// // error:Error错误对象 // error:Error错误对象
// this.windowErrors.push({ type: 'windowError', content: { message, source, lineno, colno, error: error.stack || '无法捕获错误' }}) this.windowErrors.push({ type: 'windowError', content: { message, source, lineno, colno, error: error.stack || '无法捕获错误' }})
// if (this.time1 != null) { if (this.time1 != null) {
// clearTimeout(this.time1) clearTimeout(this.time1)
// } }
// this.time1 = setTimeout(() => { this.time1 = setTimeout(() => {
// if (this.windowErrors.length > 0) { if (this.windowErrors.length > 0) {
// const list = this.removeDp2(this.windowErrors) const list = this.removeDp2(this.windowErrors)
// console.log('window错误', list) console.log('window错误', list)
// this.sendError(list) this.sendError(list)
// this.windowErrors = [] this.windowErrors = []
// } }
// }, 3000) }, 3000)
// } }
}, },
initTrack() { initTrack() {
const opts = { const opts = {
host: 'cn-hangzhou.log.aliyuncs.com', host: 'cn-hangzhou.log.aliyuncs.com',
project: 'zwwl2022', project: 'company-wx-frontend',
logstore: 'frontend_log', logstore: 'company-wx-sidebar',
time: 3, // 发送日志的时间间隔,默认是10秒。 time: 3, // 发送日志的时间间隔,默认是10秒。
count: 100, // 发送日志的数量大小,默认是10条。 count: 100, // 发送日志的数量大小,默认是10条。
topic: '掌微侧边栏' // 自定义日志主题。 topic: '掌微侧边栏' // 自定义日志主题。
...@@ -82,6 +82,7 @@ export default { ...@@ -82,6 +82,7 @@ export default {
Vue.prototype.$tracker = this.tracker Vue.prototype.$tracker = this.tracker
}, },
sendError(data) { sendError(data) {
console.log('开始发送错误', data)
this.tracker.sendBatchLogs(data) this.tracker.sendBatchLogs(data)
} }
} }
......
<template>
<el-dialog :title="title" :visible="show" width="400" :append-to-body="true" class="giftDetailsDialog" @close="close">
<div class="content">
<div v-for="(item,index) in activeInfo" :key="index" class="item">
<div v-for="(items,indexs) in item.type_details.rule.level_attribute " :key="indexs" style="background:#F9FAFF;">
<!-- 角色累充 -->
<div v-if="item.gift_type==1 || item.gift_type==4 || item.gift_type==5" class="contentConfirm">
<div v-for="(prize,prizeIndex) in items.prize_default" :key="prizeIndex" class="contentConfirmItem rowFlex spaceBetween">
<p class="info"> {{ prize.name }}</p>
</div>
</div>
<!-- 时间段充值 和 单日累充 -->
<div v-else-if="items.apply_num > 0 && (item.gift_type==2 || item.gift_type==3)" class="contentConfirm">
<div v-if=" item.gift_type==2 || item.gift_type==3">
<div v-if="items.prize_default && items.prize_default.length>0">
<div class="contentConfirmItem">
<!-- 标题 -->
<div class="title rowFlex spaceBetween">
<span>{{ items.prize_level_name }}</span>
<!-- 积分开 -->
<div v-if="item.gift_type == 3 && item.type_details.rule.exchange_score_status==1">{{ items.compare_amount ? items.compare_amount + '积分' : items.compare_amount }}<span> * {{ items.apply_num }}</span></div>
<!-- 积分关 -->
<div v-else-if="item.gift_type == 3 && item.type_details.rule.exchange_score_status==2">{{ items.compare_amount ? items.compare_amount + '金额' : items.compare_amount }}<span> * {{ items.apply_num }}</span></div>
<div v-else-if="item.gift_type == 2 ">{{ items.compare_amount ? items.compare_amount + '金额' : items.compare_amount }}<span> * {{ items.apply_num }}</span></div>
</div>
<p class="title">固定奖 <span v-if="item.gift_type==3 && item.type_details.rule.exchange_score_status==1">{{ items.apply_num ? '*' + items.apply_num : '' }}</span> </p>
<div v-for="(prize,prizeIndex) in items.prize_default" :key="prizeIndex" class="contentConfirmItem rowFlex spaceBetween prizeStyle">
<p class="info"> {{ prize.name }}</p>
</div>
</div>
</div>
</div>
<div class="contentConfirmItem">
<div v-if="items.prize_auto.length>0 && ( !items.prize_default|| items.prize_default.length==0)" class="title rowFlex spaceBetween">
<span>{{ items.prize_level_name }}</span>
<div v-if="item.gift_type == 3 & item.type_details.rule.exchange_score_status==1">{{ items.compare_amount ? items.compare_amount + '积分' : items.compare_amount }}<span> * {{ items.apply_num }}</span></div>
<!-- 积分关 -->
<div v-if="item.gift_type == 3 & item.type_details.rule.exchange_score_status==2">{{ items.compare_amount ? items.compare_amount + '金额' : items.compare_amount }}<span> * {{ items.apply_num }}</span></div>
</div>
<p v-if="items.prize_auto.length>0" class="title">自选奖 ({{ items.prize_auto.length }}{{ items.prize_auto_num }}) <span v-if="item.gift_type==3 && item.type_details.rule.exchange_score_status==1">* {{ items.apply_num ? items.apply_num : 0 * items.prize_auto_num }}</span> </p>
<div v-for="(prize,prizeIndex) in items.prize_auto" :key="prizeIndex" class="contentConfirmItem prizeStyle">
<div v-for="(auto,autoIndex) in prize.group" :key="autoIndex">
<div v-if="prize.apply_num > 0" class="rowFlex spaceBetween">
<span>{{ auto.name }}</span>
<div>*{{ prize.apply_num }}</div>
</div>
</div>
</div>
</div>
<div v-if="item.gift_type == 3 && item.exchange_score_status==1 " class="expendIcon">消耗:{{ items.compare_amount * items.apply_num }} 积分</div>
</div>
</div>
</div>
</div>
<!-- 活动列表 -->
<span class="dialog-footer rowFlex">
<el-button class="btn" type="primary" :loading="loading" @click="submit">确 定</el-button>
<el-button class="btn" @click="close">取 消</el-button>
</span>
</el-dialog>
</template>
<script type="text/javascript">
import { giftBagApply } from '@/api/game'
import { mapState } from 'vuex'
export default {
// type 3:image 4:video
props: ['show', 'width', 'title', 'activeInfo', 'remark'],
data() {
return {
loading: false
}
},
computed: {
...mapState('user', ['cser_name'])
},
watch: {
show(newVal, oldVal) {
}
},
mounted() {},
methods: {
close() {
this.$emit('update:show', false)
},
submit() {
this.loading = true
const role_id = this.activeInfo[0].role_info.value
const rule = this.activeInfo.map(item => {
let level_attribute = []
if (item.type_details.rule.gift_type == 1) {
level_attribute = item.type_details.rule.level_attribute
} else {
level_attribute = item.type_details.rule.level_attribute.filter(item => item.apply_num > 0)
}
return { level_attribute: level_attribute, id: item.id }
})
const data = {
role_id,
remark: this.remark,
recharge_date: this.activeInfo[0].recharge_date || '',
create_user: this.cser_name,
rule: rule
}
giftBagApply(data).then(res => {
this.loading = false
if (res.status_code === 1) {
this.$message.success(res.msg)
this.close()
this.$emit('close')
} else {
this.close()
}
}, err => {
this.loading = false
})
}
}
}
</script>
<style lang="scss" scoped>
.content{
padding-bottom: 40px;
}
.contentConfirm{
padding:10px 20px;
background: #F9FAFF;
margin-bottom: 20px;
.prizeStyle{
margin-top: 10px;
margin-bottom: 10px;
}
.contentConfirmItem{
width: 100%;
height: auto;
background: #F9FAFF;
.title{
font-size: 14px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 600;
color: #333333;
line-height: 20px;
}
.info{
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #666666;
}
}
}
.expendIcon{
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #666666;
text-align: center;
margin-top:20px;
}
.dialog-footer {
width: calc(100% - 20px);
height: 52px;
position: absolute;
right: 20px;
bottom: 20px;
padding-top: 20px;
border-top: 1px solid rgba(0, 0, 0, 0.06);
justify-content: flex-end;
.btn {
width: 84px;
height: 32px;
}
}
.allIcon{
width: 137px;
height: 20px;
background: #F2AC51;
border-radius: 13px;
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: 80px;
}
.content {
width: 100%;
height: auto;
}
</style>
\ No newline at end of file
<template>
<!-- 角色累充 -->
<el-drawer :lock-scroll="true" :title="title" :visible="show" size="540px" :modal="false" :modal-append-to-body="false" class="giftDetails" @close="close">
<div class="content">
<div v-for="(item,index) in activeInfo" :key="index" class="list">
<div class="giftDetailsText">
<div class="activeItem rowFlex">
<div class="activeLabel">活动名称</div>
<div class="activeValue">{{ item.title_name }}</div>
</div>
<div class="activeItem rowFlex">
<div class="activeLabel">活动类型</div>
<div class="activeValue">{{ item.gift_type_text }}</div>
</div>
<div class="activeItem rowFlex">
<div class="activeLabel">活动详情</div>
<div class="activeValue">{{ item.describe }}</div>
</div>
<div v-if="item.start_date && item.end_date" class="activeItem rowFlex">
<div class="activeLabel">活动时间</div>
<div class="activeValue">{{ item.start_date + '至' + item.end_date }}</div>
</div>
<div class="activeItem rowFlex">
<div class="activeValue">{{ item.payment_method_text }}</div>
</div>
<div v-if="item.type_details.total_recharge" class="activeItem rowFlex">
<div class="activeLabel">充值金额</div>
<div class="activeValue">{{ item.type_details.total_recharge }}</div>
</div>
<div class="activeItem rowFlex">
<div class="activeLabel">申请角色</div>
<div class="activeValue">{{ item.role_info.label || '' }}</div>
</div>
<!-- 充值积分才有 -->
</div>
<!-- 角色累充 level_attribute 档位 每个档位下面有 固定奖 和 自选奖 -->
<div v-for="(items,indexs) in item.type_details.rule.level_attribute" :key="indexs" class="activeList">
<div v-for="(k,j) in items.prize_default" :key="j" class="level_attribute_item">
<div class="activeListItemContent rowFlex">
<div class="rowFlex spaceBetween">
<div class="title">ID:{{ k.prize_id }} </div>
<div class="handle" style="margin-left:50px;">{{ k.name }}</div>
</div>
</div>
</div>
</div>
</div>
<div class="activeItem rowFlex" style="margin-top:20px;">
<div class="activeLabel" style="text-align:right;">备注</div>
<div class="activeValue">
<el-input v-model="remark" type="textarea" maxlength="150" style="width:90%;" placeholder="请输入备注"></el-input>
</div>
</div>
<span class="dialog-footer rowFlex">
<el-button class="btn" :disabled="requestLoading" type="primary" :loading='btnLoading' @click="submit">确 定</el-button>
<el-button class="btn" @click="close">取 消</el-button>
</span>
<!-- 确认弹窗 -->
<confirmLayer :is-submit="isSubmit" :remark="remark" :active-info="activeInfo" :show.sync="showConfirmLayer" title="请核对申请奖品信息" @close="close" />
</div>
</el-drawer>
</template>
<script type="text/javascript">
import { giftBagApply } from '@/api/game'
import confirmLayer from '../confirmLayer'
import { mapState } from 'vuex'
export default {
// type 3:image 4:video
components: {
confirmLayer
},
props: ['show', 'width', 'title', 'info', 'body', 'giftInfo', 'activeInfo','requestLoading'],
data() {
return {
isSubmit: false,
btnLoading:false,
remark: '',
loading: false,
showConfirmLayer: false
}
},
computed: {
...mapState('user', ['cser_name'])
},
watch: {
show(newVal, oldVal) {
if (newVal) {
// this.ruleForm = this.activeInfo
// this.recharge_date = this.activeInfo.start_date
}
}
},
mounted() {},
methods: {
close() {
this.$emit('update:show', false)
},
dateChange() {
},
handleChange() {
},
submit() {
this.btnLoading = true
const role_id = this.activeInfo[0].role_info.value
const rule = this.activeInfo.map(item => {
let level_attribute = []
if (item.type_details.rule.gift_type == 1 || item.type_details.rule.gift_type == 4 || item.type_details.rule.gift_type == 5) {
level_attribute = item.type_details.rule.level_attribute
} else {
level_attribute = item.type_details.rule.level_attribute.filter(item => item.apply_num > 0)
}
return { level_attribute: level_attribute, id: item.id }
})
this.loading = true
const data = {
role_id,
remark: this.remark,
recharge_date: this.activeInfo[0].recharge_date || '',
create_user: this.cser_name,
rule: rule
}
giftBagApply(data).then(res => {
this.loading = false
this.btnLoading =false
if (res.status_code === 1) {
this.$message.success(res.msg)
this.close()
this.$emit('close')
} else {
this.close()
}
}, err => {
this.loading = false
this.btnLoading =false
})
}
}
}
</script>
<style lang="scss" scoped>
.giftDetails {
position: fixed;
right: 450px;
top: 0;
box-shadow: 0px 9px 28px 0px rgba(0, 0, 0, 0.05);
.icon{
font-size:14px;
cursor: pointer;
margin-left: 10px;
}
.content {
padding: 0 20px;
width: 100%;
height: calc(100% - 100px);
overflow: auto;
.list{
border-bottom: 1px solid #E8E8E8;
padding: 20px 0;
}
.activeItem {
width: 100%;
height: auto;
margin-bottom: 10px;
.activeLabel {
width: 60px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999999;
line-height: 20px;
margin-right: 10px;
}
.activeValue {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
line-height: 20px;
text-align: left;
display: flex;
flex: 1;
}
}
.activeList{
width: 100%;
height:auto;
.activeListItem{
width: 100%;
height: auto;
background: #F9FAFF;
border-radius: 5px;
padding: 10px;
margin-top: 20px;
.title{
font-size: 14px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 600;
color: #333333;
line-height: 20px;
max-width: 50%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.handle{
p{
font-size: 14px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 600;
color: #333333;
margin-right: 10px;
}
}
.inputNumber{
width: 130px;
}
}
.activeListItemTitle,.contentItem{
line-height: 30px;
}
.activeListItemContent{
width: 100%;
height: auto;
.title{
font-size: 14px;
font-family: PingFangSC-Medium, PingFang SC;
color: #333333;
}
.infoText{
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #666666;
margin-top: 5px;
}
.expendIcon{
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #666666;
text-align: center;
margin-top:20px;
}
}
}
}
}
.allIcon{
width: 137px;
height: 20px;
background: #F2AC51;
border-radius: 13px;
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: 80px;
}
.remark{
margin-top:20px;
}
</style>
<template>
<div v-loading="loading" class="wx-gift-container">
<div ref="giftList" class="gift-list" @scroll="handleScroll">
<div v-for="item in giftList" :key="item._id" class="gift-item">
<div class="gift-info">
<div class="rowFlex spaceBetween columnCenter">
<div class="gift-name hidden">{{ item.gift_package_name }}</div>
<div class="gift-time">{{ item.send_time }}</div>
</div>
<div class="gift-code">
<span class="giftCodeText">{{ item.code }}</span>
</div>
<div class="rowFlex spaceBetween columnCenter gift-sender">
<div>发送客服:{{ item.cser_name }}</div>
<i class="el-icon-document-copy" style="cursor: pointer;" @click="handleCopy(item.code)"></i>
</div>
</div>
</div>
<div v-if="loading" class="loading-more">加载中...</div>
<div v-if="!hasMore && giftList.length > 0" class="no-more">没有更多数据了</div>
<div v-if="giftList.length == 0" class="noContent rowFlex allCenter">
<noContent/>
</div>
</div>
</div>
</template>
<script>
import Clipboard from 'clipboard'
import { getSendingCodeList } from '@/api/works'
import { debounce,copyText } from '@/utils/index'
import { mapState } from 'vuex'
export default {
name: 'WxGift',
data() {
return {
loading: false,
giftList: [],
page: 1,
pageSize: 20,
hasMore: true
}
},
computed: {
...mapState('game', ['chatUserInfo'])
},
created() {
console.log(this.chatUserInfo, 'chatUserInfo')
this.fetchGiftList()
},
methods: {
async fetchGiftList() {
if (this.loading || !this.hasMore) return
this.loading = true
try {
const params = {
page: this.page,
page_size: this.pageSize,
corp_id: this.chatUserInfo.corp_id,
userid: this.chatUserInfo.userid || this.chatUserInfo.user.userid,
external_userid: this.chatUserInfo.external_userid || this.chatUserInfo.external_user.external_userid
}
const res = await getSendingCodeList(params)
if (res.data && res.data.data) {
this.giftList = this.page === 1 ? res.data.data : [...this.giftList, ...res.data.data]
this.hasMore = res.data.data.length === this.pageSize
this.page++
}
} catch (error) {
console.error('获取礼包列表失败:', error)
} finally {
this.loading = false
}
},
handleScroll: debounce(function(e) {
const { scrollHeight, scrollTop, clientHeight } = e.target
if (scrollHeight - scrollTop - clientHeight < 50) {
this.fetchGiftList()
}
}, 500),
handleCopy(code) {
copyText('giftCodeText', this)
// const clipboard = new Clipboard('.')
// clipboard.on('success', e => {
// this.$message.success('复制成功')
// // 释放内存
// clipboard.destroy()
// })
}
}
}
</script>
<style lang="scss" scoped>
.wx-gift-container {
height: calc(100vh - 160px);
width: 100%;
background-color: #fff;
.gift-list {
height: 100%;
overflow-y: auto;
padding: 10px;
.gift-item {
padding: 16px;
background: #F7F8FA;
border-radius: 12px;
border: 1px solid #E5E6EB;
margin-bottom:12px;
.gift-info {
.gift-name {
font-weight: 400;
font-size: 14px;
color: #4E5969;
text-align: left;
font-style: normal;
width: calc(100% - 180px);
}
.gift-time {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 14px;
color: #4E5969;
text-align: left;
font-style: normal;
width: 150px;
}
.gift-code {
display: flex;
align-items: center;
justify-content: space-between;
border-radius: 4px;
font-family: PingFangSC, PingFang SC;
font-weight: 500;
font-size: 14px;
color: #323335;
text-align: justify;
font-style: normal;
margin: 10px 0;
span {
color: #323335;
font-size: 14px;
font-family: PingFangSC-Medium;
}
.el-button {
padding: 5px 12px;
border: 1px solid #dcdfe6;
border-radius: 4px;
font-size: 13px;
color: #606266;
&:hover {
color: #409eff;
border-color: #c6e2ff;
background-color: #ecf5ff;
}
}
}
.gift-sender {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 12px;
color: #4E5969;
line-height: 18px;
text-align: justify;
font-style: normal;
i{
color: #00BF8A;
font-size: 14px;
}
}
}
}
.loading-more,
.no-more,
.empty-data {
text-align: center;
padding: 16px;
color: #999999;
font-size: 13px;
}
}
}
</style>
\ No newline at end of file
<template> <template>
<div class="giftRecord-content"> <div class="gift-tab-container-apply-gift">
礼包记录 <el-tabs v-model="activeTab">
<el-tab-pane label="充值礼包" name="email">
<email-gift></email-gift>
</el-tab-pane>
<el-tab-pane label="企微礼包" name="wx">
<wx-gift></wx-gift>
</el-tab-pane>
</el-tabs>
</div> </div>
</template> </template>
<script> <script>
import EmailGift from './components/giftRecord/emailGift.vue'
import WxGift from './components/giftRecord/wxGift.vue'
export default { export default {
name: 'GiftRecord', name: 'GiftTab',
components: {
EmailGift,
WxGift
},
data() {
return {
activeTab: 'email'
}
}
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.giftRecord-content{ .gift-tab-container-apply-gift {
width: 100%; width: 100%;
height: 100%; height: 100%;
padding-top: 10px;
background: #fff; background: #fff;
::v-deep .el-tabs .el-tabs__header{
margin: 0;
// height: 60px;
}
} }
</style> </style>
\ No newline at end of file
<template> <template>
<div class="quickReply-content"> <div class="details columnFlex">
快捷回复 <div class="content search-form">
<el-tabs v-model="activeName">
<el-tab-pane
label="个人话术"
name="personal"
>
<skillPersonal
v-if="activeName === 'personal'"
:active-name="activeName"
/>
</el-tab-pane>
<el-tab-pane
label="企业话术"
name="company"
>
<skillCompany
:active-name="activeName"
/>
</el-tab-pane>
<el-tab-pane
label="知识库"
name="library"
>
<skillLibrary
v-if="activeName === 'library'"
:active-name="activeName"
/>
</el-tab-pane>
<!-- <el-tab-pane
v-if="workerRouter==='game' && messageSource === 'company_work'"
label="AI微言"
name="aiLibrary"
>
<template slot="label">
AI微言
<span class="bate">beta</span>
</template>
<aiLibrary
v-if="activeName === 'aiLibrary'"
:active-name="activeName"
/>
</el-tab-pane> -->
</el-tabs>
</div>
</div> </div>
</template> </template>
<script> <script>
import skillCompany from './components/skill/skillCompany.vue'
import skillPersonal from './components/skill/skillPersonal.vue'
import skillLibrary from './components/skill/skillLibrary.vue'
// import aiLibrary from './components/skill/aiLibrary.vue'
import { mapState, mapMutations, mapActions } from 'vuex'
export default { export default {
name: 'QuickReply', components: {
skillCompany,
skillPersonal,
skillLibrary,
// aiLibrary
},
props: {
messageSource: {
type: String,
default: ''
}
},
data() {
return {
activeName: 'personal'
}
},
created() { },
mounted() { },
methods: {}
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.quickReply-content{ .details {
::v-deep .el-tabs__nav-next,::v-deep .el-tabs__nav-prev{
line-height: 50px;
}
width: 100%; width: 100%;
height: 100%; height: 100%;
background: #fff; background: #fff;
::v-deep .el-tabs__item {
padding: 0 15px;
}
.detailsTitle {
width: 100%;
padding: 0 vw(20);
height: 60px;
font-size: 18px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
border-bottom: 1px solid #ebeef5;
border-left: 1px solid #ebeef5;
p {
color: #333333;
}
}
.content {
width: 100%;
height: calc(100% - 10px);
::v-deep .el-tabs__header {
margin: 0 0 20px;
}
}
::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-tabs--border-card .is-active {
border: none !important;
}
::v-deep .el-collapse-item__header {
width: 100%;
height: 44px;
background: #f9faff;
color: #333333;
padding-left: 35px;
font-size: 14px;
font-weight: 400;
// cursor: move;
}
::v-deep .is-active {
border: none;
}
.inputContent {
width: 100%;
::v-deep .el-input {
width: 80%;
}
}
::v-deep .el-tabs,
.el-tabs__content,
.el-tab-pane {
width: 100%;
height: 100%;
}
::v-deep .el-tabs__content {
width: 100%;
height: calc(100% - 50px);
}
::v-deep .el-tab-pane {
width: 100%;
height: 100%;
}
.scrollList {
width: 100%;
height: calc(100% - 40px);
overflow: auto;
}
.draggable {
position: relative;
transition: all 0.3s;
.icon {
position: absolute;
left: 10px;
top: 15px;
z-index: 10;
}
}
::v-deep .el-icon-circle-close {
color: #fff;
}
.bate {
width: 42px;
height: 20px;
background: linear-gradient(135deg, #6ee7e9 0%, #9ff2cd 47%, #e3fdb2 100%);
border-radius: 10px;
padding: 0px 10px 3px 10px;
}
} }
</style> </style>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论