|
@@ -0,0 +1,657 @@
|
|
|
|
|
+<script setup>
|
|
|
|
|
+import KtCommonTable from "@/views/Core/KtCommonTable.vue";
|
|
|
|
|
+import dayjs from "dayjs";
|
|
|
|
|
+
|
|
|
|
|
+export default {
|
|
|
|
|
+ components: {
|
|
|
|
|
+ KtCommonTable,
|
|
|
|
|
+ },
|
|
|
|
|
+ data() {
|
|
|
|
|
+ return {
|
|
|
|
|
+ pageResult: [],
|
|
|
|
|
+ queryCondition: {
|
|
|
|
|
+ nickname: "",
|
|
|
|
|
+ pageNum: 1,
|
|
|
|
|
+ pageSize: 10,
|
|
|
|
|
+ },
|
|
|
|
|
+ imageUrl: "",
|
|
|
|
|
+ dialogVisible: false,
|
|
|
|
|
+ dialogType: 'add',
|
|
|
|
|
+ uploadProgress: 0,
|
|
|
|
|
+ userLoading: false,
|
|
|
|
|
+ defaultId: "",
|
|
|
|
|
+ //提交
|
|
|
|
|
+ submitLoading: false,
|
|
|
|
|
+ // 表单数据
|
|
|
|
|
+ form: {
|
|
|
|
|
+ id: null,
|
|
|
|
|
+ nickname: '',
|
|
|
|
|
+ avatar: '',
|
|
|
|
|
+ userId: null,
|
|
|
|
|
+ departmentId: null,
|
|
|
|
|
+ receptionist: '',
|
|
|
|
|
+ receptionistId: null
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ dialogVisibleDuty: false,
|
|
|
|
|
+
|
|
|
|
|
+ allServiceList: [], // 从接口获取的客服列表
|
|
|
|
|
+ formData: {
|
|
|
|
|
+ nickname: '',
|
|
|
|
|
+ customerId: '',
|
|
|
|
|
+ dutyCustomerId: null,
|
|
|
|
|
+ dutyDateTimeList: [{
|
|
|
|
|
+ startTime: new Date().setHours(8, 30, 0),
|
|
|
|
|
+ endTime: new Date().setHours(18, 30, 0)
|
|
|
|
|
+ }]
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 选项数据
|
|
|
|
|
+ backendOptions: [],
|
|
|
|
|
+ departmentTree: [],
|
|
|
|
|
+ wecomUsers: [],
|
|
|
|
|
+
|
|
|
|
|
+ // 树配置
|
|
|
|
|
+ treeProps: {
|
|
|
|
|
+ label: 'deptName',
|
|
|
|
|
+ children: 'childDept',
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 验证规则
|
|
|
|
|
+ columns: [ //数据列
|
|
|
|
|
+ {prop: "avatarUrl", label: "客服头像", formatter: this.imgFormatter},
|
|
|
|
|
+ {prop: "nickname", label: "客服昵称"},
|
|
|
|
|
+ {prop: "username", label: "姓名"},
|
|
|
|
|
+ {prop: "userId", label: "工号"},
|
|
|
|
|
+ {prop: "receptionist", label: "企微用户"},
|
|
|
|
|
+ {prop: "dutyCustomer", label: "值班客服"},
|
|
|
|
|
+ {prop: "dutyDatetime", label: "值班时间", minWidth: 200, formatter: this.dutyDatetimeFormatter},
|
|
|
|
|
+ ],
|
|
|
|
|
+
|
|
|
|
|
+ rules: {
|
|
|
|
|
+ nickname: [
|
|
|
|
|
+ {required: true, message: '请输入客服昵称', trigger: 'blur'},
|
|
|
|
|
+ {min: 2, max: 16, message: '长度在2到16个字符', trigger: 'blur'}
|
|
|
|
|
+ ],
|
|
|
|
|
+ userId: [
|
|
|
|
|
+ {required: true, message: '请选择后线人员', trigger: 'change'},
|
|
|
|
|
+ ],
|
|
|
|
|
+ departmentId: [
|
|
|
|
|
+ {required: true, message: '请选择部门', trigger: 'change'}
|
|
|
|
|
+ ],
|
|
|
|
|
+ receptionistId: [
|
|
|
|
|
+ {required: true, message: '请选择企微用户', trigger: 'change'}
|
|
|
|
|
+ ]
|
|
|
|
|
+ },
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ created() {
|
|
|
|
|
+ this.uploadDefaultImage()
|
|
|
|
|
+ this.queryPage();
|
|
|
|
|
+ },
|
|
|
|
|
+ methods: {
|
|
|
|
|
+ changeDateTime(value) {
|
|
|
|
|
+ return dayjs(value).format("yyyy-MM-dd HH:mm:ss");
|
|
|
|
|
+ },
|
|
|
|
|
+ queryPage() {
|
|
|
|
|
+ this.$api.customerManage.pageQuery(this.queryCondition).then((res) => {
|
|
|
|
|
+ if (res.code === 200) {
|
|
|
|
|
+ this.pageResult = res.data
|
|
|
|
|
+ this.queryCondition.pageNum = res.data.pageNum
|
|
|
|
|
+ this.queryCondition.pageSize = res.data.pageSize
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.$message.error(res.msg)
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ findPage(data) {
|
|
|
|
|
+ if (data.pageRequest.pageNum !== this.queryCondition.pageNum) {
|
|
|
|
|
+ this.queryCondition.pageNum = data.pageRequest.pageNum;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (data.pageRequest.pageSize !== this.queryCondition.pageSize) {
|
|
|
|
|
+ this.queryCondition.pageSize = data.pageRequest.pageSize;
|
|
|
|
|
+ }
|
|
|
|
|
+ this.queryPage();
|
|
|
|
|
+ },
|
|
|
|
|
+ // 删除客服
|
|
|
|
|
+ deleteCustomer({row}) {
|
|
|
|
|
+ this.$confirm('此操作将永久删除客服, 是否继续?', '提示', {
|
|
|
|
|
+ confirmButtonText: '确定',
|
|
|
|
|
+ cancelButtonText: '取消',
|
|
|
|
|
+ type: 'warning'
|
|
|
|
|
+ }).then(() => {
|
|
|
|
|
+ this.$api.customerManage.deleteCustomer(row.id).then((res) => {
|
|
|
|
|
+ if (res.code === 200) {
|
|
|
|
|
+ this.$message({
|
|
|
|
|
+ type: 'success',
|
|
|
|
|
+ message: '删除成功!'
|
|
|
|
|
+ });
|
|
|
|
|
+ this.queryPage();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.$message.error(res.msg);
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ }).catch(() => {
|
|
|
|
|
+ this.$message({
|
|
|
|
|
+ type: 'info',
|
|
|
|
|
+ message: '已取消删除'
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+ // 清除值班配置
|
|
|
|
|
+ clearDutyConfig({row}) {
|
|
|
|
|
+ this.$confirm('此操作将永久清除值班配置, 是否继续?', '提示', {
|
|
|
|
|
+ confirmButtonText: '确定',
|
|
|
|
|
+ cancelButtonText: '取消',
|
|
|
|
|
+ type: 'warning'
|
|
|
|
|
+ }).then(() => {
|
|
|
|
|
+ this.$api.customerManage.clearDutyConfig(row.id).then((res) => {
|
|
|
|
|
+ if (res.code === 200) {
|
|
|
|
|
+ this.$message({
|
|
|
|
|
+ type: 'success',
|
|
|
|
|
+ message: '清除成功!'
|
|
|
|
|
+ });
|
|
|
|
|
+ this.queryPage();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.$message.error(res.msg);
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ }).catch(() => {
|
|
|
|
|
+ this.$message({
|
|
|
|
|
+ type: 'info',
|
|
|
|
|
+ message: '已取消清除'
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+ handleClick() {
|
|
|
|
|
+ if (this.submitLoading) return;
|
|
|
|
|
+ this.submitLoading = true;
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ this.handleSubmit();
|
|
|
|
|
+ this.submitLoading = false;
|
|
|
|
|
+ }, 3000);
|
|
|
|
|
+ },
|
|
|
|
|
+ // 打开弹窗(新增)
|
|
|
|
|
+ handleAdd() {
|
|
|
|
|
+ this.dialogType = 'add'
|
|
|
|
|
+ this.dialogVisible = true
|
|
|
|
|
+ this.resetForm()
|
|
|
|
|
+ this.loadDepartment();
|
|
|
|
|
+ this.loadBackendOptions();
|
|
|
|
|
+ },
|
|
|
|
|
+ // 打开弹窗(编辑)
|
|
|
|
|
+ handleEdit({row}) {
|
|
|
|
|
+ this.dialogType = 'edit'
|
|
|
|
|
+ this.dialogVisible = true
|
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
|
+ this.loadEditData(row)
|
|
|
|
|
+ this.loadBackendOptions();
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ imgFormatter(row) {
|
|
|
|
|
+ return <img src={"" + process.env.BASE_URL + row.avatarUrl + ""} style="width: 74px; height: 74px"></img>;
|
|
|
|
|
+ },
|
|
|
|
|
+ dutyDatetimeFormatter(row) {
|
|
|
|
|
+ if (row.dutyDatetime != null && row.dutyDatetime.length > 0) {
|
|
|
|
|
+ return row.dutyDatetime.map(x => {
|
|
|
|
|
+ return <el-tag>{x} </el-tag>
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ // 加载编辑数据
|
|
|
|
|
+ loadEditData(data) {
|
|
|
|
|
+ this.loadDepartment()
|
|
|
|
|
+ this.$refs.deptTree.setCurrentKey(data.departmentId)
|
|
|
|
|
+ this.loadDepartmentUsers(data.departmentId)
|
|
|
|
|
+ // 加载部门路径
|
|
|
|
|
+ if (data.id) {
|
|
|
|
|
+ this.form = {
|
|
|
|
|
+ id: data.id,
|
|
|
|
|
+ nickname: data.nickname,
|
|
|
|
|
+ avatar: data.avatar,
|
|
|
|
|
+ userId: data.userId,
|
|
|
|
|
+ departmentId: data.departmentId,
|
|
|
|
|
+ receptionist: data.receptionist,
|
|
|
|
|
+ receptionistId: data.receptionistId
|
|
|
|
|
+ }
|
|
|
|
|
+ this.imageUrl = process.env.BASE_URL + data.avatarUrl
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ // 加载后线人员选项
|
|
|
|
|
+ loadBackendOptions() {
|
|
|
|
|
+ this.$api.user.findHxUserList().then((res) => {
|
|
|
|
|
+ this.backendOptions = res.data
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ // 部门加载
|
|
|
|
|
+ loadDepartment() {
|
|
|
|
|
+ this.$api.customerManage.getDeptTree().then((rep) => {
|
|
|
|
|
+ this.departmentTree = rep.data
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ // 部门点击事件
|
|
|
|
|
+ async handleDeptClick(data) {
|
|
|
|
|
+ this.form.departmentId = data.deptId
|
|
|
|
|
+ await this.loadDepartmentUsers(data.deptId)
|
|
|
|
|
+ },
|
|
|
|
|
+ // 加载部门用户
|
|
|
|
|
+ async loadDepartmentUsers(departmentId) {
|
|
|
|
|
+ this.userLoading = true
|
|
|
|
|
+ try {
|
|
|
|
|
+ const {data} = await this.$api.customerManage.getDeptUser(departmentId)
|
|
|
|
|
+ this.wecomUsers = data
|
|
|
|
|
+ const isReceptionistId = this.wecomUsers.some(user => user.userId === this.form.receptionistId);
|
|
|
|
|
+ if (!isReceptionistId) {
|
|
|
|
|
+ this.form.receptionistId = null;
|
|
|
|
|
+ this.form.receptionist = null;
|
|
|
|
|
+ }
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ this.userLoading = false
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ // 上传图片
|
|
|
|
|
+ imageUpload(file) {
|
|
|
|
|
+ this.$refs.upload1.clearFiles();
|
|
|
|
|
+ const isImage = /\.(jpg|png)$/i.test(file.name)
|
|
|
|
|
+ const isLt2M = file.size / 1024 / 1024 < 2
|
|
|
|
|
+ if (!isImage) {
|
|
|
|
|
+ this.$message.error('只能上传png,jpg格式图片!')
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!isLt2M) {
|
|
|
|
|
+ this.$message.error('图片大小不能超过2MB!')
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+ let file1 = file.raw;
|
|
|
|
|
+ //转临时路径
|
|
|
|
|
+ this.imageUrl = window.URL.createObjectURL(file1);
|
|
|
|
|
+ const params = new FormData();
|
|
|
|
|
+ params.append("multipartFile", file1);
|
|
|
|
|
+ params.append("type", "avatar");
|
|
|
|
|
+ this.$api.letter.uploadFile(params).then((res) => {
|
|
|
|
|
+ if (res.code === 200) {
|
|
|
|
|
+ this.form.avatar = res.data.id;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.$message.error(res.msg);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ return true
|
|
|
|
|
+ },
|
|
|
|
|
+ async getLocalImageAsFile(imagePath) {
|
|
|
|
|
+ const response = await fetch(imagePath);
|
|
|
|
|
+ const blob = await response.blob();
|
|
|
|
|
+ return new File([blob], 'default-image.png', {type: blob.type});
|
|
|
|
|
+ },
|
|
|
|
|
+ //上传默认图片
|
|
|
|
|
+ async uploadDefaultImage() {
|
|
|
|
|
+ const imagePath = require('@/assets/customerAvatar.png'); // 本地图片路径
|
|
|
|
|
+ const file = await this.getLocalImageAsFile(imagePath);
|
|
|
|
|
+ const params = new FormData();
|
|
|
|
|
+ params.append("multipartFile", file);
|
|
|
|
|
+ params.append("type", "avatar");
|
|
|
|
|
+ this.$api.letter.uploadFile(params).then((res) => {
|
|
|
|
|
+ if (res.code === 200) {
|
|
|
|
|
+ this.defaultId = res.data.id;
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+ // 表单提交
|
|
|
|
|
+ async handleSubmit() {
|
|
|
|
|
+ await this.$refs.formRef.validate()
|
|
|
|
|
+ if (this.form.avatar == null || this.form.avatar.length === 0) {
|
|
|
|
|
+ this.form.avatar = this.defaultId
|
|
|
|
|
+ }
|
|
|
|
|
+ this.form.receptionist = this.wecomUsers.filter((item) => item.userId == this.form.receptionistId)[0].name
|
|
|
|
|
+ if (this.dialogType === 'add') {
|
|
|
|
|
+ this.$api.customerManage.addCustomer(this.form).then(res => {
|
|
|
|
|
+ if (res.code === 200) {
|
|
|
|
|
+ this.$message.success('操作成功')
|
|
|
|
|
+ this.$emit('success')
|
|
|
|
|
+ this.dialogVisible = false
|
|
|
|
|
+ this.queryPage()
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.$message.error(res.msg);
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ } else if (this.dialogType === 'edit') {
|
|
|
|
|
+ this.$api.customerManage.reviseCustomer(this.form.id, this.form).then(res => {
|
|
|
|
|
+ if (res.code === 200) {
|
|
|
|
|
+ this.$message.success('操作成功')
|
|
|
|
|
+ this.$emit('success')
|
|
|
|
|
+ this.dialogVisible = false
|
|
|
|
|
+ this.queryPage()
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.$message.error(res.msg);
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ // 重置表单
|
|
|
|
|
+ resetForm() {
|
|
|
|
|
+ this.form = {
|
|
|
|
|
+ id: null,
|
|
|
|
|
+ nickname: '',
|
|
|
|
|
+ avatar: '',
|
|
|
|
|
+ avatarUrl: '',
|
|
|
|
|
+ userId: null,
|
|
|
|
|
+ departmentId: null,
|
|
|
|
|
+ receptionist: '',
|
|
|
|
|
+ receptionistId: null
|
|
|
|
|
+ }
|
|
|
|
|
+ this.imageUrl = ''
|
|
|
|
|
+ },
|
|
|
|
|
+ // 重置值班规则表单
|
|
|
|
|
+ resetFormData() {
|
|
|
|
|
+ this.formData = {
|
|
|
|
|
+ nickname: '',
|
|
|
|
|
+ customerId: '',
|
|
|
|
|
+ dutyCustomerId: null,
|
|
|
|
|
+ dutyDateTimeList: [{
|
|
|
|
|
+ startTime: new Date().setHours(8, 30, 0),
|
|
|
|
|
+ endTime: new Date().setHours(18, 30, 0)
|
|
|
|
|
+ }]
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ // 弹窗关闭处理
|
|
|
|
|
+ handleClose() {
|
|
|
|
|
+ this.resetForm()
|
|
|
|
|
+ this.uploadProgress = 0
|
|
|
|
|
+ },
|
|
|
|
|
+ // 获取客服列表
|
|
|
|
|
+ getCustomerServiceList() {
|
|
|
|
|
+ this.$api.customerManage.getAll().then(res => {
|
|
|
|
|
+ this.allServiceList = res.data
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 获取详情数据
|
|
|
|
|
+ getDutyConfig(customerId) {
|
|
|
|
|
+ this.$api.customerManage.getDutyConfig(customerId).then(res => {
|
|
|
|
|
+ if (res.code === 200) {
|
|
|
|
|
+ const isReceptionistId = this.allServiceList.some(service => service.id === Number(res.data.dutyCustomerId));
|
|
|
|
|
+ if (isReceptionistId) {
|
|
|
|
|
+ this.formData.dutyCustomerId = Number(res.data.dutyCustomerId)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ res.data.dutyDateTimeList.map(item => {
|
|
|
|
|
+ this.startTime = dayjs(item.startTime).valueOf()
|
|
|
|
|
+ this.endTime = dayjs(item.endTime).valueOf()
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ this.formData.dutyDateTimeList = res.data.dutyDateTimeList
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ openDialog({row}) {
|
|
|
|
|
+ this.getCustomerServiceList()
|
|
|
|
|
+ this.getDutyConfig(row.id)
|
|
|
|
|
+ this.formData.customerId = row.id
|
|
|
|
|
+ this.formData.nickname = row.nickname
|
|
|
|
|
+ this.dialogVisibleDuty = true;
|
|
|
|
|
+ },
|
|
|
|
|
+ addTime() {
|
|
|
|
|
+ this.formData.dutyDateTimeList.push({
|
|
|
|
|
+ startTime: new Date().setHours(8, 30, 0),
|
|
|
|
|
+ endTime: new Date().setHours(18, 30, 0)
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+ removeTime(index) {
|
|
|
|
|
+ if (this.formData.dutyDateTimeList.length === 1) {
|
|
|
|
|
+ this.$message.warning('请至少保留一条数据');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ this.formData.dutyDateTimeList.splice(index, 1);
|
|
|
|
|
+ },
|
|
|
|
|
+ handleCancel() {
|
|
|
|
|
+ this.resetFormData();
|
|
|
|
|
+ this.dialogVisibleDuty = false;
|
|
|
|
|
+ this.$message({type: 'info', message: '已取消操作'});
|
|
|
|
|
+ },
|
|
|
|
|
+ dutyConfigData() {
|
|
|
|
|
+ return {
|
|
|
|
|
+ customerId: this.formData.customerId,
|
|
|
|
|
+ dutyCustomerId: this.formData.dutyCustomerId,
|
|
|
|
|
+ dutyDateTimeList: this.formData.dutyDateTimeList.map(t => ({
|
|
|
|
|
+ startTime: dayjs(t.startTime).format('YYYY-MM-DD HH:mm:ss'),
|
|
|
|
|
+ endTime: dayjs(t.endTime).format('YYYY-MM-DD HH:mm:ss')
|
|
|
|
|
+ }))
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ // 确认操作
|
|
|
|
|
+ handleConfirm() {
|
|
|
|
|
+ // 数据校验
|
|
|
|
|
+ if (!this.validateTime()) return;
|
|
|
|
|
+ // 提交逻辑(示例)
|
|
|
|
|
+ this.$api.customerManage.dutyConfig(this.dutyConfigData())
|
|
|
|
|
+ .then((res) => {
|
|
|
|
|
+ if (res.code === 200) {
|
|
|
|
|
+ this.$message.success('保存成功');
|
|
|
|
|
+ this.dialogVisibleDuty = false;
|
|
|
|
|
+ this.queryPage()
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.$message.error(res.msg);
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch(error => {
|
|
|
|
|
+ this.$message.error(`保存失败: ${error.message}`);
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 时间有效性校验
|
|
|
|
|
+ validateTime() {
|
|
|
|
|
+ for (const time of this.formData.dutyDateTimeList) {
|
|
|
|
|
+ if(time.startTime === null){
|
|
|
|
|
+ this.$message.error('开始时间必填');
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(time.endTime === null){
|
|
|
|
|
+ this.$message.error('结束时间必填');
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (new Date(time.startTime) >= new Date(time.endTime)) {
|
|
|
|
|
+ this.$message.error('结束时间必须晚于开始时间');
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ computed: {
|
|
|
|
|
+ showAddButton() {
|
|
|
|
|
+ return this.formData.dutyDateTimeList.length < 10;
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+}
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<template>
|
|
|
|
|
+
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <div class="container">
|
|
|
|
|
+ <el-form size="small" label-width="130px">
|
|
|
|
|
+ <el-row>
|
|
|
|
|
+ <el-col :span="6">
|
|
|
|
|
+ <el-form-item label="昵称">
|
|
|
|
|
+ <el-input v-model="queryCondition.nickname" placeholder="请输入昵称" class="widths" clearable></el-input>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-col>
|
|
|
|
|
+ <el-col :span="6">
|
|
|
|
|
+ <el-button type="primary" size="small" @click="queryPage">查询</el-button>
|
|
|
|
|
+ <el-button type="primary" size="small" @click="handleAdd">添加客服</el-button>
|
|
|
|
|
+ </el-col>
|
|
|
|
|
+ </el-row>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+ <kt-common-table :showBatchDelete="false" :data="pageResult" :operationWidth="250" :columns="columns"
|
|
|
|
|
+ @findPage="findPage"
|
|
|
|
|
+ button2Name="编辑" @handleButton2="handleEdit" button2Type="text"
|
|
|
|
|
+ button3Name="删除" @handleButton3="deleteCustomer" button3Type="text"
|
|
|
|
|
+ button4Name="值班配置" @handleButton4="openDialog" button4Type="text"
|
|
|
|
|
+ button5Name="清除值班配置" @handleButton5="clearDutyConfig" button5Type="text"
|
|
|
|
|
+ >
|
|
|
|
|
+ </kt-common-table>
|
|
|
|
|
+
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 弹窗主体 -->
|
|
|
|
|
+ <el-dialog
|
|
|
|
|
+ :title="dialogType === 'add' ? '新增客服' : '编辑客服'"
|
|
|
|
|
+ :visible.sync="dialogVisible"
|
|
|
|
|
+ width="700px"
|
|
|
|
|
+ :close-on-click-modal="false"
|
|
|
|
|
+ @closed="handleClose">
|
|
|
|
|
+ <el-form
|
|
|
|
|
+ ref="formRef"
|
|
|
|
|
+ :model="form"
|
|
|
|
|
+ :rules="rules"
|
|
|
|
|
+ label-width="100px"
|
|
|
|
|
+ label-position="right">
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 客服昵称 -->
|
|
|
|
|
+ <el-form-item label="客服昵称" prop="nickname">
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ v-model.trim="form.nickname"
|
|
|
|
|
+ placeholder="请输入2-16个字符"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ maxlength="16"/>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 客服头像 -->
|
|
|
|
|
+ <el-form-item label="客服头像" prop="avatar">
|
|
|
|
|
+ <el-upload
|
|
|
|
|
+ style="margin-bottom: 10px"
|
|
|
|
|
+ class="upload-demo"
|
|
|
|
|
+ action="#"
|
|
|
|
|
+ :limit="1"
|
|
|
|
|
+ accept=".png, .jpg, .jpeg"
|
|
|
|
|
+ :auto-upload="false"
|
|
|
|
|
+ :on-change="imageUpload"
|
|
|
|
|
+ :show-file-list="false"
|
|
|
|
|
+ list-type="picture-card"
|
|
|
|
|
+ ref="upload1"
|
|
|
|
|
+ >
|
|
|
|
|
+ <img v-if="imageUrl" :src="imageUrl" class="avatar" style="width: 148px; height: 148px" alt=""/>
|
|
|
|
|
+ <i v-else class="el-icon-plus avatar-uploader-icon"></i>
|
|
|
|
|
+ </el-upload>
|
|
|
|
|
+ <span>支持png,jpg格式图片,大小不超过2MB</span>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 后线人员 -->
|
|
|
|
|
+ <el-form-item label="后线人员" prop="userId">
|
|
|
|
|
+ <el-select
|
|
|
|
|
+ v-model="form.userId"
|
|
|
|
|
+ filterable
|
|
|
|
|
+ clearable
|
|
|
|
|
+ placeholder="请选择后线人员">
|
|
|
|
|
+ <el-option
|
|
|
|
|
+ v-for="item in backendOptions"
|
|
|
|
|
+ :key="item.id"
|
|
|
|
|
+ :label="item.name"
|
|
|
|
|
+ :value="item.id"/>
|
|
|
|
|
+ </el-select>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 企微部门树 -->
|
|
|
|
|
+ <el-form-item label="企微部门" prop="departmentId">
|
|
|
|
|
+ <el-tree
|
|
|
|
|
+ ref="deptTree"
|
|
|
|
|
+ :data="departmentTree"
|
|
|
|
|
+ :props="treeProps"
|
|
|
|
|
+ node-key="deptId"
|
|
|
|
|
+ highlight-current
|
|
|
|
|
+ @node-click="handleDeptClick"/>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 企微用户 -->
|
|
|
|
|
+ <el-form-item label="企微用户" prop="receptionistId">
|
|
|
|
|
+ <el-select
|
|
|
|
|
+ v-model="form.receptionistId"
|
|
|
|
|
+ :loading="userLoading"
|
|
|
|
|
+ filterable
|
|
|
|
|
+ clearable
|
|
|
|
|
+ placeholder="请先选择企微用户">
|
|
|
|
|
+ <el-option
|
|
|
|
|
+ v-for="user in wecomUsers"
|
|
|
|
|
+ :key="user.userId"
|
|
|
|
|
+ :label="user.name"
|
|
|
|
|
+ :value="user.userId"/>
|
|
|
|
|
+ </el-select>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+
|
|
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
|
|
+ <el-button @click="dialogVisible = false">取 消</el-button>
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ :disabled="submitLoading"
|
|
|
|
|
+ @click="handleClick">
|
|
|
|
|
+ 确 定
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-dialog>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 值班客服配置 -->
|
|
|
|
|
+ <el-dialog :visible.sync="dialogVisibleDuty" title="值班配置"
|
|
|
|
|
+ :close-on-click-modal="false">
|
|
|
|
|
+ <el-form :model="formData" label-width="100px" label-position="right">
|
|
|
|
|
+ <!-- 当前客服(只读) -->
|
|
|
|
|
+ <el-form-item label="当前客服">
|
|
|
|
|
+ <el-input v-model="formData.nickname" width="700px" clearable readonly></el-input>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 值班客服(可编辑) -->
|
|
|
|
|
+ <el-form-item label="值班客服">
|
|
|
|
|
+ <el-select v-model="formData.dutyCustomerId" placeholder="请选择">
|
|
|
|
|
+ <el-option
|
|
|
|
|
+ v-for="item in allServiceList"
|
|
|
|
|
+ :key="item.id"
|
|
|
|
|
+ :label="item.nickname"
|
|
|
|
|
+ :value="item.id">
|
|
|
|
|
+ </el-option>
|
|
|
|
|
+ </el-select>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 值班时间列表 -->
|
|
|
|
|
+ <el-form-item label="值班时间" v-for="(time, index) in formData.dutyDateTimeList" :key="index">
|
|
|
|
|
+ <el-date-picker
|
|
|
|
|
+ v-model="time.startTime"
|
|
|
|
|
+ type="datetime"
|
|
|
|
|
+ format="yyyy-MM-dd HH:mm:ss"
|
|
|
|
|
+ placeholder="开始时间">
|
|
|
|
|
+ </el-date-picker>
|
|
|
|
|
+ <span>至</span>
|
|
|
|
|
+ <el-date-picker
|
|
|
|
|
+ v-model="time.endTime"
|
|
|
|
|
+ type="datetime"
|
|
|
|
|
+ format="yyyy-MM-dd HH:mm:ss"
|
|
|
|
|
+ placeholder="结束时间">
|
|
|
|
|
+ </el-date-picker>
|
|
|
|
|
+ <!-- 删除按钮(首行隐藏) -->
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ v-if="index !== 0"
|
|
|
|
|
+ @click="removeTime(index)"
|
|
|
|
|
+ icon="el-icon-close"
|
|
|
|
|
+ circle>
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 添加按钮(动态隐藏) -->
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ v-if="showAddButton"
|
|
|
|
|
+ @click="addTime"
|
|
|
|
|
+ type="text"
|
|
|
|
|
+ icon="el-icon-plus">
|
|
|
|
|
+ 添加值班时间
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+
|
|
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
|
|
+ <el-button @click="handleCancel">取 消</el-button>
|
|
|
|
|
+ <el-button type="primary" @click="handleConfirm">确 认</el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-dialog>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped>
|
|
|
|
|
+
|
|
|
|
|
+</style>
|