Compare commits
2 Commits
eb477862fc
...
6d8c8b4b83
Author | SHA1 | Date | |
---|---|---|---|
6d8c8b4b83 | |||
85a0e9a9b1 |
@ -0,0 +1,43 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 自动回复 VO
|
||||
export interface AutoResponseVO {
|
||||
id: number // id
|
||||
keyword: string // 关键字
|
||||
type: number // 回复类型,文字消息/0,图片消息/1
|
||||
content: string // 回复内容
|
||||
status: number // 是否开启,开启/1,关闭/0
|
||||
}
|
||||
|
||||
// 自动回复 API
|
||||
export const AutoResponseApi = {
|
||||
// 查询自动回复分页
|
||||
getAutoResponsePage: async (params: any) => {
|
||||
return await request.get({ url: `/promotion/auto-response/page`, params })
|
||||
},
|
||||
|
||||
// 查询自动回复详情
|
||||
getAutoResponse: async (id: number) => {
|
||||
return await request.get({ url: `/promotion/auto-response/get?id=` + id })
|
||||
},
|
||||
|
||||
// 新增自动回复
|
||||
createAutoResponse: async (data: AutoResponseVO) => {
|
||||
return await request.post({ url: `/promotion/auto-response/create`, data })
|
||||
},
|
||||
|
||||
// 修改自动回复
|
||||
updateAutoResponse: async (data: AutoResponseVO) => {
|
||||
return await request.put({ url: `/promotion/auto-response/update`, data })
|
||||
},
|
||||
|
||||
// 删除自动回复
|
||||
deleteAutoResponse: async (id: number) => {
|
||||
return await request.delete({ url: `/promotion/auto-response/delete?id=` + id })
|
||||
},
|
||||
|
||||
// 导出自动回复 Excel
|
||||
exportAutoResponse: async (params) => {
|
||||
return await request.download({ url: `/promotion/auto-response/export-excel`, params })
|
||||
}
|
||||
}
|
51
yudao-admin-vue3/src/api/mall/promotion/leaveword/index.ts
Normal file
51
yudao-admin-vue3/src/api/mall/promotion/leaveword/index.ts
Normal file
@ -0,0 +1,51 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 用户留言 VO
|
||||
export interface LeaveWordVO {
|
||||
id: number // id
|
||||
name: string // 昵称
|
||||
phone: string // 电话
|
||||
content: string // 内容
|
||||
response: string //回复内容
|
||||
status: number // 状态
|
||||
}
|
||||
|
||||
// 用户留言 API
|
||||
export const LeaveWordApi = {
|
||||
// 查询用户留言分页
|
||||
getLeaveWordPage: async (params: any) => {
|
||||
return await request.get({ url: `/promotion/leave-word/page`, params })
|
||||
},
|
||||
|
||||
// 查询用户留言详情
|
||||
getLeaveWord: async (id: number) => {
|
||||
return await request.get({ url: `/promotion/leave-word/get?id=` + id })
|
||||
},
|
||||
|
||||
// 新增用户留言
|
||||
createLeaveWord: async (data: LeaveWordVO) => {
|
||||
return await request.post({ url: `/promotion/leave-word/create`, data })
|
||||
},
|
||||
|
||||
// 修改用户留言
|
||||
updateLeaveWord: async (data: LeaveWordVO) => {
|
||||
return await request.put({ url: `/promotion/leave-word/update`, data })
|
||||
},
|
||||
|
||||
// 删除用户留言
|
||||
deleteLeaveWord: async (id: number) => {
|
||||
return await request.delete({ url: `/promotion/leave-word/delete?id=` + id })
|
||||
},
|
||||
|
||||
// 导出用户留言 Excel
|
||||
exportLeaveWord: async (params) => {
|
||||
return await request.download({ url: `/promotion/leave-word/export-excel`, params })
|
||||
},
|
||||
|
||||
// 添加回复内容
|
||||
addResponse: async (id: number, content: string) => {
|
||||
return await request.get({ url: `/promotion/leave-word/addResponse?id=` + id +`&&response=` + content })
|
||||
},
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 客服人员 VO
|
||||
export interface SupportStaffVO {
|
||||
id: number // ID
|
||||
name: string // 客服名称
|
||||
pic: string //头像
|
||||
phone: string // 手机号码
|
||||
account: string // 登录账号
|
||||
password: string // 登录密码
|
||||
status: number // 客服状态
|
||||
orderManage: number // 手机订单管理
|
||||
orderInform: number // 订单通知
|
||||
}
|
||||
|
||||
// 客服人员 API
|
||||
export const SupportStaffApi = {
|
||||
// 查询客服人员分页
|
||||
getSupportStaffPage: async (params: any) => {
|
||||
return await request.get({ url: `/promotion/support-staff/page`, params })
|
||||
},
|
||||
|
||||
// 查询客服人员详情
|
||||
getSupportStaff: async (id: number) => {
|
||||
return await request.get({ url: `/promotion/support-staff/get?id=` + id })
|
||||
},
|
||||
|
||||
// 新增客服人员
|
||||
createSupportStaff: async (data: SupportStaffVO) => {
|
||||
return await request.post({ url: `/promotion/support-staff/create`, data })
|
||||
},
|
||||
|
||||
// 修改客服人员
|
||||
updateSupportStaff: async (data: SupportStaffVO) => {
|
||||
return await request.put({ url: `/promotion/support-staff/update`, data })
|
||||
},
|
||||
|
||||
// 删除客服人员
|
||||
deleteSupportStaff: async (id: number) => {
|
||||
return await request.delete({ url: `/promotion/support-staff/delete?id=` + id })
|
||||
},
|
||||
|
||||
// 导出客服人员 Excel
|
||||
exportSupportStaff: async (params) => {
|
||||
return await request.download({ url: `/promotion/support-staff/export-excel`, params })
|
||||
}
|
||||
}
|
47
yudao-admin-vue3/src/api/mall/promotion/verbaltrick/index.ts
Normal file
47
yudao-admin-vue3/src/api/mall/promotion/verbaltrick/index.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 客服话术 VO
|
||||
export interface VerbalTrickVO {
|
||||
id: number // id
|
||||
type: number // 分类
|
||||
title: string // 标题
|
||||
details: string // 详情
|
||||
}
|
||||
|
||||
// 客服话术 API
|
||||
export const VerbalTrickApi = {
|
||||
// 查询客服话术分页
|
||||
getVerbalTrickPage: async (params: any) => {
|
||||
return await request.get({ url: `/promotion/verbal-trick/page`, params })
|
||||
},
|
||||
|
||||
// 查询客服话术详情
|
||||
getVerbalTrick: async (id: number) => {
|
||||
return await request.get({ url: `/promotion/verbal-trick/get?id=` + id })
|
||||
},
|
||||
|
||||
// 新增客服话术
|
||||
createVerbalTrick: async (data: VerbalTrickVO) => {
|
||||
return await request.post({ url: `/promotion/verbal-trick/create`, data })
|
||||
},
|
||||
|
||||
// 修改客服话术
|
||||
updateVerbalTrick: async (data: VerbalTrickVO) => {
|
||||
return await request.put({ url: `/promotion/verbal-trick/update`, data })
|
||||
},
|
||||
|
||||
// 删除客服话术
|
||||
deleteVerbalTrick: async (id: number) => {
|
||||
return await request.delete({ url: `/promotion/verbal-trick/delete?id=` + id })
|
||||
},
|
||||
|
||||
// 导出客服话术 Excel
|
||||
exportVerbalTrick: async (params) => {
|
||||
return await request.download({ url: `/promotion/verbal-trick/export-excel`, params })
|
||||
},
|
||||
|
||||
// 查询客服话术
|
||||
getVerbalTrickList: async () => {
|
||||
return await request.get({ url: `/promotion/verbal-trick/getVerbalTrickList` })
|
||||
}
|
||||
}
|
@ -139,6 +139,21 @@ export enum DICT_TYPE {
|
||||
//预约:机构管理
|
||||
ORGANIZATION_STATUS = 'organization_status',
|
||||
|
||||
//客服:自动回复
|
||||
KEFU_AUTO_RESPONSE_TYPE = 'kefu_auto_response_type',
|
||||
KEFU_AUTO_RESPONSE_STATUS = 'kefu_auto_response_status',
|
||||
|
||||
//客服:留言
|
||||
KEFU_LEAVE_WORD_STATUS = 'kefu_leave_word_status',
|
||||
|
||||
//客服:话术
|
||||
KEFU_VERBAL_TRICK_TYPE = 'kefu_verbal_trick_type',
|
||||
|
||||
//客服人员管理
|
||||
KEFU_SUPPORT_STAFF_STATUS = 'kefu_support_staff_status',
|
||||
KEFU_SUPPORT_STAFF_ORDER_MANAGE = 'kefu_support_staff_order_manage',
|
||||
KEFU_SUPPORT_STAFF_ORDER_INFORM = 'kefu_support_staff_order_inform',
|
||||
|
||||
// ========== SYSTEM 模块 ==========
|
||||
SYSTEM_USER_SEX = 'system_user_sex',
|
||||
SYSTEM_MENU_TYPE = 'system_menu_type',
|
||||
|
@ -0,0 +1,125 @@
|
||||
<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="keyword">
|
||||
<el-input v-model="formData.keyword" placeholder="请输入关键字" />
|
||||
</el-form-item>
|
||||
<el-form-item label="回复类型" prop="type">
|
||||
<el-select v-model="formData.type" placeholder="请选择回复类型">
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.KEFU_AUTO_RESPONSE_TYPE)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="回复内容" prop="content">
|
||||
<el-input v-model="formData.content" type="textarea" placeholder="请输入回复内容" />
|
||||
</el-form-item>
|
||||
<el-form-item label="是否开启" prop="status">
|
||||
<el-select v-model="formData.status" placeholder="请选择是否开启">
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.KEFU_AUTO_RESPONSE_STATUS)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</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 { AutoResponseApi, AutoResponseVO } from '@/api/mall/promotion/autoresponse'
|
||||
|
||||
/** 自动回复 表单 */
|
||||
defineOptions({ name: 'AutoResponseForm' })
|
||||
|
||||
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,
|
||||
keyword: undefined,
|
||||
type: undefined,
|
||||
content: undefined,
|
||||
status: undefined
|
||||
})
|
||||
const formRules = reactive({
|
||||
keyword: [{ required: true, message: '关键字不能为空', trigger: 'blur' }],
|
||||
type: [{ required: true, message: '回复类型不能为空', trigger: 'change' }],
|
||||
content: [{ required: true, message: '回复内容不能为空', trigger: 'blur' }],
|
||||
status: [{ required: true, message: '是否开启不能为空', trigger: 'change' }]
|
||||
})
|
||||
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 AutoResponseApi.getAutoResponse(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 AutoResponseVO
|
||||
if (formType.value === 'create') {
|
||||
await AutoResponseApi.createAutoResponse(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await AutoResponseApi.updateAutoResponse(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
keyword: undefined,
|
||||
type: undefined,
|
||||
content: undefined,
|
||||
status: undefined
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
232
yudao-admin-vue3/src/views/mall/promotion/autoresponse/index.vue
Normal file
232
yudao-admin-vue3/src/views/mall/promotion/autoresponse/index.vue
Normal file
@ -0,0 +1,232 @@
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
class="-mb-15px"
|
||||
:model="queryParams"
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
label-width="68px"
|
||||
>
|
||||
<el-form-item label="关键字" prop="keyword">
|
||||
<el-input
|
||||
v-model="queryParams.keyword"
|
||||
placeholder="请输入关键字"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="回复类型" prop="type">
|
||||
<el-select
|
||||
v-model="queryParams.type"
|
||||
placeholder="请选择回复类型"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.KEFU_AUTO_RESPONSE_TYPE)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否开启" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
placeholder="请选择是否开启"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.KEFU_AUTO_RESPONSE_STATUS)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker
|
||||
v-model="queryParams.createTime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
type="daterange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="openForm('create')"
|
||||
v-hasPermi="['promotion:auto-response:create']"
|
||||
>
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
@click="handleExport"
|
||||
:loading="exportLoading"
|
||||
v-hasPermi="['promotion:auto-response:export']"
|
||||
>
|
||||
<Icon icon="ep:download" class="mr-5px" /> 导出
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column label="ID" align="center" prop="id" />
|
||||
<el-table-column label="关键字" align="center" prop="keyword" />
|
||||
<el-table-column label="回复类型" align="center" prop="type">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.KEFU_AUTO_RESPONSE_TYPE" :value="scope.row.type" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="回复内容" align="center" prop="content" />
|
||||
<el-table-column label="是否开启" align="center" prop="status">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.KEFU_AUTO_RESPONSE_STATUS" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm('update', scope.row.id)"
|
||||
v-hasPermi="['promotion:auto-response:update']"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
v-hasPermi="['promotion:auto-response:delete']"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<AutoResponseForm ref="formRef" @success="getList" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import download from '@/utils/download'
|
||||
import { AutoResponseApi, AutoResponseVO } from '@/api/mall/promotion/autoresponse'
|
||||
import AutoResponseForm from './AutoResponseForm.vue'
|
||||
|
||||
/** 自动回复 列表 */
|
||||
defineOptions({ name: 'AutoResponse' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const list = ref<AutoResponseVO[]>([]) // 列表的数据
|
||||
const total = ref(0) // 列表的总页数
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
keyword: undefined,
|
||||
type: undefined,
|
||||
content: undefined,
|
||||
status: undefined,
|
||||
createTime: []
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const exportLoading = ref(false) // 导出的加载中
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await AutoResponseApi.getAutoResponsePage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 添加/修改操作 */
|
||||
const formRef = ref()
|
||||
const openForm = (type: string, id?: number) => {
|
||||
formRef.value.open(type, id)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await AutoResponseApi.deleteAutoResponse(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
// 导出的二次确认
|
||||
await message.exportConfirm()
|
||||
// 发起导出
|
||||
exportLoading.value = true
|
||||
const data = await AutoResponseApi.exportAutoResponse(queryParams)
|
||||
download.excel(data, '自动回复.xls')
|
||||
} catch {
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
@ -10,100 +10,63 @@
|
||||
<div v-for="(item, index) in getMessageList0" :key="item.id" class="w-[100%]">
|
||||
<div class="flex justify-center items-center mb-20px">
|
||||
<!-- 日期 -->
|
||||
<div
|
||||
v-if="
|
||||
<div v-if="
|
||||
item.contentType !== KeFuMessageContentTypeEnum.SYSTEM && showTime(item, index)
|
||||
"
|
||||
class="date-message"
|
||||
>
|
||||
" class="date-message">
|
||||
{{ formatDate(item.createTime) }}
|
||||
</div>
|
||||
<!-- 系统消息 -->
|
||||
<div
|
||||
v-if="item.contentType === KeFuMessageContentTypeEnum.SYSTEM"
|
||||
class="system-message"
|
||||
>
|
||||
<div v-if="item.contentType === KeFuMessageContentTypeEnum.SYSTEM" class="system-message">
|
||||
{{ item.content }}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
:class="[
|
||||
<div :class="[
|
||||
item.senderType === UserTypeEnum.MEMBER
|
||||
? `ss-row-left`
|
||||
: item.senderType === UserTypeEnum.ADMIN
|
||||
? `ss-row-right`
|
||||
: ''
|
||||
]"
|
||||
class="flex mb-20px w-[100%]"
|
||||
>
|
||||
<el-avatar
|
||||
v-if="item.senderType === UserTypeEnum.MEMBER"
|
||||
:src="conversation.userAvatar"
|
||||
alt="avatar"
|
||||
class="w-60px h-60px"
|
||||
/>
|
||||
<div
|
||||
:class="{ 'kefu-message': KeFuMessageContentTypeEnum.TEXT === item.contentType }"
|
||||
class="p-10px"
|
||||
>
|
||||
]" class="flex mb-20px w-[100%]">
|
||||
<el-avatar v-if="item.senderType === UserTypeEnum.MEMBER" :src="conversation.userAvatar"
|
||||
alt="avatar" class="w-60px h-60px" />
|
||||
<div :class="{ 'kefu-message': KeFuMessageContentTypeEnum.TEXT === item.contentType }"
|
||||
class="p-10px">
|
||||
<!-- 文本消息 -->
|
||||
<MessageItem :message="item">
|
||||
<template v-if="KeFuMessageContentTypeEnum.TEXT === item.contentType">
|
||||
<div
|
||||
v-dompurify-html="replaceEmoji(item.content)"
|
||||
class="flex items-center"
|
||||
></div>
|
||||
<div v-dompurify-html="replaceEmoji(item.content)" class="flex items-center">
|
||||
</div>
|
||||
</template>
|
||||
</MessageItem>
|
||||
<!-- 图片消息 -->
|
||||
<MessageItem :message="item">
|
||||
<el-image
|
||||
v-if="KeFuMessageContentTypeEnum.IMAGE === item.contentType"
|
||||
:initial-index="0"
|
||||
:preview-src-list="[item.content]"
|
||||
:src="item.content"
|
||||
class="w-200px"
|
||||
fit="contain"
|
||||
preview-teleported
|
||||
/>
|
||||
<el-image v-if="KeFuMessageContentTypeEnum.IMAGE === item.contentType"
|
||||
:initial-index="0" :preview-src-list="[item.content]" :src="item.content"
|
||||
class="w-200px" fit="contain" preview-teleported />
|
||||
</MessageItem>
|
||||
<!-- 商品消息 -->
|
||||
<MessageItem :message="item">
|
||||
<ProductItem
|
||||
v-if="KeFuMessageContentTypeEnum.PRODUCT === item.contentType"
|
||||
:spuId="getMessageContent(item).spuId"
|
||||
:picUrl="getMessageContent(item).picUrl"
|
||||
<ProductItem v-if="KeFuMessageContentTypeEnum.PRODUCT === item.contentType"
|
||||
:spuId="getMessageContent(item).spuId" :picUrl="getMessageContent(item).picUrl"
|
||||
:price="getMessageContent(item).price"
|
||||
:skuText="getMessageContent(item).introduction"
|
||||
:title="getMessageContent(item).spuName"
|
||||
:titleWidth="400"
|
||||
class="max-w-70%"
|
||||
priceColor="#FF3000"
|
||||
/>
|
||||
:title="getMessageContent(item).spuName" :titleWidth="400" class="max-w-70%"
|
||||
priceColor="#FF3000" />
|
||||
</MessageItem>
|
||||
<!-- 订单消息 -->
|
||||
<MessageItem :message="item">
|
||||
<OrderItem
|
||||
v-if="KeFuMessageContentTypeEnum.ORDER === item.contentType"
|
||||
:message="item"
|
||||
class="max-w-100%"
|
||||
/>
|
||||
<OrderItem v-if="KeFuMessageContentTypeEnum.ORDER === item.contentType"
|
||||
:message="item" class="max-w-100%" />
|
||||
</MessageItem>
|
||||
</div>
|
||||
<el-avatar
|
||||
v-if="item.senderType === UserTypeEnum.ADMIN"
|
||||
:src="item.senderAvatar"
|
||||
alt="avatar"
|
||||
/>
|
||||
<el-avatar v-if="item.senderType === UserTypeEnum.ADMIN" :src="item.senderAvatar"
|
||||
alt="avatar" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
<div
|
||||
v-show="showNewMessageTip"
|
||||
class="newMessageTip flex items-center cursor-pointer"
|
||||
@click="handleToNewMessage"
|
||||
>
|
||||
<div v-show="showNewMessageTip" class="newMessageTip flex items-center cursor-pointer"
|
||||
@click="handleToNewMessage">
|
||||
<span>有新消息</span>
|
||||
<Icon class="ml-5px" icon="ep:bottom" />
|
||||
</div>
|
||||
@ -112,10 +75,12 @@
|
||||
<div class="h-[100%]">
|
||||
<div class="chat-tools flex items-center">
|
||||
<EmojiSelectPopover @select-emoji="handleEmojiSelect" />
|
||||
<PictureSelectUpload
|
||||
class="ml-15px mt-3px cursor-pointer"
|
||||
@send-picture="handleSendPicture"
|
||||
/>
|
||||
<PictureSelectUpload class="ml-15px mt-3px cursor-pointer" @send-picture="handleSendPicture" />
|
||||
<!-- <VerbalTrick class="ml-11px mt-5px cursor-pointer" /> -->
|
||||
<!-- 话术库 -->
|
||||
<div style="margin-left: 9px; margin-top:5px;cursor: pointer;">
|
||||
<img :src="Picture" class="w-32px h-32px" @click="huashu" />
|
||||
</div>
|
||||
</div>
|
||||
<el-input v-model="message" :rows="6" style="border-style: none" type="textarea" />
|
||||
<div class="h-45px flex justify-end">
|
||||
@ -125,48 +90,73 @@
|
||||
</el-footer>
|
||||
</el-container>
|
||||
<el-empty v-else description="请选择左侧的一个会话后开始" />
|
||||
|
||||
<Dialog :title="dialogTitle" v-model="dialogVisible" :modal="false" width="700px">
|
||||
|
||||
<div style="display: flex; width: 100%; height: 400px;">
|
||||
|
||||
<!-- 左边占 30% -->
|
||||
<div style="flex: 0 0 20%; background-color: #f0f0f0; padding: 10px;">
|
||||
左边的内容
|
||||
</div>
|
||||
<!-- 右边占 70% -->
|
||||
<div style="flex: 1; padding: 5px; overflow-y: auto; max-height: 400px;">
|
||||
<p v-for="item in verbalTrickList" :key="item.id" style="font-size: 12px;cursor: pointer;transition: background-color 0.3s;" class="hover-shadow" @click="huashuClick(item.details)">
|
||||
{{item.details}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ElScrollbar as ElScrollbarType } from 'element-plus'
|
||||
import { KeFuMessageApi, KeFuMessageRespVO } from '@/api/mall/promotion/kefu/message'
|
||||
import { KeFuConversationRespVO } from '@/api/mall/promotion/kefu/conversation'
|
||||
import EmojiSelectPopover from './tools/EmojiSelectPopover.vue'
|
||||
import PictureSelectUpload from './tools/PictureSelectUpload.vue'
|
||||
import ProductItem from './message/ProductItem.vue'
|
||||
import OrderItem from './message/OrderItem.vue'
|
||||
import { Emoji, useEmoji } from './tools/emoji'
|
||||
import { KeFuMessageContentTypeEnum } from './tools/constants'
|
||||
import { isEmpty } from '@/utils/is'
|
||||
import { UserTypeEnum } from '@/utils/constants'
|
||||
import { formatDate } from '@/utils/formatTime'
|
||||
import dayjs from 'dayjs'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
import { debounce } from 'lodash-es'
|
||||
import { jsonParse } from '@/utils'
|
||||
import { ElScrollbar as ElScrollbarType } from 'element-plus'
|
||||
import { KeFuMessageApi, KeFuMessageRespVO } from '@/api/mall/promotion/kefu/message'
|
||||
import { VerbalTrickApi, VerbalTrickVO } from '@/api/mall/promotion/verbaltrick'
|
||||
import { KeFuConversationRespVO } from '@/api/mall/promotion/kefu/conversation'
|
||||
import EmojiSelectPopover from './tools/EmojiSelectPopover.vue'
|
||||
import PictureSelectUpload from './tools/PictureSelectUpload.vue'
|
||||
// import VerbalTrick from './tools/VerbalTrick.vue'
|
||||
import Picture from '@/views/mall/promotion/kefu/components/asserts/huashu.png'
|
||||
import ProductItem from './message/ProductItem.vue'
|
||||
import OrderItem from './message/OrderItem.vue'
|
||||
import { Emoji, useEmoji } from './tools/emoji'
|
||||
import { KeFuMessageContentTypeEnum } from './tools/constants'
|
||||
import { isEmpty } from '@/utils/is'
|
||||
import { UserTypeEnum } from '@/utils/constants'
|
||||
import { formatDate } from '@/utils/formatTime'
|
||||
import dayjs from 'dayjs'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
import { debounce } from 'lodash-es'
|
||||
import { jsonParse } from '@/utils'
|
||||
|
||||
dayjs.extend(relativeTime)
|
||||
dayjs.extend(relativeTime)
|
||||
|
||||
defineOptions({ name: 'KeFuMessageList' })
|
||||
defineOptions({ name: 'KeFuMessageList' })
|
||||
|
||||
const message = ref('') // 消息弹窗
|
||||
const { replaceEmoji } = useEmoji()
|
||||
const messageTool = useMessage()
|
||||
const messageList = ref<KeFuMessageRespVO[]>([]) // 消息列表
|
||||
const conversation = ref<KeFuConversationRespVO>({} as KeFuConversationRespVO) // 用户会话
|
||||
const showNewMessageTip = ref(false) // 显示有新消息提示
|
||||
const queryParams = reactive({
|
||||
let dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('客服话术') // 客服话术库弹窗标题
|
||||
// 话术库的数据
|
||||
const verbalTrickList = ref<VerbalTrickVO[]>([])
|
||||
const message = ref('') // 消息弹窗
|
||||
const { replaceEmoji } = useEmoji()
|
||||
const messageTool = useMessage()
|
||||
const messageList = ref<KeFuMessageRespVO[]>([]) // 消息列表
|
||||
const conversation = ref<KeFuConversationRespVO>({} as KeFuConversationRespVO) // 用户会话
|
||||
const showNewMessageTip = ref(false) // 显示有新消息提示
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
conversationId: 0
|
||||
})
|
||||
const total = ref(0) // 消息总条数
|
||||
const refreshContent = ref(false) // 内容刷新,主要解决会话消息页面高度不一致导致的滚动功能精度失效
|
||||
})
|
||||
const total = ref(0) // 消息总条数
|
||||
const refreshContent = ref(false) // 内容刷新,主要解决会话消息页面高度不一致导致的滚动功能精度失效
|
||||
|
||||
/** 获悉消息内容 */
|
||||
const getMessageContent = computed(() => (item: any) => jsonParse(item.content))
|
||||
/** 获得消息列表 */
|
||||
const getMessageList = async () => {
|
||||
/** 获悉消息内容 */
|
||||
const getMessageContent = computed(() => (item : any) => jsonParse(item.content))
|
||||
/** 获得消息列表 */
|
||||
const getMessageList = async () => {
|
||||
const res = await KeFuMessageApi.getKeFuMessagePage(queryParams)
|
||||
total.value = res.total
|
||||
// 情况一:加载最新消息
|
||||
@ -179,24 +169,24 @@ const getMessageList = async () => {
|
||||
}
|
||||
}
|
||||
refreshContent.value = true
|
||||
}
|
||||
}
|
||||
|
||||
/** 添加消息 */
|
||||
const pushMessage = (message: any) => {
|
||||
/** 添加消息 */
|
||||
const pushMessage = (message : any) => {
|
||||
if (messageList.value.some((val) => val.id === message.id)) {
|
||||
return
|
||||
}
|
||||
messageList.value.push(message)
|
||||
}
|
||||
}
|
||||
|
||||
/** 按照时间倒序,获取消息列表 */
|
||||
const getMessageList0 = computed(() => {
|
||||
messageList.value.sort((a: any, b: any) => a.createTime - b.createTime)
|
||||
/** 按照时间倒序,获取消息列表 */
|
||||
const getMessageList0 = computed(() => {
|
||||
messageList.value.sort((a : any, b : any) => a.createTime - b.createTime)
|
||||
return messageList.value
|
||||
})
|
||||
})
|
||||
|
||||
/** 刷新消息列表 */
|
||||
const refreshMessageList = async (message?: any) => {
|
||||
/** 刷新消息列表 */
|
||||
const refreshMessageList = async (message ?: any) => {
|
||||
if (!conversation.value) {
|
||||
return
|
||||
}
|
||||
@ -220,11 +210,11 @@ const refreshMessageList = async (message?: any) => {
|
||||
// 滚动到最新消息处
|
||||
await handleToNewMessage()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 获得新会话的消息列表 */
|
||||
// TODO @puhui999:可优化:可以考虑本地做每个会话的消息 list 缓存;然后点击切换时,读取缓存;然后异步获取新消息,merge 下;
|
||||
const getNewMessageList = async (val: KeFuConversationRespVO) => {
|
||||
/** 获得新会话的消息列表 */
|
||||
// TODO @puhui999:可优化:可以考虑本地做每个会话的消息 list 缓存;然后点击切换时,读取缓存;然后异步获取新消息,merge 下;
|
||||
const getNewMessageList = async (val : KeFuConversationRespVO) => {
|
||||
// 会话切换,重置相关参数
|
||||
queryParams.pageNo = 1
|
||||
messageList.value = []
|
||||
@ -236,22 +226,22 @@ const getNewMessageList = async (val: KeFuConversationRespVO) => {
|
||||
queryParams.conversationId = val.id
|
||||
// 获取消息
|
||||
await refreshMessageList()
|
||||
}
|
||||
defineExpose({ getNewMessageList, refreshMessageList })
|
||||
}
|
||||
defineExpose({ getNewMessageList, refreshMessageList })
|
||||
|
||||
const showKeFuMessageList = computed(() => !isEmpty(conversation.value)) // 是否显示聊天区域
|
||||
const skipGetMessageList = computed(() => {
|
||||
const showKeFuMessageList = computed(() => !isEmpty(conversation.value)) // 是否显示聊天区域
|
||||
const skipGetMessageList = computed(() => {
|
||||
// 已加载到最后一页的话则不触发新的消息获取
|
||||
return total.value > 0 && Math.ceil(total.value / queryParams.pageSize) === queryParams.pageNo
|
||||
}) // 跳过消息获取
|
||||
}) // 跳过消息获取
|
||||
|
||||
/** 处理表情选择 */
|
||||
const handleEmojiSelect = (item: Emoji) => {
|
||||
/** 处理表情选择 */
|
||||
const handleEmojiSelect = (item : Emoji) => {
|
||||
message.value += item.name
|
||||
}
|
||||
}
|
||||
|
||||
/** 处理图片发送 */
|
||||
const handleSendPicture = async (picUrl: string) => {
|
||||
/** 处理图片发送 */
|
||||
const handleSendPicture = async (picUrl : string) => {
|
||||
// 组织发送消息
|
||||
const msg = {
|
||||
conversationId: conversation.value.id,
|
||||
@ -259,10 +249,27 @@ const handleSendPicture = async (picUrl: string) => {
|
||||
content: picUrl
|
||||
}
|
||||
await sendMessage(msg)
|
||||
}
|
||||
}
|
||||
|
||||
/** 发送文本消息 */
|
||||
const handleSendMessage = async () => {
|
||||
/*点击话术库*/
|
||||
const huashu = async () => {
|
||||
dialogVisible.value = true;
|
||||
}
|
||||
|
||||
const getVerbalTrickList = async () => {
|
||||
const response = await VerbalTrickApi.getVerbalTrickList();
|
||||
verbalTrickList.value = response; // 将数据部分赋值给 verbalTrickList
|
||||
}
|
||||
|
||||
|
||||
/*选择话术库内容*/
|
||||
const huashuClick = (content: string) => {
|
||||
message.value = content;
|
||||
dialogVisible.value = false;
|
||||
}
|
||||
|
||||
/** 发送文本消息 */
|
||||
const handleSendMessage = async () => {
|
||||
// 1. 校验消息是否为空
|
||||
if (isEmpty(unref(message.value))) {
|
||||
messageTool.notifyWarning('请输入消息后再发送哦!')
|
||||
@ -275,21 +282,21 @@ const handleSendMessage = async () => {
|
||||
content: message.value
|
||||
}
|
||||
await sendMessage(msg)
|
||||
}
|
||||
}
|
||||
|
||||
/** 真正发送消息 【共用】*/
|
||||
const sendMessage = async (msg: any) => {
|
||||
/** 真正发送消息 【共用】*/
|
||||
const sendMessage = async (msg : any) => {
|
||||
// 发送消息
|
||||
await KeFuMessageApi.sendKeFuMessage(msg)
|
||||
message.value = ''
|
||||
// 加载消息列表
|
||||
await refreshMessageList()
|
||||
}
|
||||
}
|
||||
|
||||
/** 滚动到底部 */
|
||||
const innerRef = ref<HTMLDivElement>()
|
||||
const scrollbarRef = ref<InstanceType<typeof ElScrollbarType>>()
|
||||
const scrollToBottom = async () => {
|
||||
/** 滚动到底部 */
|
||||
const innerRef = ref<HTMLDivElement>()
|
||||
const scrollbarRef = ref<InstanceType<typeof ElScrollbarType>>()
|
||||
const scrollToBottom = async () => {
|
||||
// 1. 首次加载时滚动到最新消息,如果加载的是历史消息则不滚动
|
||||
if (loadHistory.value) {
|
||||
return
|
||||
@ -300,17 +307,17 @@ const scrollToBottom = async () => {
|
||||
showNewMessageTip.value = false
|
||||
// 2.2 消息已读
|
||||
await KeFuMessageApi.updateKeFuMessageReadStatus(conversation.value.id)
|
||||
}
|
||||
}
|
||||
|
||||
/** 查看新消息 */
|
||||
const handleToNewMessage = async () => {
|
||||
/** 查看新消息 */
|
||||
const handleToNewMessage = async () => {
|
||||
loadHistory.value = false
|
||||
await scrollToBottom()
|
||||
}
|
||||
}
|
||||
|
||||
const loadHistory = ref(false) // 加载历史消息
|
||||
/** 处理消息列表滚动事件(debounce 限流) */
|
||||
const handleScroll = debounce(({ scrollTop }) => {
|
||||
const loadHistory = ref(false) // 加载历史消息
|
||||
/** 处理消息列表滚动事件(debounce 限流) */
|
||||
const handleScroll = debounce(({ scrollTop }) => {
|
||||
if (skipGetMessageList.value) {
|
||||
return
|
||||
}
|
||||
@ -324,9 +331,9 @@ const handleScroll = debounce(({ scrollTop }) => {
|
||||
loadHistory.value = false
|
||||
refreshMessageList()
|
||||
}
|
||||
}, 200)
|
||||
/** 加载历史消息 */
|
||||
const handleOldMessage = async () => {
|
||||
}, 200)
|
||||
/** 加载历史消息 */
|
||||
const handleOldMessage = async () => {
|
||||
// 记录已有页面高度
|
||||
const oldPageHeight = innerRef.value?.clientHeight
|
||||
if (!oldPageHeight) {
|
||||
@ -338,25 +345,35 @@ const handleOldMessage = async () => {
|
||||
await getMessageList()
|
||||
// 等页面加载完后,获得上一页最后一条消息的位置,控制滚动到它所在位置
|
||||
scrollbarRef.value!.setScrollTop(innerRef.value!.clientHeight - oldPageHeight)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* 是否显示时间
|
||||
*
|
||||
* @param {*} item - 数据
|
||||
* @param {*} index - 索引
|
||||
*/
|
||||
const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
|
||||
const showTime = computed(() => (item : KeFuMessageRespVO, index : number) => {
|
||||
if (unref(messageList.value)[index + 1]) {
|
||||
let dateString = dayjs(unref(messageList.value)[index + 1].createTime).fromNow()
|
||||
return dateString !== dayjs(unref(item).createTime).fromNow()
|
||||
}
|
||||
return false
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getVerbalTrickList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.kefu {
|
||||
|
||||
.hover-shadow:hover {
|
||||
background-color: lightgray; /* 可根据需要调整颜色 */
|
||||
}
|
||||
.kefu {
|
||||
&-title {
|
||||
border-bottom: #e4e0e0 solid 1px;
|
||||
height: 60px;
|
||||
@ -374,7 +391,8 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
|
||||
padding: 10px;
|
||||
border-radius: 30px;
|
||||
font-size: 12px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* 阴影效果 */
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
/* 阴影效果 */
|
||||
}
|
||||
|
||||
.ss-row-left {
|
||||
@ -399,6 +417,8 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.ss-row-right {
|
||||
justify-content: flex-end;
|
||||
|
||||
@ -436,6 +456,7 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
|
||||
background-color: var(--app-content-bg-color);
|
||||
transition: all 0.2s;
|
||||
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.03);
|
||||
}
|
||||
@ -463,5 +484,5 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
|
||||
::v-deep(textarea) {
|
||||
resize: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -21,6 +21,7 @@
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { KeFuConversationList, KeFuMessageList, MemberBrowsingHistory } from './components'
|
||||
import { WebSocketMessageTypeConstants } from './components/tools/constants'
|
||||
|
@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<Dialog :title="dialogTitle" v-model="dialogVisible">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:rules="formRules"
|
||||
:model="formData"
|
||||
label-width="100px"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<el-form-item label="回复内容" >
|
||||
<el-input v-model="formData.response" 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 { LeaveWordApi, LeaveWordVO } from '@/api/mall/promotion/leaveword'
|
||||
|
||||
/** 用户留言 表单 */
|
||||
defineOptions({ name: 'LeaveWordForm' })
|
||||
|
||||
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: 0,
|
||||
response: '',
|
||||
})
|
||||
const formRules = reactive({
|
||||
response: [{ required: true, message: '回复内容', trigger: 'blur' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (id: number) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = t('回复')
|
||||
// formType.value = '回复'
|
||||
formData.value.id = id
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
await formRef.value.validate()
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
console.log('1111111111111',formData.value.id +' , '+ formData.value.response )
|
||||
await LeaveWordApi.addResponse(formData.value.id,formData.value.response)
|
||||
message.notifySuccess('处理成功')
|
||||
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
223
yudao-admin-vue3/src/views/mall/promotion/leaveword/index.vue
Normal file
223
yudao-admin-vue3/src/views/mall/promotion/leaveword/index.vue
Normal file
@ -0,0 +1,223 @@
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
class="-mb-15px"
|
||||
:model="queryParams"
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
label-width="68px"
|
||||
>
|
||||
<el-form-item label="昵称" prop="name">
|
||||
<el-input
|
||||
v-model="queryParams.name"
|
||||
placeholder="请输入昵称"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="电话" prop="phone">
|
||||
<el-input
|
||||
v-model="queryParams.phone"
|
||||
placeholder="请输入电话"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
placeholder="请选择状态"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.KEFU_LEAVE_WORD_STATUS)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker
|
||||
v-model="queryParams.createTime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
type="daterange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
@click="handleExport"
|
||||
:loading="exportLoading"
|
||||
v-hasPermi="['promotion:leave-word:export']"
|
||||
>
|
||||
<Icon icon="ep:download" class="mr-5px" /> 导出
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column label="ID" align="center" prop="id" />
|
||||
<el-table-column label="昵称" align="center" prop="name" />
|
||||
<el-table-column label="电话" align="center" prop="phone" />
|
||||
<el-table-column label="内容" align="center" prop="content" />
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.KEFU_LEAVE_WORD_STATUS" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button v-if="scope.row.status == 0"
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm( scope.row.id)"
|
||||
v-hasPermi="['promotion:leave-word:update']"
|
||||
>
|
||||
待处理
|
||||
</el-button>
|
||||
<el-button v-if="scope.row.status == 1"
|
||||
disabled
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm( scope.row.id)"
|
||||
v-hasPermi="['promotion:leave-word:update']"
|
||||
>
|
||||
已处理
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
v-hasPermi="['promotion:leave-word:delete']"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<LeaveWordForm ref="formRef" @success="getList" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import download from '@/utils/download'
|
||||
import { LeaveWordApi, LeaveWordVO } from '@/api/mall/promotion/leaveword'
|
||||
import LeaveWordForm from './LeaveWordForm.vue'
|
||||
|
||||
/** 用户留言 列表 */
|
||||
defineOptions({ name: 'LeaveWord' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const list = ref<LeaveWordVO[]>([]) // 列表的数据
|
||||
const total = ref(0) // 列表的总页数
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: undefined,
|
||||
phone: undefined,
|
||||
content: undefined,
|
||||
status: undefined,
|
||||
createTime: []
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const exportLoading = ref(false) // 导出的加载中
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await LeaveWordApi.getLeaveWordPage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 添加/修改操作 */
|
||||
const formRef = ref()
|
||||
const openForm = (id?: number) => {
|
||||
formRef.value.open(id)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await LeaveWordApi.deleteLeaveWord(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
// 导出的二次确认
|
||||
await message.exportConfirm()
|
||||
// 发起导出
|
||||
exportLoading.value = true
|
||||
const data = await LeaveWordApi.exportLeaveWord(queryParams)
|
||||
download.excel(data, '用户留言.xls')
|
||||
} catch {
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<Dialog v-model="dialogVisible" :title="dialogTitle" width="95%">
|
||||
<Dialog v-model="dialogVisible" :title="dialogTitle" width="90%">
|
||||
<Form
|
||||
ref="formRef"
|
||||
v-loading="formLoading"
|
||||
@ -36,7 +36,7 @@
|
||||
<el-input-number v-model="sku.productConfig.point" :min="0" class="w-100%" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="所需金额(元)" min-width="168">
|
||||
<!-- <el-table-column align="center" label="所需金额(元)" min-width="168">
|
||||
<template #default="{ row: sku }">
|
||||
<el-input-number
|
||||
v-model="sku.productConfig.price"
|
||||
@ -46,7 +46,7 @@
|
||||
class="w-100%"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column> -->
|
||||
</SpuAndSkuList>
|
||||
</template>
|
||||
</Form>
|
||||
|
@ -0,0 +1,159 @@
|
||||
<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="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入客服名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="客服头像" prop="pic">
|
||||
<UploadImg v-model="formData.pic" />
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号码" prop="phone">
|
||||
<el-input v-model="formData.phone" placeholder="请输入手机号码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="登录账号" prop="account">
|
||||
<el-input v-model="formData.account" placeholder="请输入登录账号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="登录密码" prop="password">
|
||||
<el-input v-model="formData.password" placeholder="请输入登录密码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="客服状态" prop="status">
|
||||
<el-radio-group v-model="formData.status">
|
||||
<el-radio
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.KEFU_SUPPORT_STAFF_STATUS)"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="手机订单管理" prop="orderManage">
|
||||
<el-radio-group v-model="formData.orderManage">
|
||||
<el-radio
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.KEFU_SUPPORT_STAFF_ORDER_MANAGE)"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="订单通知" prop="orderInform">
|
||||
<el-radio-group v-model="formData.orderInform">
|
||||
<el-radio
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.KEFU_SUPPORT_STAFF_ORDER_INFORM)"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</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 { SupportStaffApi, SupportStaffVO } from '@/api/mall/promotion/supportstaff'
|
||||
|
||||
/** 客服人员 表单 */
|
||||
defineOptions({ name: 'SupportStaffForm' })
|
||||
|
||||
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,
|
||||
name: undefined,
|
||||
pic: undefined,
|
||||
phone: undefined,
|
||||
account: undefined,
|
||||
password: undefined,
|
||||
status: undefined,
|
||||
orderManage: undefined,
|
||||
orderInform: undefined
|
||||
})
|
||||
const formRules = reactive({
|
||||
name: [{ required: true, message: '客服名称不能为空', trigger: 'blur' }],
|
||||
phone: [{ required: true, message: '手机号码不能为空', trigger: 'blur' }],
|
||||
account: [{ required: true, message: '登录账号不能为空', trigger: 'blur' }],
|
||||
password: [{ 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 SupportStaffApi.getSupportStaff(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 SupportStaffVO
|
||||
if (formType.value === 'create') {
|
||||
await SupportStaffApi.createSupportStaff(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await SupportStaffApi.updateSupportStaff(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
pic: undefined,
|
||||
phone: undefined,
|
||||
account: undefined,
|
||||
password: undefined,
|
||||
status: undefined,
|
||||
orderManage: undefined,
|
||||
orderInform: undefined
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
301
yudao-admin-vue3/src/views/mall/promotion/supportstaff/index.vue
Normal file
301
yudao-admin-vue3/src/views/mall/promotion/supportstaff/index.vue
Normal file
@ -0,0 +1,301 @@
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
class="-mb-15px"
|
||||
:model="queryParams"
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
label-width="68px"
|
||||
>
|
||||
<el-form-item label="客服名称" prop="name">
|
||||
<el-input
|
||||
v-model="queryParams.name"
|
||||
placeholder="请输入客服名称"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号码" prop="phone">
|
||||
<el-input
|
||||
v-model="queryParams.phone"
|
||||
placeholder="请输入手机号码"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="登录账号" prop="account">
|
||||
<el-input
|
||||
v-model="queryParams.account"
|
||||
placeholder="请输入登录账号"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="登录密码" prop="password">
|
||||
<el-input
|
||||
v-model="queryParams.password"
|
||||
placeholder="请输入登录密码"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="客服状态" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
placeholder="请选择客服状态"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.KEFU_SUPPORT_STAFF_STATUS)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="手机订单管理" prop="orderManage">
|
||||
<el-select
|
||||
v-model="queryParams.orderManage"
|
||||
placeholder="请选择手机订单管理"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.KEFU_SUPPORT_STAFF_ORDER_MANAGE)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<!-- <el-form-item label="订单通知" prop="orderInform">
|
||||
<el-select
|
||||
v-model="queryParams.orderInform"
|
||||
placeholder="请选择订单通知"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.KEFU_SUPPORT_STAFF_ORDER_INFORM)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker
|
||||
v-model="queryParams.createTime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
type="daterange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="openForm('create')"
|
||||
v-hasPermi="['promotion:support-staff:create']"
|
||||
>
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
@click="handleExport"
|
||||
:loading="exportLoading"
|
||||
v-hasPermi="['promotion:support-staff:export']"
|
||||
>
|
||||
<Icon icon="ep:download" class="mr-5px" /> 导出
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column label="ID" align="center" prop="id" />
|
||||
<el-table-column label="客服名称" align="center" prop="name" />
|
||||
<el-table-column label="客服头像" align="center" prop="pic" >
|
||||
<template #default="{ row }">
|
||||
<div class="flex justify-center items-center">
|
||||
<el-image
|
||||
fit="cover"
|
||||
:src="row.pic"
|
||||
class="flex-none w-50px h-50px"
|
||||
@click="imagePreview(row.pic)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="手机号码" align="center" prop="phone" />
|
||||
<el-table-column label="登录账号" align="center" prop="account" />
|
||||
<!-- <el-table-column label="登录密码" align="center" prop="password" /> -->
|
||||
<el-table-column label="客服状态" align="center" prop="status">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.KEFU_SUPPORT_STAFF_STATUS" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column label="手机订单管理" align="center" prop="orderManage">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.KEFU_SUPPORT_STAFF_ORDER_MANAGE" :value="scope.row.orderManage" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="订单通知" align="center" prop="orderInform">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.KEFU_SUPPORT_STAFF_ORDER_INFORM" :value="scope.row.orderInform" />
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm('update', scope.row.id)"
|
||||
v-hasPermi="['promotion:support-staff:update']"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
v-hasPermi="['promotion:support-staff:delete']"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<SupportStaffForm ref="formRef" @success="getList" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import download from '@/utils/download'
|
||||
import { SupportStaffApi, SupportStaffVO } from '@/api/mall/promotion/supportstaff'
|
||||
import SupportStaffForm from './SupportStaffForm.vue'
|
||||
|
||||
/** 客服人员 列表 */
|
||||
defineOptions({ name: 'SupportStaff' })
|
||||
|
||||
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const list = ref<SupportStaffVO[]>([]) // 列表的数据
|
||||
const total = ref(0) // 列表的总页数
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: undefined,
|
||||
phone: undefined,
|
||||
account: undefined,
|
||||
password: undefined,
|
||||
status: undefined,
|
||||
orderManage: undefined,
|
||||
orderInform: undefined,
|
||||
createTime: []
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const exportLoading = ref(false) // 导出的加载中
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await SupportStaffApi.getSupportStaffPage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 添加/修改操作 */
|
||||
const formRef = ref()
|
||||
const openForm = (type: string, id?: number) => {
|
||||
formRef.value.open(type, id)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await SupportStaffApi.deleteSupportStaff(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
// 导出的二次确认
|
||||
await message.exportConfirm()
|
||||
// 发起导出
|
||||
exportLoading.value = true
|
||||
const data = await SupportStaffApi.exportSupportStaff(queryParams)
|
||||
download.excel(data, '客服人员.xls')
|
||||
} catch {
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
<style>
|
||||
|
||||
</style>
|
@ -0,0 +1,111 @@
|
||||
<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="type">
|
||||
<el-select v-model="formData.type" placeholder="请选择分类">
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.KEFU_VERBAL_TRICK_TYPE)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="标题" prop="title">
|
||||
<el-input v-model="formData.title" placeholder="请输入标题" />
|
||||
</el-form-item>
|
||||
<el-form-item label="详情" prop="details">
|
||||
<el-input v-model="formData.details" type="textarea" placeholder="请输入详情" :rows="6" />
|
||||
</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 { VerbalTrickApi, VerbalTrickVO } from '@/api/mall/promotion/verbaltrick'
|
||||
|
||||
/** 客服话术 表单 */
|
||||
defineOptions({ name: 'VerbalTrickForm' })
|
||||
|
||||
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,
|
||||
type: undefined,
|
||||
title: undefined,
|
||||
details: undefined
|
||||
})
|
||||
const formRules = reactive({
|
||||
title: [{ required: true, message: '标题不能为空', trigger: 'blur' }],
|
||||
details: [{ 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 VerbalTrickApi.getVerbalTrick(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 VerbalTrickVO
|
||||
if (formType.value === 'create') {
|
||||
await VerbalTrickApi.createVerbalTrick(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await VerbalTrickApi.updateVerbalTrick(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
type: undefined,
|
||||
title: undefined,
|
||||
details: undefined
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
211
yudao-admin-vue3/src/views/mall/promotion/verbaltrick/index.vue
Normal file
211
yudao-admin-vue3/src/views/mall/promotion/verbaltrick/index.vue
Normal file
@ -0,0 +1,211 @@
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
class="-mb-15px"
|
||||
:model="queryParams"
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
label-width="68px"
|
||||
>
|
||||
<el-form-item label="分类" prop="type">
|
||||
<el-select
|
||||
v-model="queryParams.type"
|
||||
placeholder="请选择分类"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.KEFU_VERBAL_TRICK_TYPE)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="标题" prop="title">
|
||||
<el-input
|
||||
v-model="queryParams.title"
|
||||
placeholder="请输入标题"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker
|
||||
v-model="queryParams.createTime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
type="daterange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="openForm('create')"
|
||||
v-hasPermi="['promotion:verbal-trick:create']"
|
||||
>
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
@click="handleExport"
|
||||
:loading="exportLoading"
|
||||
v-hasPermi="['promotion:verbal-trick:export']"
|
||||
>
|
||||
<Icon icon="ep:download" class="mr-5px" /> 导出
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column label="ID" align="center" prop="id" />
|
||||
<el-table-column label="分类" align="center" prop="type">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.KEFU_VERBAL_TRICK_TYPE" :value="scope.row.type" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="标题" align="center" prop="title" />
|
||||
<el-table-column label="详情" align="center" prop="details" />
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm('update', scope.row.id)"
|
||||
v-hasPermi="['promotion:verbal-trick:update']"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
v-hasPermi="['promotion:verbal-trick:delete']"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<VerbalTrickForm ref="formRef" @success="getList" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import download from '@/utils/download'
|
||||
import { VerbalTrickApi, VerbalTrickVO } from '@/api/mall/promotion/verbaltrick'
|
||||
import VerbalTrickForm from './VerbalTrickForm.vue'
|
||||
|
||||
/** 客服话术 列表 */
|
||||
defineOptions({ name: 'VerbalTrick' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const list = ref<VerbalTrickVO[]>([]) // 列表的数据
|
||||
const total = ref(0) // 列表的总页数
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
type: undefined,
|
||||
title: undefined,
|
||||
details: undefined,
|
||||
createTime: []
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const exportLoading = ref(false) // 导出的加载中
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await VerbalTrickApi.getVerbalTrickPage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 添加/修改操作 */
|
||||
const formRef = ref()
|
||||
const openForm = (type: string, id?: number) => {
|
||||
formRef.value.open(type, id)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await VerbalTrickApi.deleteVerbalTrick(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
// 导出的二次确认
|
||||
await message.exportConfirm()
|
||||
// 发起导出
|
||||
exportLoading.value = true
|
||||
const data = await VerbalTrickApi.exportVerbalTrick(queryParams)
|
||||
download.excel(data, '客服话术.xls')
|
||||
} catch {
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
@ -154,4 +154,16 @@ public interface ErrorCodeConstants {
|
||||
|
||||
ErrorCode TIME_FORMAT_ERROR = new ErrorCode(1_019_007_008, "秒杀时间段格式化错误");
|
||||
|
||||
// ========== 客服话术 TODO 补充编号 ==========
|
||||
ErrorCode VERBAL_TRICK_NOT_EXISTS = new ErrorCode(1_020_00_001, "客服话术不存在");
|
||||
|
||||
// ========== 用户留言 TODO 补充编号 ==========
|
||||
ErrorCode LEAVE_WORD_NOT_EXISTS = new ErrorCode(1_021_001_001, "用户留言不存在");
|
||||
|
||||
// ========== 自动回复 TODO 补充编号 ==========
|
||||
ErrorCode AUTO_RESPONSE_NOT_EXISTS = new ErrorCode(1_022_000_000, "自动回复不存在");
|
||||
|
||||
// ========== 客服人员 TODO 补充编号 ==========
|
||||
ErrorCode SUPPORT_STAFF_NOT_EXISTS = new ErrorCode(1_023_000_000, "客服人员不存在");
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,95 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.autoresponse;
|
||||
|
||||
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.autoresponse.vo.*;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.autoresponse.AutoResponseDO;
|
||||
import cn.iocoder.yudao.module.promotion.service.autoresponse.AutoResponseService;
|
||||
|
||||
@Tag(name = "管理后台 - 自动回复")
|
||||
@RestController
|
||||
@RequestMapping("/promotion/auto-response")
|
||||
@Validated
|
||||
public class AutoResponseController {
|
||||
|
||||
@Resource
|
||||
private AutoResponseService autoResponseService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建自动回复")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:auto-response:create')")
|
||||
public CommonResult<Long> createAutoResponse(@Valid @RequestBody AutoResponseSaveReqVO createReqVO) {
|
||||
return success(autoResponseService.createAutoResponse(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新自动回复")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:auto-response:update')")
|
||||
public CommonResult<Boolean> updateAutoResponse(@Valid @RequestBody AutoResponseSaveReqVO updateReqVO) {
|
||||
autoResponseService.updateAutoResponse(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除自动回复")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('promotion:auto-response:delete')")
|
||||
public CommonResult<Boolean> deleteAutoResponse(@RequestParam("id") Long id) {
|
||||
autoResponseService.deleteAutoResponse(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得自动回复")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:auto-response:query')")
|
||||
public CommonResult<AutoResponseRespVO> getAutoResponse(@RequestParam("id") Long id) {
|
||||
AutoResponseDO autoResponse = autoResponseService.getAutoResponse(id);
|
||||
return success(BeanUtils.toBean(autoResponse, AutoResponseRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得自动回复分页")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:auto-response:query')")
|
||||
public CommonResult<PageResult<AutoResponseRespVO>> getAutoResponsePage(@Valid AutoResponsePageReqVO pageReqVO) {
|
||||
PageResult<AutoResponseDO> pageResult = autoResponseService.getAutoResponsePage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, AutoResponseRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出自动回复 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:auto-response:export')")
|
||||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void exportAutoResponseExcel(@Valid AutoResponsePageReqVO pageReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<AutoResponseDO> list = autoResponseService.getAutoResponsePage(pageReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "自动回复.xls", "数据", AutoResponseRespVO.class,
|
||||
BeanUtils.toBean(list, AutoResponseRespVO.class));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.autoresponse.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 AutoResponsePageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "关键字")
|
||||
private String keyword;
|
||||
|
||||
@Schema(description = "回复类型,文字消息/0,图片消息/1", example = "2")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "回复内容")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "是否开启,开启/1,关闭/0", example = "2")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.autoresponse.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 AutoResponseRespVO {
|
||||
|
||||
@Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "13888")
|
||||
@ExcelProperty("id")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "关键字", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("关键字")
|
||||
private String keyword;
|
||||
|
||||
@Schema(description = "回复类型,文字消息/0,图片消息/1", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@ExcelProperty(value = "回复类型,文字消息/0,图片消息/1", converter = DictConvert.class)
|
||||
@DictFormat("kefu_auto_response_type") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "回复内容", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("回复内容")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "是否开启,开启/1,关闭/0", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@ExcelProperty(value = "是否开启,开启/1,关闭/0", converter = DictConvert.class)
|
||||
@DictFormat("kefu_auto_response_status") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.autoresponse.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 AutoResponseSaveReqVO {
|
||||
|
||||
@Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "13888")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "关键字", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "关键字不能为空")
|
||||
private String keyword;
|
||||
|
||||
@Schema(description = "回复类型,文字消息/0,图片消息/1", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@NotNull(message = "回复类型,文字消息/0,图片消息/1不能为空")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "回复内容", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "回复内容不能为空")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "是否开启,开启/1,关闭/0", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@NotNull(message = "是否开启,开启/1,关闭/0不能为空")
|
||||
private Integer status;
|
||||
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.leaveword;
|
||||
|
||||
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.*;
|
||||
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.leaveword.vo.*;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.leaveword.LeaveWordDO;
|
||||
import cn.iocoder.yudao.module.promotion.service.leaveword.LeaveWordService;
|
||||
|
||||
@Tag(name = "管理后台 - 用户留言")
|
||||
@RestController
|
||||
@RequestMapping("/promotion/leave-word")
|
||||
@Validated
|
||||
public class LeaveWordController {
|
||||
|
||||
@Resource
|
||||
private LeaveWordService leaveWordService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建用户留言")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:leave-word:create')")
|
||||
public CommonResult<Long> createLeaveWord(@Valid @RequestBody LeaveWordSaveReqVO createReqVO) {
|
||||
return success(leaveWordService.createLeaveWord(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新用户留言")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:leave-word:update')")
|
||||
public CommonResult<Boolean> updateLeaveWord(@Valid @RequestBody LeaveWordSaveReqVO updateReqVO) {
|
||||
leaveWordService.updateLeaveWord(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除用户留言")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('promotion:leave-word:delete')")
|
||||
public CommonResult<Boolean> deleteLeaveWord(@RequestParam("id") Long id) {
|
||||
leaveWordService.deleteLeaveWord(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得用户留言")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:leave-word:query')")
|
||||
public CommonResult<LeaveWordRespVO> getLeaveWord(@RequestParam("id") Long id) {
|
||||
LeaveWordDO leaveWord = leaveWordService.getLeaveWord(id);
|
||||
return success(BeanUtils.toBean(leaveWord, LeaveWordRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得用户留言分页")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:leave-word:query')")
|
||||
public CommonResult<PageResult<LeaveWordRespVO>> getLeaveWordPage(@Valid LeaveWordPageReqVO pageReqVO) {
|
||||
PageResult<LeaveWordDO> pageResult = leaveWordService.getLeaveWordPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, LeaveWordRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出用户留言 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:leave-word:export')")
|
||||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void exportLeaveWordExcel(@Valid LeaveWordPageReqVO pageReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<LeaveWordDO> list = leaveWordService.getLeaveWordPage(pageReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "用户留言.xls", "数据", LeaveWordRespVO.class,
|
||||
BeanUtils.toBean(list, LeaveWordRespVO.class));
|
||||
}
|
||||
|
||||
|
||||
//回复留言信息
|
||||
@GetMapping("/addResponse")
|
||||
public boolean addResponse(String id,String response){
|
||||
return leaveWordService.addResponse(id,response);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.leaveword.vo;
|
||||
|
||||
import lombok.*;
|
||||
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 LeaveWordPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "昵称", example = "芋艿")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "电话")
|
||||
private String phone;
|
||||
|
||||
@Schema(description = "回复内容")
|
||||
private String response;
|
||||
|
||||
@Schema(description = "内容")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "状态", example = "2")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.leaveword.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
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 LeaveWordRespVO {
|
||||
|
||||
@Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "25658")
|
||||
@ExcelProperty("id")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "昵称", example = "芋艿")
|
||||
@ExcelProperty("昵称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "电话", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("电话")
|
||||
private String phone;
|
||||
|
||||
@Schema(description = "回复内容", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("回复内容")
|
||||
private String response;
|
||||
|
||||
@Schema(description = "留言内容", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("留言内容")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@ExcelProperty(value = "状态", converter = DictConvert.class)
|
||||
@DictFormat("kefu_leave_word_status") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.leaveword.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
@Schema(description = "管理后台 - 用户留言新增/修改 Request VO")
|
||||
@Data
|
||||
public class LeaveWordSaveReqVO {
|
||||
|
||||
@Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "25658")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "昵称", example = "芋艿")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "电话", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "电话不能为空")
|
||||
private String phone;
|
||||
|
||||
@Schema(description = "回复内容", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "回复内容不能为空")
|
||||
private String response;
|
||||
|
||||
@Schema(description = "内容", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "内容不能为空")
|
||||
private String content;
|
||||
|
||||
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@NotNull(message = "状态不能为空")
|
||||
private Integer status;
|
||||
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.supportstaff;
|
||||
|
||||
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.*;
|
||||
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.supportstaff.vo.*;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.supportstaff.SupportStaffDO;
|
||||
import cn.iocoder.yudao.module.promotion.service.supportstaff.SupportStaffService;
|
||||
|
||||
@Tag(name = "管理后台 - 客服人员")
|
||||
@RestController
|
||||
@RequestMapping("/promotion/support-staff")
|
||||
@Validated
|
||||
public class SupportStaffController {
|
||||
|
||||
@Resource
|
||||
private SupportStaffService supportStaffService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建客服人员")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:support-staff:create')")
|
||||
public CommonResult<Integer> createSupportStaff(@Valid @RequestBody SupportStaffSaveReqVO createReqVO) {
|
||||
return success(supportStaffService.createSupportStaff(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新客服人员")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:support-staff:update')")
|
||||
public CommonResult<Boolean> updateSupportStaff(@Valid @RequestBody SupportStaffSaveReqVO updateReqVO) {
|
||||
supportStaffService.updateSupportStaff(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除客服人员")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('promotion:support-staff:delete')")
|
||||
public CommonResult<Boolean> deleteSupportStaff(@RequestParam("id") Integer id) {
|
||||
supportStaffService.deleteSupportStaff(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得客服人员")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:support-staff:query')")
|
||||
public CommonResult<SupportStaffRespVO> getSupportStaff(@RequestParam("id") Integer id) {
|
||||
SupportStaffDO supportStaff = supportStaffService.getSupportStaff(id);
|
||||
return success(BeanUtils.toBean(supportStaff, SupportStaffRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得客服人员分页")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:support-staff:query')")
|
||||
public CommonResult<PageResult<SupportStaffRespVO>> getSupportStaffPage(@Valid SupportStaffPageReqVO pageReqVO) {
|
||||
PageResult<SupportStaffDO> pageResult = supportStaffService.getSupportStaffPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, SupportStaffRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出客服人员 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:support-staff:export')")
|
||||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void exportSupportStaffExcel(@Valid SupportStaffPageReqVO pageReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<SupportStaffDO> list = supportStaffService.getSupportStaffPage(pageReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "客服人员.xls", "数据", SupportStaffRespVO.class,
|
||||
BeanUtils.toBean(list, SupportStaffRespVO.class));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.supportstaff.vo;
|
||||
|
||||
import lombok.*;
|
||||
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 SupportStaffPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "客服名称", example = "张三")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "头像",example = "https://www.iocoder.cn")
|
||||
private String pic;
|
||||
|
||||
@Schema(description = "手机号码")
|
||||
private String phone;
|
||||
|
||||
@Schema(description = "登录账号", example = "31355")
|
||||
private String account;
|
||||
|
||||
@Schema(description = "登录密码")
|
||||
private String password;
|
||||
|
||||
@Schema(description = "客服状态", example = "2")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "手机订单管理")
|
||||
private Integer orderManage;
|
||||
|
||||
@Schema(description = "订单通知")
|
||||
private Integer orderInform;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.supportstaff.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
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 SupportStaffRespVO {
|
||||
|
||||
@Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "432")
|
||||
@ExcelProperty("ID")
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "客服名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")
|
||||
@ExcelProperty("客服名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "头像", example = "https://www.iocoder.cn")
|
||||
@ExcelProperty("头像")
|
||||
private String pic;
|
||||
|
||||
@Schema(description = "手机号码", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("手机号码")
|
||||
private String phone;
|
||||
|
||||
@Schema(description = "登录账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31355")
|
||||
@ExcelProperty("登录账号")
|
||||
private String account;
|
||||
|
||||
@Schema(description = "登录密码", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("登录密码")
|
||||
private String password;
|
||||
|
||||
@Schema(description = "客服状态", example = "2")
|
||||
@ExcelProperty(value = "客服状态", converter = DictConvert.class)
|
||||
@DictFormat("kefu_support_staff_status") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "手机订单管理")
|
||||
@ExcelProperty(value = "手机订单管理", converter = DictConvert.class)
|
||||
@DictFormat("kefu_support_staff_order_manage") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
|
||||
private Integer orderManage;
|
||||
|
||||
@Schema(description = "订单通知")
|
||||
@ExcelProperty(value = "订单通知", converter = DictConvert.class)
|
||||
@DictFormat("kefu_support_staff_order_inform") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
|
||||
private Integer orderInform;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.supportstaff.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
@Schema(description = "管理后台 - 客服人员新增/修改 Request VO")
|
||||
@Data
|
||||
public class SupportStaffSaveReqVO {
|
||||
|
||||
@Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "432")
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "客服名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")
|
||||
@NotEmpty(message = "客服名称不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "头像", example = "https://www.iocoder.cn")
|
||||
private String pic;
|
||||
|
||||
@Schema(description = "手机号码", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "手机号码不能为空")
|
||||
private String phone;
|
||||
|
||||
@Schema(description = "登录账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31355")
|
||||
@NotEmpty(message = "登录账号不能为空")
|
||||
private String account;
|
||||
|
||||
@Schema(description = "登录密码", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "登录密码不能为空")
|
||||
private String password;
|
||||
|
||||
@Schema(description = "客服状态", example = "2")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "手机订单管理")
|
||||
private Integer orderManage;
|
||||
|
||||
@Schema(description = "订单通知")
|
||||
private Integer orderInform;
|
||||
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.verbaltrick;
|
||||
|
||||
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
|
||||
import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO;
|
||||
import org.springframework.util.StringUtils;
|
||||
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.verbaltrick.vo.*;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.verbaltrick.VerbalTrickDO;
|
||||
import cn.iocoder.yudao.module.promotion.service.verbaltrick.VerbalTrickService;
|
||||
|
||||
@Tag(name = "管理后台 - 客服话术")
|
||||
@RestController
|
||||
@RequestMapping("/promotion/verbal-trick")
|
||||
@Validated
|
||||
public class VerbalTrickController {
|
||||
|
||||
@Resource
|
||||
private VerbalTrickService verbalTrickService;
|
||||
|
||||
@Resource
|
||||
public DictDataApi dictDataApi;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建客服话术")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:verbal-trick:create')")
|
||||
public CommonResult<Long> createVerbalTrick(@Valid @RequestBody VerbalTrickSaveReqVO createReqVO) {
|
||||
return success(verbalTrickService.createVerbalTrick(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新客服话术")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:verbal-trick:update')")
|
||||
public CommonResult<Boolean> updateVerbalTrick(@Valid @RequestBody VerbalTrickSaveReqVO updateReqVO) {
|
||||
verbalTrickService.updateVerbalTrick(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除客服话术")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('promotion:verbal-trick:delete')")
|
||||
public CommonResult<Boolean> deleteVerbalTrick(@RequestParam("id") Long id) {
|
||||
verbalTrickService.deleteVerbalTrick(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得客服话术")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:verbal-trick:query')")
|
||||
public CommonResult<VerbalTrickRespVO> getVerbalTrick(@RequestParam("id") Long id) {
|
||||
VerbalTrickDO verbalTrick = verbalTrickService.getVerbalTrick(id);
|
||||
return success(BeanUtils.toBean(verbalTrick, VerbalTrickRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得客服话术分页")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:verbal-trick:query')")
|
||||
public CommonResult<PageResult<VerbalTrickRespVO>> getVerbalTrickPage(@Valid VerbalTrickPageReqVO pageReqVO) {
|
||||
PageResult<VerbalTrickDO> pageResult = verbalTrickService.getVerbalTrickPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, VerbalTrickRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出客服话术 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:verbal-trick:export')")
|
||||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void exportVerbalTrickExcel(@Valid VerbalTrickPageReqVO pageReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<VerbalTrickDO> list = verbalTrickService.getVerbalTrickPage(pageReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "客服话术.xls", "数据", VerbalTrickRespVO.class,
|
||||
BeanUtils.toBean(list, VerbalTrickRespVO.class));
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/getVerbalTrickList")
|
||||
@Operation(summary = "获得客服话术数据")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:verbal-trick:query')")
|
||||
public CommonResult<List<VerbalTrickDO>> getVerbalTrickList() {
|
||||
List<VerbalTrickDO> result = verbalTrickService.getVerbalTrickList();
|
||||
return success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典类型查询字典数据信息,分类
|
||||
*/
|
||||
// @GetMapping(value = "/type")
|
||||
// public CommonResult dictType() {
|
||||
// List<DictDataRespDTO> dictDataList = dictDataApi.getDictDataList("types");
|
||||
// if (!dictDataList.isEmpty()) {
|
||||
// dictDataList = new ArrayList<DictDataRespDTO>();
|
||||
// }
|
||||
// return CommonResult.success(dictDataList);
|
||||
// }
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.verbaltrick.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 VerbalTrickPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "分类", example = "1")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "标题")
|
||||
private String title;
|
||||
|
||||
@Schema(description = "详情")
|
||||
private String details;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.verbaltrick.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 VerbalTrickRespVO {
|
||||
|
||||
@Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "19467")
|
||||
@ExcelProperty("id")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "分类", example = "1")
|
||||
@ExcelProperty(value = "分类", converter = DictConvert.class)
|
||||
@DictFormat("kefu_verbal_trick_type") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("标题")
|
||||
private String title;
|
||||
|
||||
@Schema(description = "详情", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("详情")
|
||||
private String details;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.verbaltrick.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 VerbalTrickSaveReqVO {
|
||||
|
||||
@Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "19467")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "分类", example = "1")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "标题不能为空")
|
||||
private String title;
|
||||
|
||||
@Schema(description = "详情", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "详情不能为空")
|
||||
private String details;
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.dataobject.autoresponse;
|
||||
|
||||
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_kefu_auto_response")
|
||||
@KeySequence("promotion_kefu_auto_response_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class AutoResponseDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 关键字
|
||||
*/
|
||||
private String keyword;
|
||||
/**
|
||||
* 回复类型,文字消息/0,图片消息/1
|
||||
*
|
||||
* 枚举 {@link TODO kefu_auto_response_type 对应的类}
|
||||
*/
|
||||
private Integer type;
|
||||
/**
|
||||
* 回复内容
|
||||
*/
|
||||
private String content;
|
||||
/**
|
||||
* 是否开启,开启/1,关闭/0
|
||||
*
|
||||
* 枚举 {@link TODO kefu_auto_response_status 对应的类}
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.dataobject.leaveword;
|
||||
|
||||
import lombok.*;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
|
||||
/**
|
||||
* 用户留言 DO
|
||||
*
|
||||
* @author 管理员
|
||||
*/
|
||||
@TableName("promotion_kefu_leave_word")
|
||||
@KeySequence("promotion_kefu_leave_word_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class LeaveWordDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 电话
|
||||
*/
|
||||
private String phone;
|
||||
/**
|
||||
* 留言内容
|
||||
*/
|
||||
private String content;
|
||||
/**
|
||||
* 回复内容
|
||||
*/
|
||||
private String response;
|
||||
/**
|
||||
* 状态
|
||||
*
|
||||
* 枚举 {@link TODO kefu_leave_word_status 对应的类}
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.dataobject.supportstaff;
|
||||
|
||||
import lombok.*;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
|
||||
/**
|
||||
* 客服人员 DO
|
||||
*
|
||||
* @author 管理员
|
||||
*/
|
||||
@TableName("promotion_kefu_support_staff")
|
||||
@KeySequence("promotion_kefu_support_staff_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SupportStaffDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@TableId
|
||||
private Integer id;
|
||||
/**
|
||||
* 客服名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 客服头像
|
||||
*/
|
||||
private String pic;
|
||||
/**
|
||||
* 手机号码
|
||||
*/
|
||||
private String phone;
|
||||
/**
|
||||
* 登录账号
|
||||
*/
|
||||
private String account;
|
||||
/**
|
||||
* 登录密码
|
||||
*/
|
||||
private String password;
|
||||
/**
|
||||
* 客服状态
|
||||
*
|
||||
* 枚举 {@link TODO kefu_support_staff_status 对应的类}
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 手机订单管理
|
||||
*
|
||||
* 枚举 {@link TODO kefu_support_staff_order_manage 对应的类}
|
||||
*/
|
||||
private Integer orderManage;
|
||||
/**
|
||||
* 订单通知
|
||||
*
|
||||
* 枚举 {@link TODO kefu_support_staff_order_inform 对应的类}
|
||||
*/
|
||||
private Integer orderInform;
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.dataobject.verbaltrick;
|
||||
|
||||
import lombok.*;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
|
||||
/**
|
||||
* 客服话术 DO
|
||||
*
|
||||
* @author 管理员
|
||||
*/
|
||||
@TableName("promotion_kefu_verbal_trick")
|
||||
@KeySequence("promotion_kefu_verbal_trick_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class VerbalTrickDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 分类
|
||||
*
|
||||
* 枚举 {@link TODO kefu_verbal_trick_type 对应的类}
|
||||
*/
|
||||
private Integer type;
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
private String title;
|
||||
/**
|
||||
* 详情
|
||||
*/
|
||||
private String details;
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.mysql.autoresponse;
|
||||
|
||||
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.autoresponse.AutoResponseDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.autoresponse.vo.*;
|
||||
|
||||
/**
|
||||
* 自动回复 Mapper
|
||||
*
|
||||
* @author 管理员
|
||||
*/
|
||||
@Mapper
|
||||
public interface AutoResponseMapper extends BaseMapperX<AutoResponseDO> {
|
||||
|
||||
default PageResult<AutoResponseDO> selectPage(AutoResponsePageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<AutoResponseDO>()
|
||||
.eqIfPresent(AutoResponseDO::getKeyword, reqVO.getKeyword())
|
||||
.eqIfPresent(AutoResponseDO::getType, reqVO.getType())
|
||||
.eqIfPresent(AutoResponseDO::getContent, reqVO.getContent())
|
||||
.eqIfPresent(AutoResponseDO::getStatus, reqVO.getStatus())
|
||||
.betweenIfPresent(AutoResponseDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(AutoResponseDO::getId));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.mysql.leaveword;
|
||||
|
||||
|
||||
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.leaveword.LeaveWordDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.leaveword.vo.*;
|
||||
|
||||
/**
|
||||
* 用户留言 Mapper
|
||||
*
|
||||
* @author 管理员
|
||||
*/
|
||||
@Mapper
|
||||
public interface LeaveWordMapper extends BaseMapperX<LeaveWordDO> {
|
||||
|
||||
default PageResult<LeaveWordDO> selectPage(LeaveWordPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<LeaveWordDO>()
|
||||
.likeIfPresent(LeaveWordDO::getName, reqVO.getName())
|
||||
.eqIfPresent(LeaveWordDO::getPhone, reqVO.getPhone())
|
||||
.eqIfPresent(LeaveWordDO::getContent, reqVO.getContent())
|
||||
.eqIfPresent(LeaveWordDO::getStatus, reqVO.getStatus())
|
||||
.betweenIfPresent(LeaveWordDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(LeaveWordDO::getId));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.mysql.supportstaff;
|
||||
|
||||
|
||||
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.supportstaff.SupportStaffDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.supportstaff.vo.*;
|
||||
|
||||
/**
|
||||
* 客服人员 Mapper
|
||||
*
|
||||
* @author 管理员
|
||||
*/
|
||||
@Mapper
|
||||
public interface SupportStaffMapper extends BaseMapperX<SupportStaffDO> {
|
||||
|
||||
default PageResult<SupportStaffDO> selectPage(SupportStaffPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<SupportStaffDO>()
|
||||
.likeIfPresent(SupportStaffDO::getName, reqVO.getName())
|
||||
.eqIfPresent(SupportStaffDO::getPhone, reqVO.getPhone())
|
||||
.eqIfPresent(SupportStaffDO::getAccount, reqVO.getAccount())
|
||||
.eqIfPresent(SupportStaffDO::getPassword, reqVO.getPassword())
|
||||
.eqIfPresent(SupportStaffDO::getStatus, reqVO.getStatus())
|
||||
.eqIfPresent(SupportStaffDO::getOrderManage, reqVO.getOrderManage())
|
||||
.eqIfPresent(SupportStaffDO::getOrderInform, reqVO.getOrderInform())
|
||||
.betweenIfPresent(SupportStaffDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(SupportStaffDO::getId));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.mysql.verbaltrick;
|
||||
|
||||
|
||||
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.verbaltrick.VerbalTrickDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.verbaltrick.vo.*;
|
||||
|
||||
/**
|
||||
* 客服话术 Mapper
|
||||
*
|
||||
* @author 管理员
|
||||
*/
|
||||
@Mapper
|
||||
public interface VerbalTrickMapper extends BaseMapperX<VerbalTrickDO> {
|
||||
|
||||
default PageResult<VerbalTrickDO> selectPage(VerbalTrickPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<VerbalTrickDO>()
|
||||
.eqIfPresent(VerbalTrickDO::getType, reqVO.getType())
|
||||
.eqIfPresent(VerbalTrickDO::getTitle, reqVO.getTitle())
|
||||
.eqIfPresent(VerbalTrickDO::getDetails, reqVO.getDetails())
|
||||
.betweenIfPresent(VerbalTrickDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(VerbalTrickDO::getId));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.autoresponse;
|
||||
|
||||
import java.util.*;
|
||||
import javax.validation.*;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.autoresponse.vo.*;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.autoresponse.AutoResponseDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
|
||||
/**
|
||||
* 自动回复 Service 接口
|
||||
*
|
||||
* @author 管理员
|
||||
*/
|
||||
public interface AutoResponseService {
|
||||
|
||||
/**
|
||||
* 创建自动回复
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createAutoResponse(@Valid AutoResponseSaveReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新自动回复
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateAutoResponse(@Valid AutoResponseSaveReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除自动回复
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteAutoResponse(Long id);
|
||||
|
||||
/**
|
||||
* 获得自动回复
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 自动回复
|
||||
*/
|
||||
AutoResponseDO getAutoResponse(Long id);
|
||||
|
||||
/**
|
||||
* 获得自动回复分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 自动回复分页
|
||||
*/
|
||||
PageResult<AutoResponseDO> getAutoResponsePage(AutoResponsePageReqVO pageReqVO);
|
||||
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.autoresponse;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.autoresponse.vo.*;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.autoresponse.AutoResponseDO;
|
||||
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.autoresponse.AutoResponseMapper;
|
||||
|
||||
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 AutoResponseServiceImpl implements AutoResponseService {
|
||||
|
||||
@Resource
|
||||
private AutoResponseMapper autoResponseMapper;
|
||||
|
||||
@Override
|
||||
public Long createAutoResponse(AutoResponseSaveReqVO createReqVO) {
|
||||
// 插入
|
||||
AutoResponseDO autoResponse = BeanUtils.toBean(createReqVO, AutoResponseDO.class);
|
||||
autoResponseMapper.insert(autoResponse);
|
||||
// 返回
|
||||
return autoResponse.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAutoResponse(AutoResponseSaveReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateAutoResponseExists(updateReqVO.getId());
|
||||
// 更新
|
||||
AutoResponseDO updateObj = BeanUtils.toBean(updateReqVO, AutoResponseDO.class);
|
||||
autoResponseMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAutoResponse(Long id) {
|
||||
// 校验存在
|
||||
validateAutoResponseExists(id);
|
||||
// 删除
|
||||
autoResponseMapper.deleteById(id);
|
||||
}
|
||||
|
||||
private void validateAutoResponseExists(Long id) {
|
||||
if (autoResponseMapper.selectById(id) == null) {
|
||||
throw exception(AUTO_RESPONSE_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AutoResponseDO getAutoResponse(Long id) {
|
||||
return autoResponseMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<AutoResponseDO> getAutoResponsePage(AutoResponsePageReqVO pageReqVO) {
|
||||
return autoResponseMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.leaveword;
|
||||
|
||||
import java.util.*;
|
||||
import javax.validation.*;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.leaveword.vo.*;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.leaveword.LeaveWordDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
|
||||
/**
|
||||
* 用户留言 Service 接口
|
||||
*
|
||||
* @author 管理员
|
||||
*/
|
||||
public interface LeaveWordService {
|
||||
|
||||
/**
|
||||
* 创建用户留言
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createLeaveWord(@Valid LeaveWordSaveReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新用户留言
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateLeaveWord(@Valid LeaveWordSaveReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除用户留言
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteLeaveWord(Long id);
|
||||
|
||||
/**
|
||||
* 获得用户留言
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 用户留言
|
||||
*/
|
||||
LeaveWordDO getLeaveWord(Long id);
|
||||
|
||||
/**
|
||||
* 获得用户留言分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 用户留言分页
|
||||
*/
|
||||
PageResult<LeaveWordDO> getLeaveWordPage(LeaveWordPageReqVO pageReqVO);
|
||||
|
||||
|
||||
/**
|
||||
* 回复用户留言
|
||||
* @param id
|
||||
* @param response
|
||||
* @return
|
||||
*/
|
||||
boolean addResponse(String id,String response);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.leaveword;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.leaveword.vo.*;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.leaveword.LeaveWordDO;
|
||||
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.leaveword.LeaveWordMapper;
|
||||
|
||||
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 LeaveWordServiceImpl implements LeaveWordService {
|
||||
|
||||
@Resource
|
||||
private LeaveWordMapper leaveWordMapper;
|
||||
|
||||
@Override
|
||||
public Long createLeaveWord(LeaveWordSaveReqVO createReqVO) {
|
||||
// 插入
|
||||
LeaveWordDO leaveWord = BeanUtils.toBean(createReqVO, LeaveWordDO.class);
|
||||
leaveWordMapper.insert(leaveWord);
|
||||
// 返回
|
||||
return leaveWord.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLeaveWord(LeaveWordSaveReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateLeaveWordExists(updateReqVO.getId());
|
||||
// 更新
|
||||
LeaveWordDO updateObj = BeanUtils.toBean(updateReqVO, LeaveWordDO.class);
|
||||
leaveWordMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteLeaveWord(Long id) {
|
||||
// 校验存在
|
||||
validateLeaveWordExists(id);
|
||||
// 删除
|
||||
leaveWordMapper.deleteById(id);
|
||||
}
|
||||
|
||||
private void validateLeaveWordExists(Long id) {
|
||||
if (leaveWordMapper.selectById(id) == null) {
|
||||
throw exception(LEAVE_WORD_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LeaveWordDO getLeaveWord(Long id) {
|
||||
return leaveWordMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<LeaveWordDO> getLeaveWordPage(LeaveWordPageReqVO pageReqVO) {
|
||||
return leaveWordMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addResponse(String id, String response) {
|
||||
LeaveWordDO leaveWordDO = leaveWordMapper.selectOne("id", id);
|
||||
leaveWordDO.setResponse(leaveWordDO.getResponse());
|
||||
leaveWordDO.setStatus(1);
|
||||
int i = leaveWordMapper.updateById(leaveWordDO);
|
||||
if (i >= 1){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.supportstaff;
|
||||
|
||||
import javax.validation.*;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.supportstaff.vo.*;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.supportstaff.SupportStaffDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
|
||||
/**
|
||||
* 客服人员 Service 接口
|
||||
*
|
||||
* @author 管理员
|
||||
*/
|
||||
public interface SupportStaffService {
|
||||
|
||||
/**
|
||||
* 创建客服人员
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Integer createSupportStaff(@Valid SupportStaffSaveReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新客服人员
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateSupportStaff(@Valid SupportStaffSaveReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除客服人员
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteSupportStaff(Integer id);
|
||||
|
||||
/**
|
||||
* 获得客服人员
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 客服人员
|
||||
*/
|
||||
SupportStaffDO getSupportStaff(Integer id);
|
||||
|
||||
/**
|
||||
* 获得客服人员分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 客服人员分页
|
||||
*/
|
||||
PageResult<SupportStaffDO> getSupportStaffPage(SupportStaffPageReqVO pageReqVO);
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.supportstaff;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.supportstaff.vo.*;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.supportstaff.SupportStaffDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.promotion.dal.mysql.supportstaff.SupportStaffMapper;
|
||||
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 SupportStaffServiceImpl implements SupportStaffService {
|
||||
|
||||
@Resource
|
||||
private SupportStaffMapper supportStaffMapper;
|
||||
|
||||
@Override
|
||||
public Integer createSupportStaff(SupportStaffSaveReqVO createReqVO) {
|
||||
// 插入
|
||||
SupportStaffDO supportStaff = BeanUtils.toBean(createReqVO, SupportStaffDO.class);
|
||||
supportStaffMapper.insert(supportStaff);
|
||||
// 返回
|
||||
return supportStaff.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSupportStaff(SupportStaffSaveReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateSupportStaffExists(updateReqVO.getId());
|
||||
// 更新
|
||||
SupportStaffDO updateObj = BeanUtils.toBean(updateReqVO, SupportStaffDO.class);
|
||||
supportStaffMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteSupportStaff(Integer id) {
|
||||
// 校验存在
|
||||
validateSupportStaffExists(id);
|
||||
// 删除
|
||||
supportStaffMapper.deleteById(id);
|
||||
}
|
||||
|
||||
private void validateSupportStaffExists(Integer id) {
|
||||
if (supportStaffMapper.selectById(id) == null) {
|
||||
throw exception(SUPPORT_STAFF_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SupportStaffDO getSupportStaff(Integer id) {
|
||||
return supportStaffMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<SupportStaffDO> getSupportStaffPage(SupportStaffPageReqVO pageReqVO) {
|
||||
return supportStaffMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.verbaltrick;
|
||||
|
||||
import java.util.*;
|
||||
import javax.validation.*;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.verbaltrick.vo.*;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.verbaltrick.VerbalTrickDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
|
||||
/**
|
||||
* 客服话术 Service 接口
|
||||
*
|
||||
* @author 管理员
|
||||
*/
|
||||
public interface VerbalTrickService {
|
||||
|
||||
/**
|
||||
* 创建客服话术
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createVerbalTrick(@Valid VerbalTrickSaveReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新客服话术
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateVerbalTrick(@Valid VerbalTrickSaveReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除客服话术
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteVerbalTrick(Long id);
|
||||
|
||||
/**
|
||||
* 获得客服话术
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 客服话术
|
||||
*/
|
||||
VerbalTrickDO getVerbalTrick(Long id);
|
||||
|
||||
/**
|
||||
* 获得客服话术分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 客服话术分页
|
||||
*/
|
||||
PageResult<VerbalTrickDO> getVerbalTrickPage(VerbalTrickPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 获取话术数据
|
||||
* @return
|
||||
*/
|
||||
List<VerbalTrickDO> getVerbalTrickList();
|
||||
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.verbaltrick;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.verbaltrick.vo.*;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.verbaltrick.VerbalTrickDO;
|
||||
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.verbaltrick.VerbalTrickMapper;
|
||||
|
||||
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 VerbalTrickServiceImpl implements VerbalTrickService {
|
||||
|
||||
@Resource
|
||||
private VerbalTrickMapper verbalTrickMapper;
|
||||
|
||||
@Override
|
||||
public Long createVerbalTrick(VerbalTrickSaveReqVO createReqVO) {
|
||||
// 插入
|
||||
VerbalTrickDO verbalTrick = BeanUtils.toBean(createReqVO, VerbalTrickDO.class);
|
||||
verbalTrickMapper.insert(verbalTrick);
|
||||
// 返回
|
||||
return verbalTrick.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateVerbalTrick(VerbalTrickSaveReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateVerbalTrickExists(updateReqVO.getId());
|
||||
// 更新
|
||||
VerbalTrickDO updateObj = BeanUtils.toBean(updateReqVO, VerbalTrickDO.class);
|
||||
verbalTrickMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteVerbalTrick(Long id) {
|
||||
// 校验存在
|
||||
validateVerbalTrickExists(id);
|
||||
// 删除
|
||||
verbalTrickMapper.deleteById(id);
|
||||
}
|
||||
|
||||
private void validateVerbalTrickExists(Long id) {
|
||||
if (verbalTrickMapper.selectById(id) == null) {
|
||||
throw exception(VERBAL_TRICK_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public VerbalTrickDO getVerbalTrick(Long id) {
|
||||
return verbalTrickMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<VerbalTrickDO> getVerbalTrickPage(VerbalTrickPageReqVO pageReqVO) {
|
||||
return verbalTrickMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VerbalTrickDO> getVerbalTrickList() {
|
||||
return verbalTrickMapper.selectList();
|
||||
}
|
||||
|
||||
}
|
@ -42,6 +42,7 @@ import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
|
||||
@Validated
|
||||
public class PayChannelServiceImpl implements PayChannelService {
|
||||
|
||||
|
||||
/**
|
||||
* {@link PayClient} 缓存,通过它异步清空 smsClientFactory
|
||||
*/
|
||||
|
@ -2,13 +2,10 @@ package cn.iocoder.yudao.module.srbscribe.controller.admin.reservation.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
|
||||
|
@ -38,50 +38,4 @@ public class AppBrandController {
|
||||
return success(BeanUtils.toBean(pageResult, LitemallBrandRespVO.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出医馆管理列表
|
||||
*/
|
||||
// @PostMapping("/export")
|
||||
// public void export(HttpServletResponse response, LitemallBrand litemallBrand) throws IOException {
|
||||
// List<LitemallBrand> list = litemallBrandService.selectLitemallBrandList(litemallBrand);
|
||||
// ExcelUtil<LitemallBrand> util = new ExcelUtil<LitemallBrand>(LitemallBrand.class);
|
||||
// util.exportExcel(response, list, "医馆管理数据");
|
||||
// }
|
||||
|
||||
/**
|
||||
* 获取医馆管理详细信息
|
||||
*/
|
||||
// @GetMapping(value = "/{id}")
|
||||
// public AjaxResult getInfo(@PathVariable("id") Integer id) {
|
||||
// OrganizationDO organization = organizationService.getOrganization(id);
|
||||
// return AjaxResult.success(organization);
|
||||
// }
|
||||
|
||||
/**
|
||||
* 新增医馆管理
|
||||
*/
|
||||
// @PostMapping
|
||||
// public CommonResult<Integer> add(@RequestBody OrganizationSaveReqVO createReqVO) {
|
||||
// return success(organizationService.createOrganization(createReqVO));
|
||||
// }
|
||||
|
||||
/**
|
||||
* 修改医馆管理
|
||||
*/
|
||||
// @PutMapping
|
||||
// public AjaxResult edit(@RequestBody LitemallBrand litemallBrand)
|
||||
// {
|
||||
// return toAjax(litemallBrandService.updateLitemallBrand(litemallBrand));
|
||||
// }
|
||||
|
||||
/**
|
||||
* 删除医馆管理
|
||||
*/
|
||||
// @DeleteMapping("/{ids}")
|
||||
// public AjaxResult remove(@PathVariable Long[] ids)
|
||||
// {
|
||||
// return toAjax(litemallBrandService.deleteLitemallBrandByIds(ids));
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
@ -7,18 +7,15 @@ import cn.iocoder.yudao.module.srbscribe.controller.admin.reservation.vo.Litemal
|
||||
import cn.iocoder.yudao.module.srbscribe.controller.admin.reservation.vo.LitemallReservationRespVO;
|
||||
import cn.iocoder.yudao.module.srbscribe.controller.admin.reservation.vo.LitemallReservationSaveReqVO;
|
||||
import cn.iocoder.yudao.module.srbscribe.dal.dataobject.reservation.LitemallReservationDO;
|
||||
import cn.iocoder.yudao.module.srbscribe.dal.dataobject.technician.LitemallTechnicianDO;
|
||||
import cn.iocoder.yudao.module.srbscribe.service.reservation.LitemallReservationService;
|
||||
import cn.iocoder.yudao.module.srbscribe.util.AjaxResult;
|
||||
import cn.iocoder.yudao.module.srbscribe.util.StringUtils;
|
||||
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
|
||||
import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
|
||||
@ -49,7 +46,6 @@ public class AppReservationController {
|
||||
*/
|
||||
@GetMapping(value = "/type")
|
||||
public AjaxResult dictType() {
|
||||
// List<SysDictData> data = dictTypeService.selectDictDataByType("tech_type");
|
||||
List<DictDataRespDTO> dictDataList = dictDataApi.getDictDataList("types");
|
||||
if (StringUtils.isNull(dictDataList)) {
|
||||
dictDataList = new ArrayList<DictDataRespDTO>();
|
||||
@ -58,43 +54,6 @@ public class AppReservationController {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 导出预约管理列表
|
||||
*/
|
||||
// @PostMapping("/export")
|
||||
// public void export(HttpServletResponse response, LitemallReservation litemallReservation) throws IOException
|
||||
// {
|
||||
// List<LitemallReservation> list = litemallReservationService.selectLitemallReservationList(litemallReservation);
|
||||
// ExcelUtil<LitemallReservation> util = new ExcelUtil<LitemallReservation>(LitemallReservation.class);
|
||||
// util.exportExcel(response, list, "预约管理数据");
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * 获取预约管理详细信息
|
||||
// */
|
||||
// @GetMapping(value = "/{id}")
|
||||
// public CommonResult<SubscribeManageRespVO> getManage(@PathVariable("id") Long id) {
|
||||
// SubscribeManageDO manage = subscribeManageService.getManage(id);
|
||||
// return success(BeanUtils.toBean(manage, SubscribeManageRespVO.class));
|
||||
// }
|
||||
//
|
||||
|
||||
// /**
|
||||
// * 新增预约管理
|
||||
// */
|
||||
// @PostMapping
|
||||
// public CommonResult<Long> createLitemallReservation(@RequestBody LitemallReservationSaveReqVO createReqVO) {
|
||||
// return success(litemallReservationService.createLitemallReservation(createReqVO));
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * 新增预约管理
|
||||
// */
|
||||
// @PostMapping("/add")
|
||||
// public CommonResult<Long> createLitemallReservation(@RequestBody LitemallReservationSaveReqVO litemallReservationDO) {
|
||||
// return success(litemallReservationService.createReservation(litemallReservationDO));
|
||||
// }
|
||||
|
||||
/**
|
||||
* 新增预约管理
|
||||
*/
|
||||
@ -113,24 +72,6 @@ public class AppReservationController {
|
||||
}
|
||||
|
||||
|
||||
// /**
|
||||
// * 修改预约管理
|
||||
// */
|
||||
// @PutMapping
|
||||
// public CommonResult<Boolean> updateManage( @RequestBody SubscribeManageSaveReqVO updateReqVO) {
|
||||
// subscribeManageService.updateManage(updateReqVO);
|
||||
// return success(true);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 删除预约管理
|
||||
// */
|
||||
// @DeleteMapping("/{ids}")
|
||||
// public CommonResult<Boolean> deleteManage(@PathVariable("ids") Long[] ids) {
|
||||
// subscribeManageService.deleteList(ids);
|
||||
// return success(true);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,11 +4,8 @@ package cn.iocoder.yudao.module.srbscribe.controller.app.technician;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.srbscribe.controller.admin.reservation.vo.LitemallReservationPageReqVO;
|
||||
import cn.iocoder.yudao.module.srbscribe.controller.admin.reservation.vo.LitemallReservationRespVO;
|
||||
import cn.iocoder.yudao.module.srbscribe.controller.admin.technician.vo.LitemallTechnicianPageReqVO;
|
||||
import cn.iocoder.yudao.module.srbscribe.controller.admin.technician.vo.LitemallTechnicianRespVO;
|
||||
import cn.iocoder.yudao.module.srbscribe.controller.admin.technician.vo.LitemallTechnicianSaveReqVO;
|
||||
import cn.iocoder.yudao.module.srbscribe.dal.dataobject.reservation.LitemallReservationDO;
|
||||
import cn.iocoder.yudao.module.srbscribe.dal.dataobject.technician.LitemallTechnicianDO;
|
||||
import cn.iocoder.yudao.module.srbscribe.service.reservation.LitemallReservationService;
|
||||
@ -16,12 +13,8 @@ import cn.iocoder.yudao.module.srbscribe.service.technician.LitemallTechnicianSe
|
||||
import org.json.JSONException;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.json.JSONArray;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -53,39 +46,6 @@ public class AppTechnicianController {
|
||||
return success(BeanUtils.toBean(pageResult, LitemallTechnicianRespVO.class));
|
||||
}
|
||||
|
||||
|
||||
// /**
|
||||
// * 首页查询技师管理列表(名称去重)
|
||||
// */
|
||||
// @GetMapping("/listmain")
|
||||
// public CommonResult<PageResult<LitemallTechnicianRespVO>> listmain(LitemallTechnicianPageReqVO pageReqVO) {
|
||||
// PageResult<LitemallTechnicianDO> pageResult = litemallTechnicianService.getLitemallTechnicianPage(pageReqVO);
|
||||
// return success(BeanUtils.toBean(pageResult, LitemallTechnicianRespVO.class));
|
||||
// }
|
||||
|
||||
|
||||
// /**
|
||||
// * 查询技师管理列表
|
||||
// */
|
||||
// @GetMapping("/list")
|
||||
// public TableDataInfo list(LitemallTechnician litemallTechnician)
|
||||
// {
|
||||
// startPage();
|
||||
// List<LitemallTechnician> list = litemallTechnicianService.selectLitemallTechnicianList(litemallTechnician);
|
||||
// return getDataTable(list);
|
||||
// }
|
||||
// /**
|
||||
// * 首页查询技师管理列表(名称去重)
|
||||
// */
|
||||
// @GetMapping("/listmain")
|
||||
// public TableDataInfo listmain(LitemallTechnician litemallTechnician)
|
||||
// {
|
||||
// startPage();
|
||||
// List<LitemallTechnician> list = litemallTechnicianService.selectLitemallTechnicianListmian(litemallTechnician);
|
||||
// return getDataTable(list);
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* 查询技师管理详情
|
||||
*/
|
||||
@ -119,52 +79,6 @@ public class AppTechnicianController {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 导出技师管理列表
|
||||
*/
|
||||
// @PostMapping("/export")
|
||||
// public void export(HttpServletResponse response, LitemallTechnician litemallTechnician) throws IOException
|
||||
// {
|
||||
// List<LitemallTechnician> list = litemallTechnicianService.selectLitemallTechnicianList(litemallTechnician);
|
||||
// ExcelUtil<LitemallTechnician> util = new ExcelUtil<LitemallTechnician>(LitemallTechnician.class);
|
||||
// util.exportExcel(response, list, "技师管理数据");
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * 获取技师管理详细信息
|
||||
// */
|
||||
// @GetMapping(value = "/{id}")
|
||||
// public CommonResult<StaffRespVO> getInfo(@PathVariable("id") Long id) {
|
||||
// StaffDO staff = staffService.getStaff(id);
|
||||
// return success(BeanUtils.toBean(staff, StaffRespVO.class));
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 新增技师管理
|
||||
// */
|
||||
// @PostMapping
|
||||
// public CommonResult<Long> add(@Valid @RequestBody StaffSaveReqVO createReqVO) {
|
||||
// return success(staffService.createStaff(createReqVO));
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 修改技师管理
|
||||
// */
|
||||
// @PutMapping
|
||||
// public CommonResult<Boolean> updateStaff( @RequestBody StaffSaveReqVO updateReqVO) {
|
||||
// staffService.updateStaff(updateReqVO);
|
||||
// return success(true);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 删除技师管理
|
||||
// */
|
||||
// @DeleteMapping("/{ids}")
|
||||
// public CommonResult<Boolean> deleteStaff(@PathVariable("ids") Long id) {
|
||||
// staffService.deleteStaff(id);
|
||||
// return success(true);
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,6 @@
|
||||
package cn.iocoder.yudao.module.srbscribe.dal.dataobject.reservation;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user