添加开屏广告管理 #123
@ -136,7 +136,7 @@
|
|||||||
<div class="app-loading">
|
<div class="app-loading">
|
||||||
<div class="app-loading-wrap">
|
<div class="app-loading-wrap">
|
||||||
<div class="app-loading-title">
|
<div class="app-loading-title">
|
||||||
<img src="/logo.gif" class="app-loading-logo" alt="Logo" />
|
<!-- <img src="/logo.gif" class="app-loading-logo" alt="Logo" />-->
|
||||||
<div class="app-loading-title">%VITE_APP_TITLE%</div>
|
<div class="app-loading-title">%VITE_APP_TITLE%</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="app-loading-item">
|
<div class="app-loading-item">
|
||||||
|
50
yudao-admin-vue3/src/api/mall/promotion/advertising/index.ts
Normal file
50
yudao-admin-vue3/src/api/mall/promotion/advertising/index.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
// 开屏广告 VO
|
||||||
|
export interface AdvertisingVO {
|
||||||
|
id: number // id
|
||||||
|
status: number // 广告状态
|
||||||
|
time: number // 广告时间(秒)
|
||||||
|
property: string // 广告属性
|
||||||
|
picData: []
|
||||||
|
stat: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开屏广告 API
|
||||||
|
export const AdvertisingApi = {
|
||||||
|
// 查询开屏广告分页
|
||||||
|
getAdvertisingPage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/promotion/advertising/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 查询开屏广告详情
|
||||||
|
getAdvertising: async () => {
|
||||||
|
return await request.get({ url: `/promotion/advertising/getAdvertising`})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增开屏广告
|
||||||
|
createAdvertising: async (data: AdvertisingVO) => {
|
||||||
|
return await request.post({ url: `/promotion/advertising/create`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改开屏广告
|
||||||
|
updateAdvertising: async (data: AdvertisingVO) => {
|
||||||
|
return await request.put({ url: `/promotion/advertising/update`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除开屏广告
|
||||||
|
deleteAdvertising: async (id: number) => {
|
||||||
|
return await request.delete({ url: `/promotion/advertising/delete?id=` + id })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出开屏广告 Excel
|
||||||
|
exportAdvertising: async (params) => {
|
||||||
|
return await request.download({ url: `/promotion/advertising/export-excel`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 新增修稿开屏广告
|
||||||
|
saveAdvertising: async (data: AdvertisingVO) => {
|
||||||
|
return await request.post({ url: `/promotion/advertising/saveAdvertising`, data })
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
@ -3,7 +3,7 @@ import request from '@/config/axios'
|
|||||||
// 客服配置 VO
|
// 客服配置 VO
|
||||||
export interface ConfigurationVO {
|
export interface ConfigurationVO {
|
||||||
id: number // id
|
id: number // id
|
||||||
type: string // 客服类型
|
type: number // 客服类型
|
||||||
feedback: string // 客服反馈
|
feedback: string // 客服反馈
|
||||||
phone: string // 客服电话
|
phone: string // 客服电话
|
||||||
link: string // 客服链接
|
link: string // 客服链接
|
||||||
|
@ -23,8 +23,8 @@ export const KeFuConversationApi = {
|
|||||||
return await request.get({ url: '/promotion/kefu-conversation/list' })
|
return await request.get({ url: '/promotion/kefu-conversation/list' })
|
||||||
},
|
},
|
||||||
// 获得客服会话列表
|
// 获得客服会话列表
|
||||||
getConversationListByKefuId: async (kefuId: number) => {
|
getConversationListByKefuId: async (kefuId: number , name: string) => {
|
||||||
return await request.get({ url: '/promotion/kefu-conversation/list?kefuId=' + kefuId })
|
return await request.get({ url: '/promotion/kefu-conversation/list?kefuId=' + kefuId + `&name=` + name })
|
||||||
},
|
},
|
||||||
// 客服会话置顶
|
// 客服会话置顶
|
||||||
updateConversationPinned: async (data: any) => {
|
updateConversationPinned: async (data: any) => {
|
||||||
|
@ -32,5 +32,10 @@ export const KeFuMessageApi = {
|
|||||||
// 获得消息分页数据
|
// 获得消息分页数据
|
||||||
getKeFuMessagePage: async (params: any) => {
|
getKeFuMessagePage: async (params: any) => {
|
||||||
return await request.get({ url: '/promotion/kefu-message/page', params })
|
return await request.get({ url: '/promotion/kefu-message/page', params })
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获得消息分页数据
|
||||||
|
getBySenderIdStat: async (senderId: number) => {
|
||||||
|
return await request.get({ url: '/promotion/kefu-message/getBySenderIdStat?senderId=' + senderId })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
yudao-admin-vue3/src/assets/imgs/quxiao.png
Normal file
BIN
yudao-admin-vue3/src/assets/imgs/quxiao.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.0 KiB |
@ -120,7 +120,8 @@
|
|||||||
<IFrame class="w-375px border-4px border-rounded-8px border-solid p-2px h-667px!" :src="previewUrl" />
|
<IFrame class="w-375px border-4px border-rounded-8px border-solid p-2px h-667px!" :src="previewUrl" />
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<el-text>手机扫码预览</el-text>
|
<el-text>手机扫码预览</el-text>
|
||||||
<Qrcode :text="previewUrl" logo="/logo.gif" />
|
<Qrcode :text="previewUrl" />
|
||||||
|
<!-- <Qrcode :text="previewUrl" logo="/logo.gif" />-->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
@ -124,6 +124,9 @@ export enum DICT_TYPE {
|
|||||||
TECHNICIAN_STATUS = 'technician_status',
|
TECHNICIAN_STATUS = 'technician_status',
|
||||||
SEX = 'sex',
|
SEX = 'sex',
|
||||||
|
|
||||||
|
//客服配置类型
|
||||||
|
KEFU_CONFIGURATION_TYPE = 'kefu_configuration_type',
|
||||||
|
|
||||||
INFRA_FILE_TYPE = 'infra_file_type',
|
INFRA_FILE_TYPE = 'infra_file_type',
|
||||||
|
|
||||||
PAY_WALLET_RECHARGE_PAY_STATUS = 'pay_wallet_recharge_pay_status',
|
PAY_WALLET_RECHARGE_PAY_STATUS = 'pay_wallet_recharge_pay_status',
|
||||||
|
@ -60,11 +60,11 @@
|
|||||||
<Icon icon="ep:upload" class="mr-5px"/>
|
<Icon icon="ep:upload" class="mr-5px"/>
|
||||||
上传文件
|
上传文件
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<img @click="liebiao" style="cursor: pointer;margin-left: 240px;" class="mr-10px h-27px w-27px"
|
||||||
|
src="@/assets/imgs/liebiao.png"/>
|
||||||
|
<img @click="tubiao" style="cursor: pointer;" class="mr-10px h-27px w-27px"
|
||||||
|
src="@/assets/imgs/tubiao.png"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<span><img @click="liebiao" style="cursor: pointer;" class="mr-10px h-30px w-30px"
|
|
||||||
src="@/assets/imgs/liebiao.png"/></span>
|
|
||||||
<span><img @click="tubiao" style="cursor: pointer;" class="mr-10px h-30px w-30px"
|
|
||||||
src="@/assets/imgs/tubiao.png"/></span>
|
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -0,0 +1,118 @@
|
|||||||
|
<template>
|
||||||
|
<Dialog :title="dialogTitle" v-model="dialogVisible">
|
||||||
|
<el-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="formData"
|
||||||
|
:rules="formRules"
|
||||||
|
label-width="100px"
|
||||||
|
v-loading="formLoading"
|
||||||
|
>
|
||||||
|
<el-form-item label="广告状态" prop="status">
|
||||||
|
<el-radio-group v-model="formData.status">
|
||||||
|
<el-radio
|
||||||
|
v-for="dict in getIntDictOptions(DICT_TYPE.PROMOTION_DIY_ADVERTISING)"
|
||||||
|
:key="dict.value"
|
||||||
|
:label="dict.value"
|
||||||
|
>
|
||||||
|
{{ dict.label }}
|
||||||
|
</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="广告时间(秒)" prop="time">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="formData.time"
|
||||||
|
type="date"
|
||||||
|
value-format="x"
|
||||||
|
placeholder="选择广告时间(秒)"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="广告属性" prop="property">
|
||||||
|
<el-input v-model="formData.property" placeholder="请输入广告属性" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
|
||||||
|
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||||
|
</template>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||||
|
import { AdvertisingApi, AdvertisingVO } from '@/api/mall/promotion/advertising'
|
||||||
|
|
||||||
|
/** 开屏广告 表单 */
|
||||||
|
defineOptions({ name: 'AdvertisingForm' })
|
||||||
|
|
||||||
|
const { t } = useI18n() // 国际化
|
||||||
|
const message = useMessage() // 消息弹窗
|
||||||
|
|
||||||
|
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||||
|
const dialogTitle = ref('') // 弹窗的标题
|
||||||
|
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||||
|
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||||
|
const formData = ref({
|
||||||
|
id: undefined,
|
||||||
|
status: undefined,
|
||||||
|
time: undefined,
|
||||||
|
property: undefined
|
||||||
|
})
|
||||||
|
const formRules = reactive({
|
||||||
|
status: [{ required: true, message: '广告状态不能为空', trigger: 'blur' }],
|
||||||
|
time: [{ required: true, message: '广告时间(秒)不能为空', trigger: 'blur' }],
|
||||||
|
property: [{ required: true, message: '广告属性不能为空', trigger: 'blur' }]
|
||||||
|
})
|
||||||
|
const formRef = ref() // 表单 Ref
|
||||||
|
|
||||||
|
/** 打开弹窗 */
|
||||||
|
const open = async (type: string, id?: number) => {
|
||||||
|
dialogVisible.value = true
|
||||||
|
dialogTitle.value = t('action.' + type)
|
||||||
|
formType.value = type
|
||||||
|
resetForm()
|
||||||
|
// 修改时,设置数据
|
||||||
|
if (id) {
|
||||||
|
formLoading.value = true
|
||||||
|
try {
|
||||||
|
formData.value = await AdvertisingApi.getAdvertising(id)
|
||||||
|
} finally {
|
||||||
|
formLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||||
|
|
||||||
|
/** 提交表单 */
|
||||||
|
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||||
|
const submitForm = async () => {
|
||||||
|
// 校验表单
|
||||||
|
await formRef.value.validate()
|
||||||
|
// 提交请求
|
||||||
|
formLoading.value = true
|
||||||
|
try {
|
||||||
|
const data = formData.value as unknown as AdvertisingVO
|
||||||
|
if (formType.value === 'create') {
|
||||||
|
await AdvertisingApi.createAdvertising(data)
|
||||||
|
message.success(t('common.createSuccess'))
|
||||||
|
} else {
|
||||||
|
await AdvertisingApi.updateAdvertising(data)
|
||||||
|
message.success(t('common.updateSuccess'))
|
||||||
|
}
|
||||||
|
dialogVisible.value = false
|
||||||
|
// 发送操作成功的事件
|
||||||
|
emit('success')
|
||||||
|
} finally {
|
||||||
|
formLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置表单 */
|
||||||
|
const resetForm = () => {
|
||||||
|
formData.value = {
|
||||||
|
id: undefined,
|
||||||
|
status: undefined,
|
||||||
|
time: undefined,
|
||||||
|
property: undefined
|
||||||
|
}
|
||||||
|
formRef.value?.resetFields()
|
||||||
|
}
|
||||||
|
</script>
|
228
yudao-admin-vue3/src/views/mall/promotion/advertising/index.vue
Normal file
228
yudao-admin-vue3/src/views/mall/promotion/advertising/index.vue
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
<template>
|
||||||
|
<ContentWrap>
|
||||||
|
<span>数据配置</span>
|
||||||
|
<el-button type="primary" @click="baocun" style="margin-left:85%">保存</el-button>
|
||||||
|
</ContentWrap>
|
||||||
|
|
||||||
|
<ContentWrap>
|
||||||
|
<div class="container">
|
||||||
|
<div class="left">
|
||||||
|
|
||||||
|
<img :src="image" style="width: 100%;height: 100%;border-radius: 10px;" v-show="check == 1" />
|
||||||
|
|
||||||
|
<span v-show="check == 2" style="margin-left:80px">暂无图片,请添加~</span>
|
||||||
|
</div>
|
||||||
|
<div class="right">
|
||||||
|
<div>
|
||||||
|
<p style="font-weight: 700;">引导页设置</p>
|
||||||
|
<span>开屏广告:</span><span> <el-switch v-model="formData.stat" size="large" /> </span>
|
||||||
|
<br />
|
||||||
|
<span>广告时间:</span><span> <el-input v-model="formData.time" style="width: 240px"
|
||||||
|
placeholder="请输入秒" /></span><span> 单位(秒)</span>
|
||||||
|
<br />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<div v-for="(item, index) in timeRanges" :key="index" class="rectangle-container">
|
||||||
|
<div class="imageLeft">
|
||||||
|
<UploadImg width="100px" height="100px" v-model="item.pic" />
|
||||||
|
</div>
|
||||||
|
<div class="inputRight">
|
||||||
|
<div style="margin-top: 20%;">
|
||||||
|
<span>图片名称:</span>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<div>
|
||||||
|
<span>链接地址:</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<el-input style="width: 200px;margin-top: 3%;" type="text" v-model="item.name"
|
||||||
|
placeholder="请输入名称" />
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<div>
|
||||||
|
<AppLinkInput v-model="item.url" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img @click="removePic(index)"
|
||||||
|
style="width: 25px;height: 25px;position: absolute;top: 1px;right: 1px;cursor: pointer;"
|
||||||
|
src="@/assets/imgs/quxiao.png" />
|
||||||
|
<br />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<el-button type="primary" @click="addNewPic">添加图片</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ContentWrap>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { AdvertisingApi, AdvertisingVO } from '@/api/mall/promotion/advertising'
|
||||||
|
|
||||||
|
|
||||||
|
/** 开屏广告 列表 */
|
||||||
|
defineOptions({ name: 'Advertising' })
|
||||||
|
|
||||||
|
const message = useMessage() // 消息弹窗
|
||||||
|
const { t } = useI18n() // 国际化
|
||||||
|
|
||||||
|
const formData = ref({
|
||||||
|
id: undefined,
|
||||||
|
status: undefined,
|
||||||
|
stat: false,
|
||||||
|
time: undefined,
|
||||||
|
property: undefined,
|
||||||
|
picData: [{ pic: '', name: '', url: '' }]
|
||||||
|
})
|
||||||
|
|
||||||
|
const image = ref('')
|
||||||
|
const check = ref(2)
|
||||||
|
|
||||||
|
const timeRanges = ref([{ pic: '', name: '', url: '' }]);
|
||||||
|
//添加
|
||||||
|
const addNewPic = () => {
|
||||||
|
if (timeRanges.value.length <= 5) {
|
||||||
|
timeRanges.value.push({ pic: '', name: '', url: '' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//移出
|
||||||
|
const removePic = (index : number) => {
|
||||||
|
if (timeRanges.value.length >= 1) {
|
||||||
|
timeRanges.value.splice(index, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//提交保存
|
||||||
|
const baocun = async () => {
|
||||||
|
|
||||||
|
formData.value.picData = timeRanges.value
|
||||||
|
const data = formData.value as unknown as AdvertisingVO
|
||||||
|
await AdvertisingApi.saveAdvertising(data)
|
||||||
|
getAdvertising()
|
||||||
|
message.success('保存成功')
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** 查询开屏广告数据配置 */
|
||||||
|
const getAdvertising = async () => {
|
||||||
|
|
||||||
|
formData.value = await AdvertisingApi.getAdvertising()
|
||||||
|
|
||||||
|
if (formData.value.id == null) {
|
||||||
|
console.log('11111:', formData.value)
|
||||||
|
} else {
|
||||||
|
console.log('22222:', formData.value)
|
||||||
|
check.value = 1
|
||||||
|
timeRanges.value = formData.value.picData
|
||||||
|
if (formData.value.picData && formData.value.picData.length > 0) {
|
||||||
|
image.value = formData.value.picData[0].pic
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// if(formData.value.picData.length < 1){
|
||||||
|
// timeRanges.value = [{ pic: '', name: '', url: '' }]
|
||||||
|
// }
|
||||||
|
// if(formData.value.picData.length > 0){
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** 初始化 **/
|
||||||
|
onMounted(() => {
|
||||||
|
getAdvertising()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
/* justify-content: space-between; /* 左右分布 */
|
||||||
|
width: 1000px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.left {
|
||||||
|
margin-left: 20px;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
width: 300px;
|
||||||
|
height: 550px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right {
|
||||||
|
margin-left: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传图片
|
||||||
|
*/
|
||||||
|
.rectangle-container {
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 8px;
|
||||||
|
position: relative;
|
||||||
|
margin-top: 13px;
|
||||||
|
display: grid;
|
||||||
|
/* 使用 Grid 布局 */
|
||||||
|
grid-template-columns: 25% 20% 55%;
|
||||||
|
/* 设置四列,每列占 25% 宽度 */
|
||||||
|
/* 元素间的间隔 */
|
||||||
|
width: 450px;
|
||||||
|
/* 或者设置固定宽度 */
|
||||||
|
height: 100px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .imageLeft {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
} */
|
||||||
|
|
||||||
|
/* .inputRight {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
} */
|
||||||
|
|
||||||
|
/* .right-input {
|
||||||
|
background-color: aqua;
|
||||||
|
} */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.image-preview {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
/* object-fit: cover;
|
||||||
|
border-radius: 8px; */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* .inputRight input {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding: 8px;
|
||||||
|
width: 200px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 4px;
|
||||||
|
} */
|
||||||
|
</style>
|
@ -6,9 +6,13 @@
|
|||||||
<span>客服类型:</span>
|
<span>客服类型:</span>
|
||||||
<span>
|
<span>
|
||||||
<el-radio-group v-model="radios" @change="handleRadioChange">
|
<el-radio-group v-model="radios" @change="handleRadioChange">
|
||||||
<el-radio value="1" size="large">系统客服</el-radio>
|
<el-radio v-for="dict in getIntDictOptions(DICT_TYPE.KEFU_CONFIGURATION_TYPE)"
|
||||||
<el-radio value="2" size="large">拨打电话</el-radio>
|
:key="dict.value"
|
||||||
<!-- <el-radio value="3" size="large">跳转链接</el-radio> -->
|
:value="dict.value"
|
||||||
|
size="large"
|
||||||
|
>
|
||||||
|
{{dict.label}}
|
||||||
|
</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</span>
|
</span>
|
||||||
<p style="margin-left: 80px;color:#bcbaba;font-size:13px">系统客服:点击联系客服使用系统的自带客服;拨打电话:点击联系客服拨打客服电话;跳转链接:跳转外部链接联系客服</p>
|
<p style="margin-left: 80px;color:#bcbaba;font-size:13px">系统客服:点击联系客服使用系统的自带客服;拨打电话:点击联系客服拨打客服电话;跳转链接:跳转外部链接联系客服</p>
|
||||||
@ -76,6 +80,8 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||||
|
|
||||||
import { ConfigurationApi, ConfigurationVO } from '@/api/mall/promotion/configuration'
|
import { ConfigurationApi, ConfigurationVO } from '@/api/mall/promotion/configuration'
|
||||||
|
|
||||||
|
|
||||||
@ -84,7 +90,7 @@ const { t } = useI18n() // 国际化
|
|||||||
|
|
||||||
const loading = ref(true) // 列表的加载中
|
const loading = ref(true) // 列表的加载中
|
||||||
|
|
||||||
const radios = ref('1')
|
const radios = ref(1)
|
||||||
|
|
||||||
const formData = ref({
|
const formData = ref({
|
||||||
id: undefined,
|
id: undefined,
|
||||||
@ -101,7 +107,7 @@ const getList = async () => {
|
|||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
|
|
||||||
formData.value = await ConfigurationApi.getConfiguration(Number(radios.value))
|
formData.value = await ConfigurationApi.getConfiguration(radios.value)
|
||||||
// radios.value = formData.value.id
|
// radios.value = formData.value.id
|
||||||
console.log('11111',radios.value)
|
console.log('11111',radios.value)
|
||||||
|
|
||||||
|
@ -4,17 +4,17 @@
|
|||||||
:show-tab-bar="selectedTemplateItem === 0" :show-navigation-bar="selectedTemplateItem !== 0"
|
:show-tab-bar="selectedTemplateItem === 0" :show-navigation-bar="selectedTemplateItem !== 0"
|
||||||
:preview-url="previewUrl" @save="submitForm" @reset="handleEditorReset">
|
:preview-url="previewUrl" @save="submitForm" @reset="handleEditorReset">
|
||||||
<template #toolBarLeft>
|
<template #toolBarLeft>
|
||||||
<!-- <el-radio-group
|
<!-- <el-radio-group-->
|
||||||
v-model="selectedTemplateItem"
|
<!-- v-model="selectedTemplateItem"-->
|
||||||
class="h-full!"
|
<!-- class="h-full!"-->
|
||||||
@change="handleTemplateItemChange"
|
<!-- @change="handleTemplateItemChange"-->
|
||||||
>
|
<!-- >-->
|
||||||
<el-tooltip v-for="(item, index) in templateItems" :key="index" :content="item.name">
|
<!-- <el-tooltip v-for="(item, index) in templateItems" :key="index" :content="item.name">-->
|
||||||
<el-radio-button :label="index">
|
<!-- <el-radio-button :label="index">-->
|
||||||
<Icon :icon="item.icon" :size="24" />
|
<!-- <Icon :icon="item.icon" :size="24" />-->
|
||||||
</el-radio-button>
|
<!-- </el-radio-button>-->
|
||||||
</el-tooltip>
|
<!-- </el-tooltip>-->
|
||||||
</el-radio-group> -->
|
<!-- </el-radio-group>-->
|
||||||
</template>
|
</template>
|
||||||
</DiyEditor>
|
</DiyEditor>
|
||||||
</template>
|
</template>
|
||||||
|
@ -89,8 +89,8 @@ const activeConversationId = ref(-1) // 选中的会话
|
|||||||
const collapse = computed(() => appStore.getCollapse) // 折叠菜单
|
const collapse = computed(() => appStore.getCollapse) // 折叠菜单
|
||||||
|
|
||||||
/** 加载会话列表 */
|
/** 加载会话列表 */
|
||||||
const getConversationList = async () => {
|
const getConversationList = async (name: string) => {
|
||||||
const list = await KeFuConversationApi.getConversationListByKefuId(getStaffToken())
|
const list = await KeFuConversationApi.getConversationListByKefuId(getStaffToken(),name)
|
||||||
list.sort((a: KeFuConversationRespVO, _) => (a.adminPinned ? -1 : 1))
|
list.sort((a: KeFuConversationRespVO, _) => (a.adminPinned ? -1 : 1))
|
||||||
conversationList.value = list
|
conversationList.value = list
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-footer>
|
</el-footer>
|
||||||
</el-container>
|
</el-container>
|
||||||
<el-empty v-else description="请选择左侧的一个会话后开始" />
|
<el-empty style="background-color: white;" v-else description="请选择左侧的一个会话后开始" />
|
||||||
|
|
||||||
<Dialog :title="dialogTitle" v-model="dialogVisible" :modal="false" width="700px">
|
<Dialog :title="dialogTitle" v-model="dialogVisible" :modal="false" width="700px">
|
||||||
|
|
||||||
|
@ -2,11 +2,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-show="!isEmpty(conversation)" class="kefu">
|
<div v-show="!isEmpty(conversation)" class="kefu">
|
||||||
<!-- <div class="header-title h-60px flex justify-center items-center">他的足迹</div> -->
|
<!-- <div class="header-title h-60px flex justify-center items-center">他的足迹</div> -->
|
||||||
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
|
<el-tabs tab-position="top" v-model="activeName" class="demo-tabs" @tab-click="handleClick">
|
||||||
<el-tab-pane label="最近浏览" name="a" />
|
<el-tab-pane label="足迹" name="a" />
|
||||||
<el-tab-pane label="订单列表" name="b" />
|
<el-tab-pane label="购买" name="b" />
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
<div>
|
<div >
|
||||||
|
<el-input @input="findgoodsNameInput" v-model="goodsName" placeholder="搜索商品名称" v-if="activeName === 'a'"
|
||||||
|
style="width: 100%;"/>
|
||||||
|
|
||||||
|
<el-input @input="findNoInput" v-model="no" placeholder="搜索订单编号" v-if="activeName === 'b'"
|
||||||
|
style="width: 100%;"/>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 5px;">
|
||||||
<el-scrollbar ref="scrollbarRef" always height="calc(115vh - 400px)" @scroll="handleScroll">
|
<el-scrollbar ref="scrollbarRef" always height="calc(115vh - 400px)" @scroll="handleScroll">
|
||||||
<!-- 最近浏览 -->
|
<!-- 最近浏览 -->
|
||||||
<ProductBrowsingHistory v-if="activeName === 'a'" ref="productBrowsingHistoryRef" />
|
<ProductBrowsingHistory v-if="activeName === 'a'" ref="productBrowsingHistoryRef" />
|
||||||
@ -30,7 +37,8 @@ import { ElScrollbar as ElScrollbarType } from 'element-plus/es/components/scrol
|
|||||||
defineOptions({ name: 'MemberBrowsingHistory' })
|
defineOptions({ name: 'MemberBrowsingHistory' })
|
||||||
|
|
||||||
const activeName = ref('a')
|
const activeName = ref('a')
|
||||||
|
const goodsName = ref('')
|
||||||
|
const no = ref('')
|
||||||
/** tab 切换 */
|
/** tab 切换 */
|
||||||
const productBrowsingHistoryRef = ref<InstanceType<typeof ProductBrowsingHistory>>()
|
const productBrowsingHistoryRef = ref<InstanceType<typeof ProductBrowsingHistory>>()
|
||||||
const orderBrowsingHistoryRef = ref<InstanceType<typeof OrderBrowsingHistory>>()
|
const orderBrowsingHistoryRef = ref<InstanceType<typeof OrderBrowsingHistory>>()
|
||||||
@ -40,21 +48,32 @@ const handleClick = async (tab: TabsPaneContext) => {
|
|||||||
await getHistoryList()
|
await getHistoryList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//查询
|
||||||
|
const findgoodsNameInput = async () => {
|
||||||
|
getHistoryList()
|
||||||
|
}
|
||||||
|
|
||||||
/** 获得历史数据 */
|
/** 获得历史数据 */
|
||||||
// TODO @puhui:不要用 a、b 哈。就订单列表、浏览列表这种噶
|
// TODO @puhui:不要用 a、b 哈。就订单列表、浏览列表这种噶
|
||||||
const getHistoryList = async () => {
|
const getHistoryList = async () => {
|
||||||
|
|
||||||
switch (activeName.value) {
|
switch (activeName.value) {
|
||||||
case 'a':
|
case 'a':
|
||||||
await productBrowsingHistoryRef.value?.getHistoryList(conversation.value)
|
await productBrowsingHistoryRef.value?.getHistoryList(conversation.value,goodsName.value)
|
||||||
break
|
break
|
||||||
case 'b':
|
case 'b':
|
||||||
await orderBrowsingHistoryRef.value?.getHistoryList(conversation.value)
|
await orderBrowsingHistoryRef.value?.getHistoryList(conversation.value,no.value)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//搜索框
|
||||||
|
const findNoInput = async () => {
|
||||||
|
getHistoryList()
|
||||||
|
}
|
||||||
|
|
||||||
/** 加载下一页数据 */
|
/** 加载下一页数据 */
|
||||||
const loadMore = async () => {
|
const loadMore = async () => {
|
||||||
switch (activeName.value) {
|
switch (activeName.value) {
|
||||||
|
@ -0,0 +1,92 @@
|
|||||||
|
<!-- 目录是不是叫 member 好点。然后这个组件是 MemberInfo,里面有浏览足迹 -->
|
||||||
|
<template>
|
||||||
|
<div v-show="!isEmpty(conversation)" class="kefu">
|
||||||
|
<!-- <div class="header-title h-60px flex justify-center items-center">他的足迹</div> -->
|
||||||
|
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
|
||||||
|
<el-tab-pane label="全部" name="a" />
|
||||||
|
<el-tab-pane label="未支付" name="b" />
|
||||||
|
<el-tab-pane label="未发货" name="c" />
|
||||||
|
<el-tab-pane label="退款中" name="d" />
|
||||||
|
</el-tabs>
|
||||||
|
<div>
|
||||||
|
<el-input @input="findNoInput" v-model="no" placeholder="搜索订单编号"
|
||||||
|
style="width: 100%;"/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<el-scrollbar ref="scrollbarRef" always height="calc(115vh - 400px)" @scroll="handleScroll">
|
||||||
|
<OrderBrowsingHistorys ref="orderBrowsingHistorysRef" />
|
||||||
|
</el-scrollbar>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-empty v-show="isEmpty(conversation)" description="请选择左侧的一个会话后开始" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { TabsPaneContext } from 'element-plus'
|
||||||
|
import OrderBrowsingHistorys from './OrderBrowsingHistorys.vue'
|
||||||
|
import { KeFuConversationRespVO } from '@/api/mall/promotion/kefu/conversation'
|
||||||
|
import { isEmpty } from '@/utils/is'
|
||||||
|
import { debounce } from 'lodash-es'
|
||||||
|
import { ElScrollbar as ElScrollbarType } from 'element-plus/es/components/scrollbar/index'
|
||||||
|
|
||||||
|
defineOptions({ name: 'MemberBrowsingHistorys' })
|
||||||
|
|
||||||
|
const activeName = ref('a')
|
||||||
|
|
||||||
|
/** tab 切换 */
|
||||||
|
const orderBrowsingHistorysRef = ref<InstanceType<typeof OrderBrowsingHistorys>>()
|
||||||
|
const handleClick = async (tab: TabsPaneContext) => {
|
||||||
|
activeName.value = tab.paneName as string
|
||||||
|
await nextTick()
|
||||||
|
await getHistoryList()
|
||||||
|
}
|
||||||
|
const no = ref('')
|
||||||
|
|
||||||
|
/** 获得历史数据 */
|
||||||
|
// TODO @puhui:不要用 a、b 哈。就订单列表、浏览列表这种噶 : 我就要用abcd😈
|
||||||
|
const getHistoryList = async () => {
|
||||||
|
console.log('11111执行11111',activeName.value)
|
||||||
|
|
||||||
|
await orderBrowsingHistorysRef.value?.getHistoryList(conversation.value,activeName.value,no.value)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//搜索框
|
||||||
|
const findNoInput = async () => {
|
||||||
|
getHistoryList()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 加载下一页数据 */
|
||||||
|
const loadMore = async () => {
|
||||||
|
await orderBrowsingHistorysRef.value?.loadMore()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 浏览历史初始化 */
|
||||||
|
const conversation = ref<KeFuConversationRespVO>({} as KeFuConversationRespVO) // 用户会话
|
||||||
|
const initHistory = async (val: KeFuConversationRespVO) => {
|
||||||
|
activeName.value = 'a'
|
||||||
|
conversation.value = val
|
||||||
|
await nextTick()
|
||||||
|
await getHistoryList()
|
||||||
|
}
|
||||||
|
defineExpose({ initHistory })
|
||||||
|
|
||||||
|
/** 处理消息列表滚动事件(debounce 限流) */
|
||||||
|
const scrollbarRef = ref<InstanceType<typeof ElScrollbarType>>()
|
||||||
|
const handleScroll = debounce(() => {
|
||||||
|
const wrap = scrollbarRef.value?.wrapRef
|
||||||
|
// 触底重置
|
||||||
|
if (Math.abs(wrap!.scrollHeight - wrap!.clientHeight - wrap!.scrollTop) < 1) {
|
||||||
|
loadMore()
|
||||||
|
}
|
||||||
|
}, 200)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.header-title {
|
||||||
|
border-bottom: #e4e0e0 solid 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</style>
|
@ -15,7 +15,8 @@ const total = ref(0) // 总数
|
|||||||
const queryParams = reactive({
|
const queryParams = reactive({
|
||||||
pageNo: 1,
|
pageNo: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
userId: 0
|
userId: 0,
|
||||||
|
no: '',
|
||||||
})
|
})
|
||||||
const skipGetMessageList = computed(() => {
|
const skipGetMessageList = computed(() => {
|
||||||
// 已加载到最后一页的话则不触发新的消息获取
|
// 已加载到最后一页的话则不触发新的消息获取
|
||||||
@ -23,8 +24,9 @@ const skipGetMessageList = computed(() => {
|
|||||||
}) // 跳过消息获取
|
}) // 跳过消息获取
|
||||||
|
|
||||||
/** 获得浏览记录 */
|
/** 获得浏览记录 */
|
||||||
const getHistoryList = async (val: KeFuConversationRespVO) => {
|
const getHistoryList = async (val: KeFuConversationRespVO,no: string) => {
|
||||||
queryParams.userId = val.userId
|
queryParams.userId = val.userId
|
||||||
|
queryParams.no = no
|
||||||
const res = await getOrderPage(queryParams)
|
const res = await getOrderPage(queryParams)
|
||||||
total.value = res.total
|
total.value = res.total
|
||||||
list.value = res.list
|
list.value = res.list
|
||||||
@ -38,7 +40,8 @@ const loadMore = async () => {
|
|||||||
queryParams.pageNo += 1
|
queryParams.pageNo += 1
|
||||||
const res = await getOrderPage(queryParams)
|
const res = await getOrderPage(queryParams)
|
||||||
total.value = res.total
|
total.value = res.total
|
||||||
concat(list.value, res.list)
|
// concat(list.value, res.list)
|
||||||
|
list.value = list.value.concat(res.list);
|
||||||
}
|
}
|
||||||
defineExpose({ getHistoryList, loadMore })
|
defineExpose({ getHistoryList, loadMore })
|
||||||
</script>
|
</script>
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
<template>
|
||||||
|
<OrderItems v-for="item in list" :key="item.id" :order="item" class="mb-10px" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import OrderItems from '@/views/mall/promotion/kefu/components/message/OrderItems.vue'
|
||||||
|
import { KeFuConversationRespVO } from '@/api/mall/promotion/kefu/conversation'
|
||||||
|
import { getOrderPage } from '@/api/mall/trade/order'
|
||||||
|
import { concat } from 'lodash-es'
|
||||||
|
|
||||||
|
defineOptions({ name: 'OrderBrowsingHistorys' })
|
||||||
|
|
||||||
|
const list = ref<any>([]) // 列表
|
||||||
|
const total = ref(0) // 总数
|
||||||
|
const queryParams = reactive({
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
userId: 0,
|
||||||
|
activeName: 'a',
|
||||||
|
no: '',
|
||||||
|
})
|
||||||
|
const skipGetMessageList = computed(() => {
|
||||||
|
// 已加载到最后一页的话则不触发新的消息获取
|
||||||
|
return total.value > 0 && Math.ceil(total.value / queryParams.pageSize) === queryParams.pageNo
|
||||||
|
}) // 跳过消息获取
|
||||||
|
|
||||||
|
/** 获得浏览记录 */
|
||||||
|
const getHistoryList = async (val: KeFuConversationRespVO,activeName: string,no: string) => {
|
||||||
|
queryParams.userId = val.userId
|
||||||
|
queryParams.activeName = activeName
|
||||||
|
queryParams.no = no
|
||||||
|
queryParams.pageNo = 1
|
||||||
|
const res = await getOrderPage(queryParams)
|
||||||
|
total.value = res.total
|
||||||
|
list.value = res.list
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 加载下一页数据 */
|
||||||
|
const loadMore = async () => {
|
||||||
|
if (skipGetMessageList.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
queryParams.pageNo += 1
|
||||||
|
const res = await getOrderPage(queryParams)
|
||||||
|
total.value = res.total
|
||||||
|
// concat(list.value, res.list)
|
||||||
|
list.value = list.value.concat(res.list);
|
||||||
|
}
|
||||||
|
defineExpose({ getHistoryList, loadMore })
|
||||||
|
</script>
|
@ -27,7 +27,8 @@ const queryParams = reactive({
|
|||||||
pageNo: 1,
|
pageNo: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
userId: 0,
|
userId: 0,
|
||||||
userDeleted: false
|
userDeleted: false,
|
||||||
|
goodsName: ''
|
||||||
})
|
})
|
||||||
const skipGetMessageList = computed(() => {
|
const skipGetMessageList = computed(() => {
|
||||||
// 已加载到最后一页的话则不触发新的消息获取
|
// 已加载到最后一页的话则不触发新的消息获取
|
||||||
@ -35,8 +36,9 @@ const skipGetMessageList = computed(() => {
|
|||||||
}) // 跳过消息获取
|
}) // 跳过消息获取
|
||||||
|
|
||||||
/** 获得浏览记录 */
|
/** 获得浏览记录 */
|
||||||
const getHistoryList = async (val: KeFuConversationRespVO) => {
|
const getHistoryList = async (val: KeFuConversationRespVO,goodsName: string) => {
|
||||||
queryParams.userId = val.userId
|
queryParams.userId = val.userId
|
||||||
|
queryParams.goodsName = goodsName
|
||||||
const res = await getBrowseHistoryPage(queryParams)
|
const res = await getBrowseHistoryPage(queryParams)
|
||||||
total.value = res.total
|
total.value = res.total
|
||||||
list.value = res.list
|
list.value = res.list
|
||||||
@ -50,7 +52,8 @@ const loadMore = async () => {
|
|||||||
queryParams.pageNo += 1
|
queryParams.pageNo += 1
|
||||||
const res = await getBrowseHistoryPage(queryParams)
|
const res = await getBrowseHistoryPage(queryParams)
|
||||||
total.value = res.total
|
total.value = res.total
|
||||||
concat(list.value, res.list)
|
// concat(list.value, res.list)
|
||||||
|
list.value = list.value.concat(res.list);
|
||||||
}
|
}
|
||||||
defineExpose({ getHistoryList, loadMore })
|
defineExpose({ getHistoryList, loadMore })
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import KeFuConversationList from './KeFuConversationList.vue'
|
import KeFuConversationList from './KeFuConversationList.vue'
|
||||||
import KeFuMessageList from './KeFuMessageList.vue'
|
import KeFuMessageList from './KeFuMessageList.vue'
|
||||||
import MemberBrowsingHistory from './history/MemberBrowsingHistory.vue'
|
import MemberBrowsingHistory from './history/MemberBrowsingHistory.vue'
|
||||||
import UserInfo from './UserInfo.vue'
|
import MemberBrowsingHistorys from './history/MemberBrowsingHistorys.vue'
|
||||||
|
|
||||||
export { KeFuConversationList, KeFuMessageList, MemberBrowsingHistory ,UserInfo}
|
export { KeFuConversationList, KeFuMessageList, MemberBrowsingHistory ,MemberBrowsingHistorys}
|
||||||
|
@ -0,0 +1,182 @@
|
|||||||
|
<template>
|
||||||
|
<div v-if="isObject(getMessageContent)">
|
||||||
|
<div :key="getMessageContent.id" class="order-list-card-box mt-14px">
|
||||||
|
<div class="order-card-header flex items-center justify-between p-x-5px">
|
||||||
|
<div class="order-no">
|
||||||
|
订单号:
|
||||||
|
<span style="cursor: pointer" @click="openDetail(getMessageContent.id)">
|
||||||
|
{{ getMessageContent.no }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div :class="formatOrderColor(getMessageContent)" class="order-state font-16">
|
||||||
|
{{ formatOrderStatus(getMessageContent) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-for="item in getMessageContent.items" :key="item.id" class="border-bottom">
|
||||||
|
<ProductItem
|
||||||
|
:spu-id="item.spuId"
|
||||||
|
:num="item.count"
|
||||||
|
:picUrl="item.picUrl"
|
||||||
|
:price="item.price"
|
||||||
|
:skuText="item.properties.map((property: any) => property.valueName).join(' ')"
|
||||||
|
:title="item.spuName"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="pay-box flex justify-end pr-5px">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="discounts-title pay-color"
|
||||||
|
>共 {{ getMessageContent?.productCount }} 件商品,总金额:
|
||||||
|
</div>
|
||||||
|
<div class="discounts-money pay-color">
|
||||||
|
¥{{ fenToYuan(getMessageContent?.payPrice) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { fenToYuan, jsonParse } from '@/utils'
|
||||||
|
import { KeFuMessageRespVO } from '@/api/mall/promotion/kefu/message'
|
||||||
|
import { isObject } from '@/utils/is'
|
||||||
|
import ProductItem from '@/views/mall/promotion/kefu/components/message/ProductItem.vue'
|
||||||
|
|
||||||
|
const { push } = useRouter()
|
||||||
|
|
||||||
|
defineOptions({ name: 'OrderItems' })
|
||||||
|
const props = defineProps<{
|
||||||
|
message?: KeFuMessageRespVO
|
||||||
|
order?: any
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const getMessageContent = computed(() =>
|
||||||
|
typeof props.message !== 'undefined' ? jsonParse(props!.message!.content) : props.order
|
||||||
|
)
|
||||||
|
|
||||||
|
/** 查看订单详情 */
|
||||||
|
const openDetail = (id: number) => {
|
||||||
|
console.log(getMessageContent)
|
||||||
|
push({ name: 'TradeOrderDetail', params: { id } })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化订单状态的颜色
|
||||||
|
*
|
||||||
|
* @param order 订单
|
||||||
|
* @return {string} 颜色的 class 名称
|
||||||
|
*/
|
||||||
|
function formatOrderColor(order: any) {
|
||||||
|
if (order.status === 0) {
|
||||||
|
return 'info-color'
|
||||||
|
}
|
||||||
|
if (order.status === 10 || order.status === 20 || (order.status === 30 && !order.commentStatus)) {
|
||||||
|
return 'warning-color'
|
||||||
|
}
|
||||||
|
if (order.status === 30 && order.commentStatus) {
|
||||||
|
return 'success-color'
|
||||||
|
}
|
||||||
|
return 'danger-color'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化订单状态
|
||||||
|
*
|
||||||
|
* @param order 订单
|
||||||
|
*/
|
||||||
|
function formatOrderStatus(order: any) {
|
||||||
|
if (order.status === 0) {
|
||||||
|
return '待付款'
|
||||||
|
}
|
||||||
|
if (order.status === 10 && order.deliveryType === 1) {
|
||||||
|
return '待发货'
|
||||||
|
}
|
||||||
|
if (order.status === 10 && order.deliveryType === 2) {
|
||||||
|
return '待核销'
|
||||||
|
}
|
||||||
|
if (order.status === 20) {
|
||||||
|
return '待收货'
|
||||||
|
}
|
||||||
|
if (order.status === 30 && !order.commentStatus) {
|
||||||
|
return '待评价'
|
||||||
|
}
|
||||||
|
if (order.status === 30 && order.commentStatus) {
|
||||||
|
return '已完成'
|
||||||
|
}
|
||||||
|
if (order.status === 100) {
|
||||||
|
return '退款中'
|
||||||
|
}
|
||||||
|
return '已关闭'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.order-list-card-box {
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px var(--el-border-color) solid;
|
||||||
|
background-color: var(--app-content-bg-color);
|
||||||
|
|
||||||
|
.order-card-header {
|
||||||
|
height: 28px;
|
||||||
|
|
||||||
|
.order-no {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
span {
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: var(--left-menu-bg-active-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pay-box {
|
||||||
|
padding-top: 10px;
|
||||||
|
|
||||||
|
.discounts-title {
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: normal;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discounts-money {
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: normal;
|
||||||
|
color: #999;
|
||||||
|
font-family: OPPOSANS;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pay-color {
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--left-menu-text-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-color {
|
||||||
|
color: #faad14;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.danger-color {
|
||||||
|
color: #ff3000;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success-color {
|
||||||
|
color: #52c41a;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-color {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
</style>
|
@ -3,7 +3,7 @@
|
|||||||
<el-popover :width="500" placement="top" trigger="click">
|
<el-popover :width="500" placement="top" trigger="click">
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<!-- <Icon :size="30" class="ml-10px cursor-pointer" icon="twemoji:grinning-face" /> -->
|
<!-- <Icon :size="30" class="ml-10px cursor-pointer" icon="twemoji:grinning-face" /> -->
|
||||||
<img :src="biaoqing" style="margin-left:20px" class="w-23px h-25px" />
|
<img :src="biaoqing" class="w-23px h-25px" />
|
||||||
</template>
|
</template>
|
||||||
<ElScrollbar height="300px">
|
<ElScrollbar height="300px">
|
||||||
<ul class="ml-2 flex flex-wrap px-2">
|
<ul class="ml-2 flex flex-wrap px-2">
|
||||||
|
@ -1,52 +1,57 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<!-- 新区域,放在头部 -->
|
<!-- 新区域,放在头部 -->
|
||||||
<el-row style="display: flex; justify-content: center;">
|
<el-row style="display: flex; justify-content: center;">
|
||||||
|
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<div style="width:100%;height:68px;background-color:#3c80ff;">
|
<div style="width:100%;height:68px;background-color:#3c80ff;">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-input
|
<el-input @input="findNameInput" v-model="findName"
|
||||||
style="width: 80%;margin-top: 20px;margin-left:10px;"
|
style="width: 80%;margin-top: 20px;margin-left:23px;"
|
||||||
:suffix-icon="Search"
|
:suffix-icon="Search"/>
|
||||||
/>
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="1">
|
||||||
|
<el-avatar style=" margin-top: 15px;" :src="pic"/>
|
||||||
|
<!-- <span style="display: flex; margin-top: 15px;">
|
||||||
|
|
||||||
|
<span style="margin-left:5px;margin-top: 9px;">{{name}}</span>
|
||||||
|
<el-switch
|
||||||
|
style="margin-top: 4px;--el-switch-on-color: #13ce66; --el-switch-off-color: #b6bac1;"
|
||||||
|
v-model="lineStatus" class="ml-2" width="60" inline-prompt active-text="在线"
|
||||||
|
inactive-text="下线" @change="handleSwitchChange"/>
|
||||||
|
</span> -->
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="7">
|
||||||
|
|
||||||
|
<span style="display: flex; margin-top: 15px;">
|
||||||
|
<!-- <el-avatar :src="pic"/> -->
|
||||||
|
<span style="margin-left:5px;margin-top: 9px;">{{name}}</span>
|
||||||
|
<el-switch
|
||||||
|
style="margin-top: 4px;--el-switch-on-color: #13ce66; --el-switch-off-color: #b6bac1;"
|
||||||
|
v-model="lineStatus" class="ml-2" width="60" inline-prompt active-text="在线"
|
||||||
|
inactive-text="下线" @change="handleSwitchChange"/>
|
||||||
|
</span>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="4">
|
||||||
|
<el-button @click="out" size="small" round
|
||||||
|
style="margin-top:23px;margin-left:72%">退出
|
||||||
|
</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<span style="display: flex; margin-top: 15px;">
|
<el-menu background-color="#3c80ff" text-color="white" active-text-color="white"
|
||||||
<el-avatar
|
style="width:100%;display: flex;">
|
||||||
:src="pic"
|
<el-menu-item @click="userInfo" style="width:33%;height:70px" index="1">客户信息
|
||||||
/>
|
</el-menu-item>
|
||||||
<span style="margin-left:5px;margin-top: 9px;">{{name}}</span>
|
<el-menu-item @click="jiaoyi" style="width:33%;height:70px" index="3">交易订单
|
||||||
<el-switch
|
</el-menu-item>
|
||||||
style="margin-top: 4px;--el-switch-on-color: #13ce66; --el-switch-off-color: #b6bac1;"
|
<el-menu-item @click="zuoji" style="width:33%;height:70px" index="2">商品信息
|
||||||
v-model="lineStatus"
|
</el-menu-item>
|
||||||
class="ml-2"
|
<!-- <el-menu-item style="width:34%;height:70px" index="3">商品信息</el-menu-item> -->
|
||||||
width="60"
|
</el-menu>
|
||||||
inline-prompt
|
|
||||||
active-text="在线"
|
|
||||||
inactive-text="下线"
|
|
||||||
@change="handleSwitchChange"
|
|
||||||
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="6">
|
|
||||||
<el-button @click="out" size="small" round style="margin-top:23px;margin-left:75%">退出</el-button>
|
|
||||||
</el-col>
|
|
||||||
|
|
||||||
<el-col :span="6">
|
|
||||||
<el-menu
|
|
||||||
background-color="#3c80ff"
|
|
||||||
text-color="white"
|
|
||||||
active-text-color="white"
|
|
||||||
style="width:100%;display: flex;"
|
|
||||||
>
|
|
||||||
<el-menu-item @click="userInfo" style="width:33%;height:70px" index="1">客户信息</el-menu-item>
|
|
||||||
<el-menu-item @click="zuoji" style="width:33%;height:70px" index="2">他的足迹</el-menu-item>
|
|
||||||
<!-- <el-menu-item style="width:34%;height:70px" index="3">商品信息</el-menu-item> -->
|
|
||||||
</el-menu>
|
|
||||||
|
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@ -67,61 +72,77 @@
|
|||||||
<!-- 会话详情(选中会话的消息列表) -->
|
<!-- 会话详情(选中会话的消息列表) -->
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
|
|
||||||
<KeFuMessageList ref="keFuChatBoxRef" @change="getConversationList"/>
|
<KeFuMessageList ref="keFuChatBoxRef" @change="getConversationList"/>
|
||||||
|
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
<!-- 会员足迹(选中会话的会员足迹) -->
|
<!-- 会员足迹(选中会话的会员足迹) -->
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<ContentWrap v-show="chick == '2'">
|
|
||||||
|
<ContentWrap v-show="chick == '1' && clickUser == 2">
|
||||||
|
<div style="height: 522px ;">
|
||||||
|
<div>
|
||||||
|
<span style="display: flex;">
|
||||||
|
<el-avatar style="border: 1px solid #f8f9ee;" :src="user.avatar"/>
|
||||||
|
<span style="margin-left:5px;margin-top: 9px;">{{user.nickname}}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-divider style="border-color: #f5f5f5;margin-top: 15px;margin-bottom:15px;"/>
|
||||||
|
<div>
|
||||||
|
<span style="color: #5d5d59;font-size: 13px ;">手机号</span><span
|
||||||
|
style="margin-left: 47px;font-size: 14px ;">{{user.mobile}}</span>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 5px;">
|
||||||
|
<span style="color: #5d5d59;font-size: 13px ;">分组</span><span
|
||||||
|
style="margin-left: 60px;font-size: 14px ;">{{user.groupName}}</span>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 5px;">
|
||||||
|
<span style="color: #5d5d59;font-size: 13px ;">用户标签</span><span
|
||||||
|
style="margin-left: 33px;font-size: 14px ;">客户</span>
|
||||||
|
</div>
|
||||||
|
<el-divider style="border-color: #f5f5f5;margin-top: 15px;margin-bottom:15px;"/>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<span style="color: #5d5d59;font-size: 13px ;">用户等级</span><span
|
||||||
|
style="margin-left: 35px;font-size: 14px ;">{{user.levelName}}</span>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 5px;">
|
||||||
|
<span style="color: #5d5d59;font-size: 13px ;">推荐人</span><span
|
||||||
|
style="margin-left: 47px;font-size: 14px ;">客户</span>
|
||||||
|
</div>
|
||||||
|
<!-- <div style="margin-top: 5px;">
|
||||||
|
<span style="color: #5d5d59;font-size: 13px ;">用户类型</span><span
|
||||||
|
style="margin-left: 33px;font-size: 14px ;">小客户</span>
|
||||||
|
</div> -->
|
||||||
|
<div style="margin-top: 5px;">
|
||||||
|
<span style="color: #5d5d59;font-size: 13px ;">积分</span><span
|
||||||
|
style="margin-left: 60px;font-size: 14px ;">{{user.point}}</span>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 5px;">
|
||||||
|
<span style="color: #5d5d59;font-size: 13px ;">推广员</span><span
|
||||||
|
style="margin-left: 47px;font-size: 14px ;">客户</span>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 5px;">
|
||||||
|
<span style="color: #5d5d59;font-size: 13px ;">生日</span><span
|
||||||
|
style="margin-left: 60px;font-size: 14px ;">{{user.birthday}}</span>
|
||||||
|
</div>
|
||||||
|
<el-divider style="border-color: #f5f5f5;margin-top: 15px;margin-bottom:15px;"/>
|
||||||
|
</div>
|
||||||
|
</ContentWrap>
|
||||||
|
|
||||||
|
<ContentWrap v-show="chick == '1' && clickUser == 1">
|
||||||
|
<el-empty description="请选择左侧的一个会话后开始" />
|
||||||
|
</ContentWrap>
|
||||||
|
|
||||||
|
<ContentWrap v-show="chick == '2'">
|
||||||
<MemberBrowsingHistory ref="memberBrowsingHistoryRef"/>
|
<MemberBrowsingHistory ref="memberBrowsingHistoryRef"/>
|
||||||
</ContentWrap>
|
</ContentWrap>
|
||||||
|
|
||||||
<ContentWrap v-show = "chick == '1'">
|
<ContentWrap v-show="chick == '3'">
|
||||||
<div style="height: 522px ;" >
|
<MemberBrowsingHistorys ref="memberBrowsingHistorysRef"/>
|
||||||
<div>
|
|
||||||
<span style="display: flex;">
|
|
||||||
<el-avatar
|
|
||||||
style="border: 1px solid #f8f9ee;"
|
|
||||||
:src="user.avatar"
|
|
||||||
/>
|
|
||||||
<span style="margin-left:5px;margin-top: 9px;">{{user.nickname}}</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-divider style="border-color: #f5f5f5;margin-top: 15px;margin-bottom:15px;" />
|
|
||||||
<div>
|
|
||||||
<span style="color: #5d5d59;font-size: 13px ;">手机号</span><span style="margin-left: 47px;font-size: 14px ;">{{user.mobile}}</span>
|
|
||||||
</div>
|
|
||||||
<div style="margin-top: 5px;">
|
|
||||||
<span style="color: #5d5d59;font-size: 13px ;">分组</span><span style="margin-left: 60px;font-size: 14px ;">{{user.groupName}}</span>
|
|
||||||
</div>
|
|
||||||
<div style="margin-top: 5px;">
|
|
||||||
<span style="color: #5d5d59;font-size: 13px ;">用户标签</span><span style="margin-left: 33px;font-size: 14px ;">小客户</span>
|
|
||||||
</div>
|
|
||||||
<el-divider style="border-color: #f5f5f5;margin-top: 15px;margin-bottom:15px;" />
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<span style="color: #5d5d59;font-size: 13px ;">用户等级</span><span style="margin-left: 35px;font-size: 14px ;">{{user.levelName}}</span>
|
|
||||||
</div>
|
|
||||||
<div style="margin-top: 5px;">
|
|
||||||
<span style="color: #5d5d59;font-size: 13px ;">推荐人</span><span style="margin-left: 47px;font-size: 14px ;">客户</span>
|
|
||||||
</div>
|
|
||||||
<div style="margin-top: 5px;">
|
|
||||||
<span style="color: #5d5d59;font-size: 13px ;">用户类型</span><span style="margin-left: 33px;font-size: 14px ;">小客户</span>
|
|
||||||
</div>
|
|
||||||
<div style="margin-top: 5px;">
|
|
||||||
<span style="color: #5d5d59;font-size: 13px ;">积分</span><span style="margin-left: 60px;font-size: 14px ;">{{user.point}}</span>
|
|
||||||
</div>
|
|
||||||
<div style="margin-top: 5px;">
|
|
||||||
<span style="color: #5d5d59;font-size: 13px ;">推广员</span><span style="margin-left: 47px;font-size: 14px ;">客户</span>
|
|
||||||
</div>
|
|
||||||
<div style="margin-top: 5px;">
|
|
||||||
<span style="color: #5d5d59;font-size: 13px ;">生日</span><span style="margin-left: 60px;font-size: 14px ;">{{user.birthday}}</span>
|
|
||||||
</div>
|
|
||||||
<el-divider style="border-color: #f5f5f5;margin-top: 15px;margin-bottom:15px;" />
|
|
||||||
</div>
|
|
||||||
</ContentWrap>
|
</ContentWrap>
|
||||||
|
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
@ -129,21 +150,32 @@
|
|||||||
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { KeFuConversationList, KeFuMessageList,MemberBrowsingHistory,UserInfo } from './components'
|
import {
|
||||||
|
KeFuConversationList,
|
||||||
|
KeFuMessageList,
|
||||||
|
MemberBrowsingHistorys,
|
||||||
|
MemberBrowsingHistory
|
||||||
|
|
||||||
|
} from './components'
|
||||||
import {WebSocketMessageTypeConstants} from './components/tools/constants'
|
import {WebSocketMessageTypeConstants} from './components/tools/constants'
|
||||||
|
import { KeFuMessageApi, KeFuMessageRespVO } from '@/api/mall/promotion/kefu/message'
|
||||||
import {KeFuConversationRespVO} from '@/api/mall/promotion/kefu/conversation'
|
import {KeFuConversationRespVO} from '@/api/mall/promotion/kefu/conversation'
|
||||||
import {getRefreshToken, getAccessToken} from '@/utils/auth'
|
import {getRefreshToken, getAccessToken} from '@/utils/auth'
|
||||||
import {useWebSocket} from '@vueuse/core'
|
import {useWebSocket} from '@vueuse/core'
|
||||||
import {Search} from '@element-plus/icons-vue'
|
import {Search} from '@element-plus/icons-vue'
|
||||||
import * as UserApi from '@/api/member/user'
|
import * as UserApi from '@/api/member/user'
|
||||||
import { SupportStaffApi, SupportStaffVO } from '@/api/mall/promotion/supportstaff'
|
import {SupportStaffApi, SupportStaffVO} from '@/api/mall/promotion/supportstaff'
|
||||||
|
import {string} from 'vue-types'
|
||||||
|
import type { TabsPaneContext } from 'element-plus'
|
||||||
|
const findName = ref('')
|
||||||
|
|
||||||
defineOptions({name: 'KeFu'})
|
defineOptions({name: 'KeFu'})
|
||||||
|
|
||||||
const lineStatus = ref(true)
|
const lineStatus = ref(true)
|
||||||
|
|
||||||
|
const clickUser = ref(1)
|
||||||
|
|
||||||
|
|
||||||
const message = useMessage() // 消息弹窗
|
const message = useMessage() // 消息弹窗
|
||||||
|
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
@ -154,74 +186,91 @@
|
|||||||
// const userInfoRef = ref<InstanceType<typeof UserInfo>>()
|
// const userInfoRef = ref<InstanceType<typeof UserInfo>>()
|
||||||
const user = ref<UserApi.UserVO>({} as UserApi.UserVO)
|
const user = ref<UserApi.UserVO>({} as UserApi.UserVO)
|
||||||
const userId = ref(0)
|
const userId = ref(0)
|
||||||
|
const stat = ref(false)
|
||||||
|
|
||||||
// ======================= WebSocket start =======================
|
// ======================= WebSocket start =======================
|
||||||
const server = ref(
|
const server = ref(
|
||||||
(import.meta.env.VITE_BASE_URL + '/infra/ws').replace('http', 'ws') +
|
(import.meta.env.VITE_BASE_URL + '/infra/ws').replace('http', 'ws') +
|
||||||
'?token=' +
|
'?token=' + getRefreshToken()
|
||||||
getRefreshToken()
|
// getAccessToken()
|
||||||
// 使用 getRefreshToken() 方法,而不使用 getAccessToken() 方法的原因:WebSocket 无法方便的刷新访问令牌
|
// 使用 getRefreshToken() 方法,而不使用 getAccessToken() 方法的原因:WebSocket 无法方便的刷新访问令牌
|
||||||
) // WebSocket 服务地址
|
) // WebSocket 服务地址
|
||||||
|
|
||||||
const handleSwitchChange = async (value) =>{
|
|
||||||
console.log('11111:',value)
|
|
||||||
let a = 0;
|
|
||||||
|
|
||||||
if(value == true){
|
|
||||||
a = 1;
|
|
||||||
await SupportStaffApi.updateLineStatus(kefuId,a)
|
|
||||||
message.success('已上线')
|
|
||||||
}else{
|
|
||||||
a = 2;
|
|
||||||
await SupportStaffApi.updateLineStatus(kefuId,a)
|
|
||||||
message.success('已下线')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
const handleSwitchChange = async (value) => {
|
||||||
|
console.log('11111:', value)
|
||||||
|
let a = 0;
|
||||||
|
|
||||||
|
if (value == true) {
|
||||||
|
a = 1;
|
||||||
|
await SupportStaffApi.updateLineStatus(kefuId, a)
|
||||||
|
message.success('已上线')
|
||||||
|
} else {
|
||||||
|
a = 2;
|
||||||
|
await SupportStaffApi.updateLineStatus(kefuId, a)
|
||||||
|
message.success('已下线')
|
||||||
}
|
}
|
||||||
|
|
||||||
let a = 0;
|
}
|
||||||
|
|
||||||
const {status, data, send, open, close} = useWebSocket(server.value, {
|
const shangxian = async () => {
|
||||||
onConnected: function (ws) {
|
await SupportStaffApi.updateLineStatus(kefuId, 1)
|
||||||
console.log('websocket 连接成功!', ws);
|
}
|
||||||
},
|
|
||||||
onDisconnected: function (ws, event) {
|
const xiaxian = async () => {
|
||||||
console.log('WebSocket 连接断开', event);
|
await SupportStaffApi.updateLineStatus(kefuId, 2)
|
||||||
},
|
}
|
||||||
onError: function (ws, event) {
|
|
||||||
console.error('WebSocket 连接错误:', event);
|
let a = 0;
|
||||||
if (event instanceof ErrorEvent) {
|
|
||||||
console.error('详细错误信息:', event.message);
|
const {status, data, send, open, close} = useWebSocket(server.value, {
|
||||||
} else {
|
onConnected: function (ws) {
|
||||||
console.error('非标准错误:', event);
|
shangxian(); //连接成功上线
|
||||||
}
|
console.log('websocket 连接成功!', ws);
|
||||||
},
|
},
|
||||||
onMessage: function (ws, event) {
|
onDisconnected: function (ws, event) {
|
||||||
console.log('收到的 WebSocket 消息:', event.data);
|
xiaxian(); //断开下线
|
||||||
|
console.log('WebSocket 连接断开', event);
|
||||||
|
},
|
||||||
|
// onError: function (ws, event) {
|
||||||
|
// console.error('WebSocket 连接错误:', event);
|
||||||
|
// if (event instanceof ErrorEvent) {
|
||||||
|
// console.error('详细错误信息:', event.message);
|
||||||
|
// } else {
|
||||||
|
// console.error('非标准错误:', event);
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
onMessage: function (ws, event) {
|
||||||
|
// console.log('收到的 WebSocket 消息:', event.data);
|
||||||
|
|
||||||
|
a = a + 1;
|
||||||
|
if (a == 2) {
|
||||||
|
getConversationList()
|
||||||
|
if(userId.value != 0){
|
||||||
|
getBySenderIdStat()
|
||||||
|
if(stat.value){
|
||||||
|
keFuChatBoxRef.value?.refreshMessageList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
a = a + 1 ;
|
},
|
||||||
if(a == 2){
|
autoReconnect: true, // 开启自动重连
|
||||||
getConversationList()
|
heartbeat: true
|
||||||
keFuChatBoxRef.value?.refreshMessageList()
|
});
|
||||||
a = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
autoReconnect: false, // 开启自动重连
|
|
||||||
heartbeat: true
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
// const { data, close, open } = useWebSocket(server.value, {
|
||||||
|
// autoReconnect: true,
|
||||||
|
// heartbeat: true
|
||||||
|
// })
|
||||||
|
|
||||||
|
|
||||||
/** 监听 WebSocket 数据 */
|
/** 监听 WebSocket 数据 */
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
console.log('连接服务器得到消息:',data.value)
|
console.log('连接服务器得到消息:', data.value)
|
||||||
if (!data.value) {
|
if (!data.value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -234,7 +283,7 @@
|
|||||||
// 2.1 解析 type 消息类型
|
// 2.1 解析 type 消息类型
|
||||||
const jsonMessage = JSON.parse(data.value)
|
const jsonMessage = JSON.parse(data.value)
|
||||||
const type = jsonMessage.type
|
const type = jsonMessage.type
|
||||||
console.log('来自用户发送的消息:',data.value)
|
|
||||||
|
|
||||||
if (!type) {
|
if (!type) {
|
||||||
message.error('未知的消息类型:' + data.value)
|
message.error('未知的消息类型:' + data.value)
|
||||||
@ -242,6 +291,7 @@
|
|||||||
}
|
}
|
||||||
// 2.2 消息类型:KEFU_MESSAGE_TYPE
|
// 2.2 消息类型:KEFU_MESSAGE_TYPE
|
||||||
if (type === WebSocketMessageTypeConstants.KEFU_MESSAGE_TYPE) {
|
if (type === WebSocketMessageTypeConstants.KEFU_MESSAGE_TYPE) {
|
||||||
|
console.log('来自用户发送的消息:', JSON.parse(jsonMessage.content))
|
||||||
// 刷新会话列表
|
// 刷新会话列表
|
||||||
// TODO @puhui999:不应该刷新列表,而是根据消息,本地 update 列表的数据;
|
// TODO @puhui999:不应该刷新列表,而是根据消息,本地 update 列表的数据;
|
||||||
getConversationList()
|
getConversationList()
|
||||||
@ -261,39 +311,63 @@
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ======================= WebSocket end =======================
|
// ======================= WebSocket end =======================
|
||||||
/** 加载会话列表 */
|
/** 加载会话列表 */
|
||||||
const keFuConversationRef = ref<InstanceType<typeof KeFuConversationList>>()
|
const keFuConversationRef = ref<InstanceType<typeof KeFuConversationList>>()
|
||||||
const getConversationList = () => {
|
const getConversationList = () => {
|
||||||
keFuConversationRef.value?.getConversationList()
|
keFuConversationRef.value?.getConversationList(findName.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 加载指定会话的消息列表 */
|
/** 加载指定会话的消息列表 */
|
||||||
const keFuChatBoxRef = ref<InstanceType<typeof KeFuMessageList>>()
|
const keFuChatBoxRef = ref<InstanceType<typeof KeFuMessageList>>()
|
||||||
const memberBrowsingHistoryRef = ref<InstanceType<typeof MemberBrowsingHistory>>()
|
const memberBrowsingHistoryRef = ref<InstanceType<typeof MemberBrowsingHistory>>()
|
||||||
const handleChange = (conversation: KeFuConversationRespVO) => {
|
const memberBrowsingHistorysRef = ref<InstanceType<typeof MemberBrowsingHistorys>>()
|
||||||
conversations.value = conversation
|
const handleChange = async (conversation: KeFuConversationRespVO) => {
|
||||||
chick.value = '2'
|
conversations.value = conversation
|
||||||
userId.value = conversation.userId
|
// chick.value = '1'
|
||||||
|
clickUser.value = 2
|
||||||
|
userId.value = conversation.userId
|
||||||
|
userInfo()
|
||||||
keFuChatBoxRef.value?.getNewMessageList(conversation)
|
keFuChatBoxRef.value?.getNewMessageList(conversation)
|
||||||
memberBrowsingHistoryRef.value?.initHistory(conversation)
|
memberBrowsingHistoryRef.value?.initHistory(conversation)
|
||||||
|
memberBrowsingHistorysRef.value?.initHistory(conversation)
|
||||||
}
|
}
|
||||||
|
|
||||||
const out = () =>{
|
const out = async () => {
|
||||||
window.close();
|
// await SupportStaffApi.updateLineStatus(kefuId, 2)
|
||||||
// window.location.href = '/kefu/support-staff';
|
window.close();
|
||||||
|
// window.location.href = '/kefu/support-staff';
|
||||||
|
}
|
||||||
|
|
||||||
|
const getBySenderIdStat = async () => {
|
||||||
|
stat.value = await KeFuMessageApi.getBySenderIdStat(userId.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const chick = ref('1')
|
||||||
|
const userInfo = async () => {
|
||||||
|
chick.value = '1'
|
||||||
|
if(clickUser.value == 2){
|
||||||
|
user.value = await UserApi.getUserInfo(userId.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
const zuoji = () => {
|
||||||
|
chick.value = '2'
|
||||||
|
// keFuChatBoxRef.value?.getNewMessageList(conversations.value)
|
||||||
|
memberBrowsingHistoryRef.value?.initHistory(conversations.value)
|
||||||
|
}
|
||||||
|
const jiaoyi = () => {
|
||||||
|
chick.value = '3'
|
||||||
|
// keFuChatBoxRef.value?.getNewMessageList(conversations.value)
|
||||||
|
// memberBrowsingHistoryRef.value?.initHistory(conversations.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const chick = ref('2')
|
const findNameInput = () => {
|
||||||
const userInfo = async () =>{
|
keFuConversationRef.value?.getConversationList(findName.value)
|
||||||
chick.value = '1'
|
|
||||||
user.value = await UserApi.getUserInfo(userId.value)
|
|
||||||
}
|
|
||||||
const zuoji = () =>{
|
|
||||||
chick.value = '2'
|
|
||||||
// keFuChatBoxRef.value?.getNewMessageList(conversations.value)
|
|
||||||
memberBrowsingHistoryRef.value?.initHistory(conversations.value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 初始化 */
|
/** 初始化 */
|
||||||
@ -301,21 +375,22 @@
|
|||||||
getConversationList()
|
getConversationList()
|
||||||
// 打开 websocket 连接
|
// 打开 websocket 连接
|
||||||
open()
|
open()
|
||||||
console.log('WebSocket 已初始化');
|
console.log('WebSocket 已初始化');
|
||||||
})
|
})
|
||||||
|
|
||||||
/** 销毁 */
|
// /** 销毁 */
|
||||||
onBeforeUnmount(() => {
|
// onBeforeUnmount(() => {
|
||||||
// 关闭 websocket 连接
|
// // 关闭 websocket 连接
|
||||||
close()
|
// close()
|
||||||
console.log('WebSocket 已关闭');
|
// console.log('WebSocket 已关闭');
|
||||||
})
|
// })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.kefu {
|
.kefu {
|
||||||
height: calc(100vh - 165px);
|
height: calc(100vh - 165px);
|
||||||
overflow: auto; /* 确保内容可滚动 */
|
overflow: auto;
|
||||||
|
/* 确保内容可滚动 */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,7 +246,6 @@ const handleDelete = async (id: number) => {
|
|||||||
}
|
}
|
||||||
/** 客服进入工作台 */
|
/** 客服进入工作台 */
|
||||||
const handleEnterConsole = async (id: number,name: string,pic: string) => {
|
const handleEnterConsole = async (id: number,name: string,pic: string) => {
|
||||||
await SupportStaffApi.updateLineStatus(JSON.stringify(id),1)
|
|
||||||
setStaffToken(id);
|
setStaffToken(id);
|
||||||
const url = `${window.location.origin}/kefu/kefu?id=${encodeURIComponent(id)}&name=${encodeURIComponent(name)}&pic=${encodeURIComponent(pic)}`;
|
const url = `${window.location.origin}/kefu/kefu?id=${encodeURIComponent(id)}&name=${encodeURIComponent(name)}&pic=${encodeURIComponent(pic)}`;
|
||||||
window.open(url, '_blank');
|
window.open(url, '_blank');
|
||||||
|
@ -41,10 +41,7 @@ public abstract class AbstractWebSocketMessageSender implements WebSocketMessage
|
|||||||
send(sessionId, (Integer) null,null, messageType, messageContent);
|
send(sessionId, (Integer) null,null, messageType, messageContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void send(String sessionId, Long userId, Integer userType,String messageType, String messageContent) {
|
|
||||||
send(sessionId, userType,userId, messageType, messageContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送消息
|
* 发送消息
|
||||||
|
@ -38,9 +38,6 @@ public interface WebSocketMessageSender {
|
|||||||
void send(String sessionId, String messageType, String messageContent);
|
void send(String sessionId, String messageType, String messageContent);
|
||||||
|
|
||||||
|
|
||||||
void send(String sessionId, Long userId, Integer userType,String messageType, String messageContent);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
default void sendObject(Integer userType, Long userId, String messageType, Object messageContent) {
|
default void sendObject(Integer userType, Long userId, String messageType, Object messageContent) {
|
||||||
send(userType, userId, messageType, JsonUtils.toJsonString(messageContent));
|
send(userType, userId, messageType, JsonUtils.toJsonString(messageContent));
|
||||||
@ -54,8 +51,6 @@ public interface WebSocketMessageSender {
|
|||||||
send(sessionId, messageType, JsonUtils.toJsonString(messageContent));
|
send(sessionId, messageType, JsonUtils.toJsonString(messageContent));
|
||||||
}
|
}
|
||||||
|
|
||||||
default void sendObject(String sessionId, Long userId, Integer userType,String messageType, String messageContent) {
|
|
||||||
send(sessionId,userId,userType, messageType, JsonUtils.toJsonString(messageContent));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -48,10 +48,7 @@ public class RedisWebSocketMessageSender extends AbstractWebSocketMessageSender
|
|||||||
sendRedisMessage(sessionId, null, null, messageType, messageContent);
|
sendRedisMessage(sessionId, null, null, messageType, messageContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void send(String sessionId, Long userId, Integer userType,String messageType, String messageContent) {
|
|
||||||
sendRedisMessage(sessionId, userId, userType, messageType, messageContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过 Redis 广播消息
|
* 通过 Redis 广播消息
|
||||||
@ -65,24 +62,6 @@ public class RedisWebSocketMessageSender extends AbstractWebSocketMessageSender
|
|||||||
private void sendRedisMessage(String sessionId, Long userId, Integer userType,
|
private void sendRedisMessage(String sessionId, Long userId, Integer userType,
|
||||||
String messageType, String messageContent) {
|
String messageType, String messageContent) {
|
||||||
|
|
||||||
|
|
||||||
if (userType == 2){
|
|
||||||
ConcurrentMap<String, WebSocketSession> stringWebSocketSessionConcurrentMap = webSocketSessionManager.idSessions();
|
|
||||||
for (Map.Entry<String, WebSocketSession> entry : stringWebSocketSessionConcurrentMap.entrySet()) {
|
|
||||||
String key = entry.getKey();
|
|
||||||
WebSocketSession session = entry.getValue();
|
|
||||||
|
|
||||||
Map<String, Object> attributes = session.getAttributes();
|
|
||||||
LoginUser loginUser = (LoginUser) attributes.get("LOGIN_USER");
|
|
||||||
if(loginUser.getId() == 1 && loginUser.getUserType() == 2){
|
|
||||||
sessionId = key;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// 处理每个 WebSocketSession
|
|
||||||
System.out.println("Key: " + key + ", Session: " + session);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RedisWebSocketMessage mqMessage = new RedisWebSocketMessage()
|
RedisWebSocketMessage mqMessage = new RedisWebSocketMessage()
|
||||||
.setSessionId(sessionId).setUserId(userId).setUserType(userType)
|
.setSessionId(sessionId).setUserId(userId).setUserType(userType)
|
||||||
.setMessageType(messageType).setMessageContent(messageContent);
|
.setMessageType(messageType).setMessageContent(messageContent);
|
||||||
|
@ -40,13 +40,12 @@ public interface WebSocketSenderApi {
|
|||||||
void send(String sessionId, String messageType, String messageContent);
|
void send(String sessionId, String messageType, String messageContent);
|
||||||
|
|
||||||
|
|
||||||
void send(String sessionId, Long userId, Integer userType,String messageType, String messageContent);
|
|
||||||
|
|
||||||
default void sendObject(Integer userType, Long userId, String messageType, Object messageContent) {
|
default void sendObject(Integer userType, Long userId, String messageType, Object messageContent) {
|
||||||
send(userType, userId, messageType, JsonUtils.toJsonString(messageContent));
|
send(userType, userId, messageType, JsonUtils.toJsonString(messageContent));
|
||||||
}
|
}
|
||||||
|
|
||||||
default void sendObject(Integer userType, String messageType, Object messageContent) { //用户发送消息
|
default void sendObject(Integer userType, String messageType, Object messageContent) {
|
||||||
send(userType, messageType, JsonUtils.toJsonString(messageContent));
|
send(userType, messageType, JsonUtils.toJsonString(messageContent));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,8 +53,5 @@ public interface WebSocketSenderApi {
|
|||||||
send(sessionId, messageType, JsonUtils.toJsonString(messageContent));
|
send(sessionId, messageType, JsonUtils.toJsonString(messageContent));
|
||||||
}
|
}
|
||||||
|
|
||||||
default void sendObject(String sessionId, Long userId, Integer userType,String messageType, Object messageContent) {
|
|
||||||
send(sessionId,userId,userType, messageType, JsonUtils.toJsonString(messageContent));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,9 +31,6 @@ public class WebSocketSenderApiImpl implements WebSocketSenderApi {
|
|||||||
webSocketMessageSender.send(sessionId, messageType, messageContent);
|
webSocketMessageSender.send(sessionId, messageType, messageContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void send(String sessionId, Long userId, Integer userType, String messageType, String messageContent) {
|
|
||||||
webSocketMessageSender.send(sessionId, userId,userType,messageType, messageContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,22 @@ public class ProductBrowseHistoryController {
|
|||||||
productBrowseHistoryRespVO.setIntroduction(productSpuDO.getIntroduction());
|
productBrowseHistoryRespVO.setIntroduction(productSpuDO.getIntroduction());
|
||||||
resultList.add(productBrowseHistoryRespVO);
|
resultList.add(productBrowseHistoryRespVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (pageReqVO.getGoodsName() != null){
|
||||||
|
List<ProductBrowseHistoryRespVO> results = new ArrayList<>();
|
||||||
|
for (ProductBrowseHistoryRespVO productBrowseHistoryRespVO : resultList) {
|
||||||
|
if (productBrowseHistoryRespVO.getSpuName().toLowerCase().contains(pageReqVO.getGoodsName().toLowerCase())) {
|
||||||
|
results.add(productBrowseHistoryRespVO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PageResult<ProductBrowseHistoryRespVO> result = new PageResult<>();
|
||||||
|
result.setTotal((long)results.size());
|
||||||
|
result.setList(results);
|
||||||
|
return success(result);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
PageResult<ProductBrowseHistoryRespVO> result = new PageResult<>();
|
PageResult<ProductBrowseHistoryRespVO> result = new PageResult<>();
|
||||||
result.setTotal(pageResult.getTotal());
|
result.setTotal(pageResult.getTotal());
|
||||||
result.setList(resultList);
|
result.setList(resultList);
|
||||||
|
@ -30,4 +30,6 @@ public class ProductBrowseHistoryPageReqVO extends SortablePageParam {
|
|||||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||||
private LocalDateTime[] createTime;
|
private LocalDateTime[] createTime;
|
||||||
|
|
||||||
|
private String goodsName;
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,104 @@
|
|||||||
|
package cn.iocoder.yudao.module.promotion.controller.admin.advertising;
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
|
||||||
|
import javax.validation.constraints.*;
|
||||||
|
import javax.validation.*;
|
||||||
|
import javax.servlet.http.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||||
|
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.advertising.vo.*;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.advertising.AdvertisingDO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.service.advertising.AdvertisingService;
|
||||||
|
|
||||||
|
@Tag(name = "管理后台 - 开屏广告")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/promotion/advertising")
|
||||||
|
@Validated
|
||||||
|
public class AdvertisingController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AdvertisingService advertisingService;
|
||||||
|
|
||||||
|
@PostMapping("/create")
|
||||||
|
@Operation(summary = "创建开屏广告")
|
||||||
|
@PreAuthorize("@ss.hasPermission('promotion:advertising:create')")
|
||||||
|
public CommonResult<Long> createAdvertising(@Valid @RequestBody AdvertisingSaveReqVO createReqVO) {
|
||||||
|
return success(advertisingService.createAdvertising(createReqVO));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/update")
|
||||||
|
@Operation(summary = "更新开屏广告")
|
||||||
|
@PreAuthorize("@ss.hasPermission('promotion:advertising:update')")
|
||||||
|
public CommonResult<Boolean> updateAdvertising(@Valid @RequestBody AdvertisingSaveReqVO updateReqVO) {
|
||||||
|
advertisingService.updateAdvertising(updateReqVO);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/delete")
|
||||||
|
@Operation(summary = "删除开屏广告")
|
||||||
|
@Parameter(name = "id", description = "编号", required = true)
|
||||||
|
@PreAuthorize("@ss.hasPermission('promotion:advertising:delete')")
|
||||||
|
public CommonResult<Boolean> deleteAdvertising(@RequestParam("id") Long id) {
|
||||||
|
advertisingService.deleteAdvertising(id);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/page")
|
||||||
|
@Operation(summary = "获得开屏广告分页")
|
||||||
|
@PreAuthorize("@ss.hasPermission('promotion:advertising:query')")
|
||||||
|
public CommonResult<PageResult<AdvertisingRespVO>> getAdvertisingPage(@Valid AdvertisingPageReqVO pageReqVO) {
|
||||||
|
PageResult<AdvertisingDO> pageResult = advertisingService.getAdvertisingPage(pageReqVO);
|
||||||
|
return success(BeanUtils.toBean(pageResult, AdvertisingRespVO.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/export-excel")
|
||||||
|
@Operation(summary = "导出开屏广告 Excel")
|
||||||
|
@PreAuthorize("@ss.hasPermission('promotion:advertising:export')")
|
||||||
|
@ApiAccessLog(operateType = EXPORT)
|
||||||
|
public void exportAdvertisingExcel(@Valid AdvertisingPageReqVO pageReqVO,
|
||||||
|
HttpServletResponse response) throws IOException {
|
||||||
|
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||||
|
List<AdvertisingDO> list = advertisingService.getAdvertisingPage(pageReqVO).getList();
|
||||||
|
// 导出 Excel
|
||||||
|
ExcelUtils.write(response, "开屏广告.xls", "数据", AdvertisingRespVO.class,
|
||||||
|
BeanUtils.toBean(list, AdvertisingRespVO.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//添加修改开屏广告
|
||||||
|
@PostMapping("/saveAdvertising")
|
||||||
|
public CommonResult<Long> saveAdvertising(@Valid @RequestBody AdvertisingSaveReqVO createReqVO) {
|
||||||
|
return success(advertisingService.saveAdvertising(createReqVO));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/getAdvertising")
|
||||||
|
public CommonResult<AdvertisingRespVO> getAdvertising() {
|
||||||
|
AdvertisingDO advertising = advertisingService.getAdvertising();
|
||||||
|
return success(BeanUtils.toBean(advertising, AdvertisingRespVO.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package cn.iocoder.yudao.module.promotion.controller.admin.advertising.vo;
|
||||||
|
|
||||||
|
import lombok.*;
|
||||||
|
import java.util.*;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - 开屏广告分页 Request VO")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class AdvertisingPageReqVO extends PageParam {
|
||||||
|
|
||||||
|
@Schema(description = "广告状态", example = "2")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@Schema(description = "广告时间(秒)")
|
||||||
|
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||||
|
private Integer[] time;
|
||||||
|
|
||||||
|
@Schema(description = "广告属性")
|
||||||
|
private String property;
|
||||||
|
|
||||||
|
@Schema(description = "创建时间")
|
||||||
|
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||||
|
private LocalDateTime[] createTime;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package cn.iocoder.yudao.module.promotion.controller.admin.advertising.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.*;
|
||||||
|
import java.util.*;
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import com.alibaba.excel.annotation.*;
|
||||||
|
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
|
||||||
|
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - 开屏广告 Response VO")
|
||||||
|
@Data
|
||||||
|
@ExcelIgnoreUnannotated
|
||||||
|
public class AdvertisingRespVO {
|
||||||
|
|
||||||
|
@Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "684")
|
||||||
|
@ExcelProperty("id")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "广告状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||||
|
@ExcelProperty(value = "广告状态", converter = DictConvert.class)
|
||||||
|
@DictFormat("promotion_diy_advertising") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@Schema(description = "广告时间(秒)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
@ExcelProperty("广告时间(秒)")
|
||||||
|
private Integer time;
|
||||||
|
|
||||||
|
@Schema(description = "广告属性", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
@ExcelProperty("广告属性")
|
||||||
|
private String property;
|
||||||
|
|
||||||
|
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
@ExcelProperty("创建时间")
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
private List<Object> picData;
|
||||||
|
|
||||||
|
private Boolean stat;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package cn.iocoder.yudao.module.promotion.controller.admin.advertising.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.*;
|
||||||
|
import java.util.*;
|
||||||
|
import javax.validation.constraints.*;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - 开屏广告新增/修改 Request VO")
|
||||||
|
@Data
|
||||||
|
public class AdvertisingSaveReqVO {
|
||||||
|
|
||||||
|
@Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "684")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "广告状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@Schema(description = "广告时间(秒)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
@NotNull(message = "广告时间(秒)不能为空")
|
||||||
|
private Integer time;
|
||||||
|
|
||||||
|
@Schema(description = "广告属性", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private String property;
|
||||||
|
|
||||||
|
@Schema(description = "图片添加不能为空", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private List<Object> picData;
|
||||||
|
|
||||||
|
private Boolean stat;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -16,7 +16,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
|
|||||||
public class KeFuConfigurationPageReqVO extends PageParam {
|
public class KeFuConfigurationPageReqVO extends PageParam {
|
||||||
|
|
||||||
@Schema(description = "客服类型", example = "1")
|
@Schema(description = "客服类型", example = "1")
|
||||||
private String type;
|
private Integer type;
|
||||||
|
|
||||||
@Schema(description = "客服反馈")
|
@Schema(description = "客服反馈")
|
||||||
private String feedback;
|
private String feedback;
|
||||||
|
@ -18,7 +18,7 @@ public class KeFuConfigurationRespVO {
|
|||||||
|
|
||||||
@Schema(description = "客服类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
@Schema(description = "客服类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
@ExcelProperty("客服类型")
|
@ExcelProperty("客服类型")
|
||||||
private String type;
|
private Integer type;
|
||||||
|
|
||||||
@Schema(description = "客服反馈")
|
@Schema(description = "客服反馈")
|
||||||
@ExcelProperty("客服反馈")
|
@ExcelProperty("客服反馈")
|
||||||
|
@ -14,7 +14,7 @@ public class KeFuConfigurationSaveReqVO {
|
|||||||
|
|
||||||
@Schema(description = "客服类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
@Schema(description = "客服类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
@NotEmpty(message = "客服类型不能为空")
|
@NotEmpty(message = "客服类型不能为空")
|
||||||
private String type;
|
private Integer type;
|
||||||
|
|
||||||
@Schema(description = "客服反馈")
|
@Schema(description = "客服反馈")
|
||||||
private String feedback;
|
private String feedback;
|
||||||
|
@ -20,6 +20,7 @@ import javax.validation.Valid;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||||
@ -56,7 +57,7 @@ public class KeFuConversationController {
|
|||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
@Operation(summary = "获得客服会话列表")
|
@Operation(summary = "获得客服会话列表")
|
||||||
@PreAuthorize("@ss.hasPermission('promotion:kefu-conversation:query')")
|
@PreAuthorize("@ss.hasPermission('promotion:kefu-conversation:query')")
|
||||||
public CommonResult<List<KeFuConversationRespVO>> getConversationList(@RequestParam(required = false, value = "kefuId") Long kefuId) {
|
public CommonResult<List<KeFuConversationRespVO>> getConversationList(@RequestParam(required = false, value = "kefuId") Long kefuId,String name) {
|
||||||
// 如果会话列表中的kefuId为null,则转接给当前kefuId(处理小程序新会话)
|
// 如果会话列表中的kefuId为null,则转接给当前kefuId(处理小程序新会话)
|
||||||
if (kefuId != null) {
|
if (kefuId != null) {
|
||||||
List<KeFuConversationDO> updateList = new ArrayList<>();
|
List<KeFuConversationDO> updateList = new ArrayList<>();
|
||||||
@ -80,8 +81,20 @@ public class KeFuConversationController {
|
|||||||
Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(convertSet(respList, KeFuConversationRespVO::getUserId));
|
Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(convertSet(respList, KeFuConversationRespVO::getUserId));
|
||||||
respList.forEach(item -> findAndThen(userMap, item.getUserId(),
|
respList.forEach(item -> findAndThen(userMap, item.getUserId(),
|
||||||
memberUser -> item.setUserAvatar(memberUser.getAvatar()).setUserNickname(memberUser.getNickname())));
|
memberUser -> item.setUserAvatar(memberUser.getAvatar()).setUserNickname(memberUser.getNickname())));
|
||||||
return success(respList);
|
|
||||||
|
|
||||||
|
List<KeFuConversationRespVO> result = new ArrayList<>();
|
||||||
|
for (KeFuConversationRespVO keFuConversationRespVO : respList) {
|
||||||
|
if (keFuConversationRespVO.getUserNickname().toLowerCase().contains(name.toLowerCase())) {
|
||||||
|
result.add(keFuConversationRespVO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return success(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Operation(summary = "转接会话给指定客服")
|
@Operation(summary = "转接会话给指定客服")
|
||||||
@GetMapping("/transfer/{id}/{kefuId}")
|
@GetMapping("/transfer/{id}/{kefuId}")
|
||||||
public CommonResult<String> transferConversation(@PathVariable("id") Long id, @PathVariable("kefuId") Long kefuId) {
|
public CommonResult<String> transferConversation(@PathVariable("id") Long id, @PathVariable("kefuId") Long kefuId) {
|
||||||
|
@ -47,6 +47,11 @@ public class KeFuMessageController {
|
|||||||
return success(messageService.sendKefuMessage(sendReqVO));
|
return success(messageService.sendKefuMessage(sendReqVO));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/sendMess")
|
||||||
|
public String sendMess(String mess){
|
||||||
|
return messageService.sendMess(mess);
|
||||||
|
}
|
||||||
|
|
||||||
@PutMapping("/update-read-status")
|
@PutMapping("/update-read-status")
|
||||||
@Operation(summary = "更新客服消息已读状态")
|
@Operation(summary = "更新客服消息已读状态")
|
||||||
@Parameter(name = "conversationId", description = "会话编号", required = true)
|
@Parameter(name = "conversationId", description = "会话编号", required = true)
|
||||||
@ -72,4 +77,11 @@ public class KeFuMessageController {
|
|||||||
return success(result);
|
return success(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/getBySenderIdStat")
|
||||||
|
@Operation(summary = "发送客服消息")
|
||||||
|
public CommonResult<Boolean> getLatestMessageBySenderId(Integer senderId) {
|
||||||
|
return success(messageService.getLatestMessageBySenderId(senderId));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package cn.iocoder.yudao.module.promotion.controller.app.Advertising;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.advertising.vo.AdvertisingRespVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.advertising.AdvertisingDO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.service.advertising.AdvertisingService;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/promotion/advertising")
|
||||||
|
public class AppAdvertisingController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AdvertisingService advertisingService;
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/getAdvertising")
|
||||||
|
public CommonResult<AdvertisingRespVO> getAdvertising() {
|
||||||
|
AdvertisingDO advertising = advertisingService.getAppAdvertising();
|
||||||
|
return success(BeanUtils.toBean(advertising, AdvertisingRespVO.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
package cn.iocoder.yudao.module.promotion.dal.dataobject.advertising;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开屏广告 DO
|
||||||
|
*
|
||||||
|
* @author 管理员
|
||||||
|
*/
|
||||||
|
@TableName("promotion_diy_template_advertising")
|
||||||
|
@KeySequence("promotion_diy_template_advertising_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class AdvertisingDO extends BaseDO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* id
|
||||||
|
*/
|
||||||
|
@TableId
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 广告状态
|
||||||
|
*
|
||||||
|
* 枚举 {@link TODO promotion_diy_advertising 对应的类}
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
/**
|
||||||
|
* 广告时间(秒)
|
||||||
|
*/
|
||||||
|
private Integer time;
|
||||||
|
/**
|
||||||
|
* 广告属性
|
||||||
|
*/
|
||||||
|
private String property;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图片数据
|
||||||
|
*/
|
||||||
|
@TableField(exist = false)
|
||||||
|
private List<Object> picData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开屏状态
|
||||||
|
*/
|
||||||
|
@TableField(exist = false)
|
||||||
|
private Boolean stat;
|
||||||
|
|
||||||
|
}
|
@ -30,7 +30,7 @@ public class KeFuConfigurationDO extends BaseDO {
|
|||||||
/**
|
/**
|
||||||
* 客服类型
|
* 客服类型
|
||||||
*/
|
*/
|
||||||
private String type;
|
private Integer type;
|
||||||
/**
|
/**
|
||||||
* 客服反馈
|
* 客服反馈
|
||||||
*/
|
*/
|
||||||
|
@ -3,12 +3,11 @@ package cn.iocoder.yudao.module.promotion.dal.dataobject.kefu;
|
|||||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||||
import cn.iocoder.yudao.module.promotion.enums.kefu.KeFuMessageContentTypeEnum;
|
import cn.iocoder.yudao.module.promotion.enums.kefu.KeFuMessageContentTypeEnum;
|
||||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 客服消息 DO
|
* 客服消息 DO
|
||||||
*
|
*
|
||||||
@ -86,4 +85,7 @@ public class KeFuMessageDO extends BaseDO {
|
|||||||
|
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
private String kefuName;
|
private String kefuName;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private Integer stat;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
package cn.iocoder.yudao.module.promotion.dal.mysql.advertising;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.advertising.AdvertisingDO;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.advertising.vo.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开屏广告 Mapper
|
||||||
|
*
|
||||||
|
* @author 管理员
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface AdvertisingMapper extends BaseMapperX<AdvertisingDO> {
|
||||||
|
|
||||||
|
default PageResult<AdvertisingDO> selectPage(AdvertisingPageReqVO reqVO) {
|
||||||
|
return selectPage(reqVO, new LambdaQueryWrapperX<AdvertisingDO>()
|
||||||
|
.eqIfPresent(AdvertisingDO::getStatus, reqVO.getStatus())
|
||||||
|
.betweenIfPresent(AdvertisingDO::getTime, reqVO.getTime())
|
||||||
|
.eqIfPresent(AdvertisingDO::getProperty, reqVO.getProperty())
|
||||||
|
.betweenIfPresent(AdvertisingDO::getCreateTime, reqVO.getCreateTime())
|
||||||
|
.orderByDesc(AdvertisingDO::getId));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -51,4 +51,7 @@ public interface KeFuMessageMapper extends BaseMapperX<KeFuMessageDO> {
|
|||||||
@Select(" SELECT avatar FROM system_users where id = #{id} ")
|
@Select(" SELECT avatar FROM system_users where id = #{id} ")
|
||||||
String findSystemUserAvatar(Long id);
|
String findSystemUserAvatar(Long id);
|
||||||
|
|
||||||
|
@Select("SELECT read_status as stat FROM promotion_kefu_message WHERE sender_id = #{senderId} ORDER BY create_time DESC LIMIT 1")
|
||||||
|
String getLatestMessageBySenderId(Integer senderId);
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
package cn.iocoder.yudao.module.promotion.service.advertising;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import javax.validation.*;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.advertising.vo.*;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.advertising.AdvertisingDO;
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开屏广告 Service 接口
|
||||||
|
*
|
||||||
|
* @author 管理员
|
||||||
|
*/
|
||||||
|
public interface AdvertisingService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建开屏广告
|
||||||
|
*
|
||||||
|
* @param createReqVO 创建信息
|
||||||
|
* @return 编号
|
||||||
|
*/
|
||||||
|
Long createAdvertising(@Valid AdvertisingSaveReqVO createReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新开屏广告
|
||||||
|
*
|
||||||
|
* @param updateReqVO 更新信息
|
||||||
|
*/
|
||||||
|
void updateAdvertising(@Valid AdvertisingSaveReqVO updateReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除开屏广告
|
||||||
|
*
|
||||||
|
* @param id 编号
|
||||||
|
*/
|
||||||
|
void deleteAdvertising(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得开屏广告
|
||||||
|
*
|
||||||
|
* @return 开屏广告
|
||||||
|
*/
|
||||||
|
AdvertisingDO getAdvertising();
|
||||||
|
|
||||||
|
AdvertisingDO getAppAdvertising();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得开屏广告分页
|
||||||
|
*
|
||||||
|
* @param pageReqVO 分页查询
|
||||||
|
* @return 开屏广告分页
|
||||||
|
*/
|
||||||
|
PageResult<AdvertisingDO> getAdvertisingPage(AdvertisingPageReqVO pageReqVO);
|
||||||
|
|
||||||
|
|
||||||
|
Long saveAdvertising(@Valid AdvertisingSaveReqVO createReqVO);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,114 @@
|
|||||||
|
package cn.iocoder.yudao.module.promotion.service.advertising;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.validation.Valid;
|
||||||
|
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.advertising.vo.*;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.advertising.AdvertisingDO;
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.mysql.advertising.AdvertisingMapper;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开屏广告 Service 实现类
|
||||||
|
*
|
||||||
|
* @author 管理员
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Validated
|
||||||
|
public class AdvertisingServiceImpl implements AdvertisingService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AdvertisingMapper advertisingMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long createAdvertising(AdvertisingSaveReqVO createReqVO) {
|
||||||
|
// 插入
|
||||||
|
AdvertisingDO advertising = BeanUtils.toBean(createReqVO, AdvertisingDO.class);
|
||||||
|
advertisingMapper.insert(advertising);
|
||||||
|
// 返回
|
||||||
|
return advertising.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateAdvertising(AdvertisingSaveReqVO updateReqVO) {
|
||||||
|
// 校验存在
|
||||||
|
validateAdvertisingExists(updateReqVO.getId());
|
||||||
|
// 更新
|
||||||
|
AdvertisingDO updateObj = BeanUtils.toBean(updateReqVO, AdvertisingDO.class);
|
||||||
|
advertisingMapper.updateById(updateObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteAdvertising(Long id) {
|
||||||
|
// 校验存在
|
||||||
|
validateAdvertisingExists(id);
|
||||||
|
// 删除
|
||||||
|
advertisingMapper.deleteById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateAdvertisingExists(Long id) {
|
||||||
|
if (advertisingMapper.selectById(id) == null) {
|
||||||
|
throw exception(ADVERTISING_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AdvertisingDO getAdvertising() {
|
||||||
|
List<AdvertisingDO> advertisingDOS = advertisingMapper.selectList();
|
||||||
|
if (advertisingDOS.isEmpty()){
|
||||||
|
return new AdvertisingDO();
|
||||||
|
}
|
||||||
|
AdvertisingDO advertisingDO = advertisingDOS.get(0);
|
||||||
|
advertisingDO.setPicData(JSON.parseArray(advertisingDO.getProperty()));
|
||||||
|
if (advertisingDO.getStatus() == 1){
|
||||||
|
advertisingDO.setStat(true);
|
||||||
|
}
|
||||||
|
if (advertisingDO.getStatus() == 2){
|
||||||
|
advertisingDO.setStat(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return advertisingDO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AdvertisingDO getAppAdvertising() {
|
||||||
|
List<AdvertisingDO> advertisingDOS = advertisingMapper.selectList();
|
||||||
|
return advertisingDOS.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageResult<AdvertisingDO> getAdvertisingPage(AdvertisingPageReqVO pageReqVO) {
|
||||||
|
return advertisingMapper.selectPage(pageReqVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long saveAdvertising(@Valid AdvertisingSaveReqVO createReqVO) {
|
||||||
|
if (createReqVO.getStat()){
|
||||||
|
createReqVO.setStatus(1);
|
||||||
|
}else {
|
||||||
|
createReqVO.setStatus(2);
|
||||||
|
}
|
||||||
|
List<AdvertisingDO> advertisingDOS = advertisingMapper.selectList();
|
||||||
|
if (advertisingDOS.isEmpty()){
|
||||||
|
createReqVO.setProperty(JSON.toJSONString(createReqVO.getPicData()));
|
||||||
|
AdvertisingDO advertising = BeanUtils.toBean(createReqVO, AdvertisingDO.class);
|
||||||
|
return (long) advertisingMapper.insert(advertising);
|
||||||
|
}
|
||||||
|
AdvertisingDO advertisingDO = advertisingDOS.get(0);
|
||||||
|
advertisingDO.setProperty(JSON.toJSONString(createReqVO.getPicData()));
|
||||||
|
return (long)advertisingMapper.updateById(advertisingDO);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -40,6 +40,7 @@ public class KeFuConfigurationServiceImpl implements KeFuConfigurationService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateKeFuConfiguration(KeFuConfigurationSaveReqVO updateReqVO) {
|
public void updateKeFuConfiguration(KeFuConfigurationSaveReqVO updateReqVO) {
|
||||||
|
|
||||||
// 校验存在
|
// 校验存在
|
||||||
validateKeFuConfigurationExists(updateReqVO.getId());
|
validateKeFuConfigurationExists(updateReqVO.getId());
|
||||||
// 更新
|
// 更新
|
||||||
|
@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuM
|
|||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 客服消息 Service 接口
|
* 客服消息 Service 接口
|
||||||
@ -24,6 +25,8 @@ public interface KeFuMessageService {
|
|||||||
*/
|
*/
|
||||||
Long sendKefuMessage(@Valid KeFuMessageSendReqVO sendReqVO);
|
Long sendKefuMessage(@Valid KeFuMessageSendReqVO sendReqVO);
|
||||||
|
|
||||||
|
String sendMess(String mess);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 【会员】发送客服消息
|
* 【会员】发送客服消息
|
||||||
*
|
*
|
||||||
@ -63,4 +66,11 @@ public interface KeFuMessageService {
|
|||||||
|
|
||||||
String findSystemUserAvatar(Long id);
|
String findSystemUserAvatar(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 senderId 查询创建时间最近的一条数据
|
||||||
|
* @param senderId 发送人编号
|
||||||
|
* @return Optional<KeFuMessageDO> 返回最近的一条消息
|
||||||
|
*/
|
||||||
|
Boolean getLatestMessageBySenderId(Integer senderId);
|
||||||
|
|
||||||
}
|
}
|
@ -15,13 +15,20 @@ import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMe
|
|||||||
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageSendReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageSendReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessagePageReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessagePageReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessageSendReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessageSendReqVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.configuration.KeFuConfigurationDO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuConversationDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuConversationDO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.supportstaff.SupportStaffDO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.mysql.configuration.KeFuConfigurationMapper;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.mysql.kefu.KeFuConversationMapper;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.mysql.kefu.KeFuMessageMapper;
|
import cn.iocoder.yudao.module.promotion.dal.mysql.kefu.KeFuMessageMapper;
|
||||||
|
import cn.iocoder.yudao.module.promotion.dal.mysql.supportstaff.SupportStaffMapper;
|
||||||
|
import cn.iocoder.yudao.module.promotion.enums.kefu.KeFuMessageContentTypeEnum;
|
||||||
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
|
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
|
||||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyMessageDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyMessageDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.mysql.notify.NotifyMessageMapper;
|
import cn.iocoder.yudao.module.system.dal.mysql.notify.NotifyMessageMapper;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@ -30,6 +37,7 @@ import org.springframework.validation.annotation.Validated;
|
|||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
@ -58,9 +66,15 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
|
|||||||
@Resource
|
@Resource
|
||||||
private WebSocketSenderApi webSocketSenderApi;
|
private WebSocketSenderApi webSocketSenderApi;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SupportStaffMapper supportStaffMapper;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private NotifyMessageMapper notifyMessageMapper;
|
private NotifyMessageMapper notifyMessageMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private KeFuConfigurationMapper keFuConfigurationMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public Long sendKefuMessage(KeFuMessageSendReqVO sendReqVO) { //客服发消息
|
public Long sendKefuMessage(KeFuMessageSendReqVO sendReqVO) { //客服发消息
|
||||||
@ -83,6 +97,12 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
|
|||||||
return kefuMessage.getId();
|
return kefuMessage.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String sendMess(String mess) {
|
||||||
|
webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), 1L, KEFU_MESSAGE_TYPE, mess);
|
||||||
|
return "发送成功";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long sendKefuMessage(AppKeFuMessageSendReqVO sendReqVO) { //用户发消息
|
public Long sendKefuMessage(AppKeFuMessageSendReqVO sendReqVO) { //用户发消息
|
||||||
// 1.1 设置会话编号
|
// 1.1 设置会话编号
|
||||||
@ -96,11 +116,33 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
|
|||||||
// 2. 更新会话消息冗余
|
// 2. 更新会话消息冗余
|
||||||
conversationService.updateConversationLastMessage(kefuMessage);
|
conversationService.updateConversationLastMessage(kefuMessage);
|
||||||
|
|
||||||
getSelf().sendAsyncMessageToMembers(conversation.getKefuId(), KEFU_MESSAGE_TYPE, kefuMessage);
|
//客服实时接收消息
|
||||||
|
// getSelf().sendAsyncMessageToMembers(conversation.getKefuId(), KEFU_MESSAGE_TYPE, kefuMessage);
|
||||||
|
|
||||||
|
//判断客服是否在线,自动回复
|
||||||
|
SupportStaffDO supportStaffDO = supportStaffMapper.selectOne("id", conversation.getKefuId());
|
||||||
|
if (supportStaffDO.getLineStatus() == 2){ //离线
|
||||||
|
KeFuConfigurationDO type = keFuConfigurationMapper.selectOne("type", 1);
|
||||||
|
if (type != null){ //是否配置了客服不在线回复
|
||||||
|
if (type.getFeedback() != null){
|
||||||
|
KeFuMessageDO keFuMessageDO = new KeFuMessageDO();
|
||||||
|
keFuMessageDO.setSenderId(conversation.getKefuId());
|
||||||
|
keFuMessageDO.setSenderType(UserTypeEnum.ADMIN.getValue());
|
||||||
|
keFuMessageDO.setContent(type.getFeedback());
|
||||||
|
keFuMessageDO.setContentType(KeFuMessageContentTypeEnum.TEXT.getType());
|
||||||
|
keFuMessageDO.setConversationId(conversation.getId());
|
||||||
|
keFuMessageDO.setReceiverId(conversation.getUserId()).setReceiverType(UserTypeEnum.MEMBER.getValue()); // 设置接收人
|
||||||
|
keFuMessageMapper.insert(keFuMessageDO);
|
||||||
|
// 2.2 更新会话消息冗余
|
||||||
|
conversationService.updateConversationLastMessage(keFuMessageDO);
|
||||||
|
// 3.1 发送消息给用户
|
||||||
|
getSelf().sendAsyncMessageToMember(conversation.getUserId(), KEFU_MESSAGE_TYPE, keFuMessageDO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 3. 通知所有管理员更新对话
|
// 3. 通知所有管理员更新对话
|
||||||
getSelf().sendAsyncMessageToAdmins(KEFU_MESSAGE_TYPE, kefuMessage);
|
getSelf().sendAsyncMessageToAdmin(KEFU_MESSAGE_TYPE, kefuMessage);
|
||||||
return kefuMessage.getId();
|
return kefuMessage.getId();
|
||||||
}
|
}
|
||||||
//添加站内信
|
//添加站内信
|
||||||
@ -169,7 +211,7 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
|
|||||||
|
|
||||||
@Async
|
@Async
|
||||||
public void sendAsyncMessageToMembers(Long userId, String messageType, Object content) {
|
public void sendAsyncMessageToMembers(Long userId, String messageType, Object content) {
|
||||||
webSocketSenderApi.sendObject("",userId, UserTypeEnum.ADMIN.getValue(), messageType, content);
|
webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), userId, messageType, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Async
|
@Async
|
||||||
@ -177,10 +219,6 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
|
|||||||
webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), messageType, content);
|
webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), messageType, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Async
|
|
||||||
public void sendAsyncMessageToAdmins(String messageType, Object content) {
|
|
||||||
webSocketSenderApi.sendObject(UserTypeEnum.MEMBER.getValue(), messageType, content);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageResult<KeFuMessageDO> getKeFuMessagePage(KeFuMessagePageReqVO pageReqVO) {
|
public PageResult<KeFuMessageDO> getKeFuMessagePage(KeFuMessagePageReqVO pageReqVO) {
|
||||||
@ -204,6 +242,15 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
|
|||||||
return keFuMessageMapper.findSystemUserAvatar(id);
|
return keFuMessageMapper.findSystemUserAvatar(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean getLatestMessageBySenderId(Integer senderId) {
|
||||||
|
String stat = keFuMessageMapper.getLatestMessageBySenderId(senderId);
|
||||||
|
if (stat.equals("0")){ //未读:0, 已读:1
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private KeFuMessageServiceImpl getSelf() {
|
private KeFuMessageServiceImpl getSelf() {
|
||||||
return SpringUtil.getBean(getClass());
|
return SpringUtil.getBean(getClass());
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,8 @@ public class TradeOrderController {
|
|||||||
@Operation(summary = "获得交易订单分页")
|
@Operation(summary = "获得交易订单分页")
|
||||||
@PreAuthorize("@ss.hasPermission('trade:order:query')")
|
@PreAuthorize("@ss.hasPermission('trade:order:query')")
|
||||||
public CommonResult<PageResult<TradeOrderPageItemRespVO>> getOrderPage(TradeOrderPageReqVO reqVO) {
|
public CommonResult<PageResult<TradeOrderPageItemRespVO>> getOrderPage(TradeOrderPageReqVO reqVO) {
|
||||||
|
|
||||||
|
|
||||||
// 查询订单
|
// 查询订单
|
||||||
PageResult<TradeOrderDO> pageResult = tradeOrderQueryService.getOrderPage(reqVO);
|
PageResult<TradeOrderDO> pageResult = tradeOrderQueryService.getOrderPage(reqVO);
|
||||||
if (CollUtil.isEmpty(pageResult.getList())) {
|
if (CollUtil.isEmpty(pageResult.getList())) {
|
||||||
|
@ -61,4 +61,7 @@ public class TradeOrderPageReqVO extends PageParam {
|
|||||||
@InEnum(value = TerminalEnum.class, message = "订单来源 {value}")
|
@InEnum(value = TerminalEnum.class, message = "订单来源 {value}")
|
||||||
private Integer terminal;
|
private Integer terminal;
|
||||||
|
|
||||||
|
//客服工作台用户交易订单类型
|
||||||
|
private String activeName;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,14 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
|||||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSalePageReqVO;
|
import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSalePageReqVO;
|
||||||
import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO;
|
import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO;
|
||||||
|
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
||||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface AfterSaleMapper extends BaseMapperX<AfterSaleDO> {
|
public interface AfterSaleMapper extends BaseMapperX<AfterSaleDO> {
|
||||||
@ -48,4 +52,9 @@ public interface AfterSaleMapper extends BaseMapperX<AfterSaleDO> {
|
|||||||
.in(AfterSaleDO::getStatus, statuses));
|
.in(AfterSaleDO::getStatus, statuses));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Select(" SELECT a.* FROM trade_order a " +
|
||||||
|
" INNER JOIN trade_after_sale b on a.id = b.order_id " +
|
||||||
|
" where a.user_id = #{userId} and b.status != 50 LIMIT #{startRow},#{limit} ")
|
||||||
|
List<TradeOrderDO> traderOrderList(@Param("userId") Long userId,@Param("startRow") Integer startRow, @Param("limit") Integer limit);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,9 +12,11 @@ import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReq
|
|||||||
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderSummaryRespVO;
|
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderSummaryRespVO;
|
||||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppPointOrderVO;
|
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppPointOrderVO;
|
||||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO;
|
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO;
|
||||||
|
import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO;
|
||||||
import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
|
import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
|
||||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
||||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
|
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
|
||||||
|
import cn.iocoder.yudao.module.trade.dal.mysql.aftersale.AfterSaleMapper;
|
||||||
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper;
|
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper;
|
||||||
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
|
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
|
||||||
import cn.iocoder.yudao.module.trade.dal.redis.RedisKeyConstants;
|
import cn.iocoder.yudao.module.trade.dal.redis.RedisKeyConstants;
|
||||||
@ -57,6 +59,9 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService {
|
|||||||
@Resource
|
@Resource
|
||||||
private MemberUserApi memberUserApi;
|
private MemberUserApi memberUserApi;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AfterSaleMapper afterSaleMapper;
|
||||||
|
|
||||||
// =================== Order ===================
|
// =================== Order ===================
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -89,6 +94,31 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageResult<TradeOrderDO> getOrderPage(TradeOrderPageReqVO reqVO) {
|
public PageResult<TradeOrderDO> getOrderPage(TradeOrderPageReqVO reqVO) {
|
||||||
|
if(reqVO.getActiveName() != null){
|
||||||
|
if (reqVO.getActiveName().equals("b")){ //未付款
|
||||||
|
reqVO.setStatus(TradeOrderStatusEnum.UNPAID.getStatus());
|
||||||
|
}
|
||||||
|
if (reqVO.getActiveName().equals("c")){ //未发货
|
||||||
|
reqVO.setStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus());
|
||||||
|
}
|
||||||
|
if (reqVO.getActiveName().equals("d")){ //退款中
|
||||||
|
Integer startRow = (reqVO.getPageNo() - 1) * reqVO.getPageSize();
|
||||||
|
List<TradeOrderDO> tradeOrderDOS = afterSaleMapper.traderOrderList(reqVO.getUserId(), startRow, reqVO.getPageSize());
|
||||||
|
for (int i = 0; i < tradeOrderDOS.size(); i++) {
|
||||||
|
tradeOrderDOS.get(i).setStatus(100);
|
||||||
|
}
|
||||||
|
// 根据用户查询条件构建用户编号列表
|
||||||
|
Set<Long> userIds = buildQueryConditionUserIds(reqVO);
|
||||||
|
if (userIds == null) { // 没查询到用户,说明肯定也没他的订单
|
||||||
|
return PageResult.empty();
|
||||||
|
}
|
||||||
|
// 分页查询
|
||||||
|
PageResult<TradeOrderDO> tradeOrderDOPageResult = new PageResult<>();
|
||||||
|
tradeOrderDOPageResult.setList(tradeOrderDOS);
|
||||||
|
tradeOrderDOPageResult.setTotal((long)tradeOrderDOS.size());
|
||||||
|
return tradeOrderDOPageResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
// 根据用户查询条件构建用户编号列表
|
// 根据用户查询条件构建用户编号列表
|
||||||
Set<Long> userIds = buildQueryConditionUserIds(reqVO);
|
Set<Long> userIds = buildQueryConditionUserIds(reqVO);
|
||||||
if (userIds == null) { // 没查询到用户,说明肯定也没他的订单
|
if (userIds == null) { // 没查询到用户,说明肯定也没他的订单
|
||||||
|
Loading…
Reference in New Issue
Block a user