<template>
<el-dialog
:visible.sync="dialogVisible"
:title="`${title[operateType]}范围子规则`"
width="500"
:close-on-click-modal="false"
>
<el-form
:model="ruleForm"
:rules="rules"
ref="ruleFormRef"
label-width="100px"
class="base-ruleForm"
label-position="top"
size="mini"
:disabled="operateType == 'detail'"
>
<el-form-item label="规则名称" prop="nameCn">
<el-input v-model="ruleForm.nameCn"></el-input>
</el-form-item>
<el-form-item label="描述" prop="description">
<el-input
v-model="ruleForm.description"
type="textarea"
rows="3"
show-word-limit
maxlength="200"
></el-input>
</el-form-item>
</el-form>
<el-form
:model="customRuleForm"
:rules="customRules"
:inline="true"
ref="customRuleFormRef"
label-width="100px"
class="custom-ruleForm"
label-position="top"
size="mini"
:disabled="operateType == 'detail'"
>
<el-form-item label="发送人类型" prop="fromTypeList">
<el-select
v-model="customRuleForm.fromTypeList"
multiple
@change="dealSelectAll('fromTypeList')"
>
<el-option
v-for="opt in filterOptions.FromTypeEnum"
:key="opt.code"
:label="opt.info"
:value="opt.code"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="接收人类型" prop="toTypeList">
<el-select
v-model="customRuleForm.toTypeList"
multiple
@change="dealSelectAll('toTypeList')"
>
<el-option
v-for="opt in filterOptions.ToTypeEnum"
:key="opt.code"
:label="opt.info"
:value="opt.code"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="消息类型" prop="msgTypeList">
<el-select v-model="customRuleForm.msgTypeList" multiple>
<el-option
v-for="opt in filterOptions.MsgTypeEnum"
:key="opt.code"
:label="opt.info"
:value="opt.code"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="聊天类型" prop="chatTypeList">
<el-select
v-model="customRuleForm.chatTypeList"
multiple
@change="changeChatTypeList(false)"
>
<el-option
v-for="opt in filterOptions.ChatTypeEnum"
:key="opt.code"
:label="opt.info"
:value="opt.code"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="群聊群主" prop="roomOwnerIdList">
<el-select v-model="customRuleForm.roomOwnerIdList" multiple>
<el-option
v-for="opt in filterOptions.RoomOwnerIdListEnum"
:key="opt.ownerId"
:label="opt.ownerName"
:value="opt.ownerId"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="群主员工所属部门" prop="roomOwnerDeptList">
<el-select
v-model="customRuleForm.roomOwnerDeptList"
multiple
filterable
remote
:remote-method="searchDepts"
:loading="roomOwnerDeptScroll.loading"
v-infinite-scroll="loadMoreDepts"
infinite-scroll-disabled="roomOwnerDeptScroll.loading"
infinite-scroll-distance="50"
>
<el-option
v-for="opt in filterOptions.RoomOwnerDeptListEnum"
:key="opt.id"
:label="opt.name"
:value="opt.id"
>
</el-option>
<div v-if="roomOwnerDeptScroll.loading" class="loading-text">
加载中...
</div>
<div v-if="!roomOwnerDeptScroll.noMore" class="loading-text">
下拉加载更多...
</div>
<div v-if="roomOwnerDeptScroll.noMore" class="loading-text">
没有更多了
</div>
</el-select>
</el-form-item>
<el-form-item label="群聊列表" prop="roomIdList">
<el-select
v-model="customRuleForm.roomIdList"
multiple
@change="changeRoomId(false)"
>
<el-option
v-for="opt in filterOptions.RoomIdListEnum"
:key="opt.roomId"
:label="opt.roomName"
:value="opt.roomId"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="群聊成员白名单" prop="roomExcludeList">
<el-select v-model="customRuleForm.roomExcludeList" multiple>
<el-option
v-for="opt in filterOptions.roomExcludeListEnum"
:key="opt.qwUserId"
:label="opt.name"
:value="opt.qwUserId"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="群聊关注成员" prop="roomFocueList">
<el-select v-model="customRuleForm.roomFocueList" multiple>
<el-option
v-for="opt in filterOptions.roomExcludeListEnum"
:key="opt.qwUserId"
:label="opt.name"
:value="opt.qwUserId"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="员工" prop="employeeList">
<private-cloud-member-select-new
style="width: 100%"
ref="privateCloudMemberUse"
placeholder="请选择员工"
:defaultCheckedKey="defalutValue.employeeList"
mode="member"
@selectedMembers="choseEmployeeList"
/>
</el-form-item>
<el-form-item label="部门" prop="deptList">
<private-cloud-member-select-new
style="width: 100%"
ref="privateCloudDeptUse"
mode="group"
placeholder="请选择部门"
:defaultCheckedKey="defalutValue.deptList"
@selectedGroups="choseDeptList"
/>
</el-form-item>
<el-form-item label="是否启用白名单" prop="enableWhite">
<el-switch
v-model="customRuleForm.enableWhite"
:active-value="1"
:inactive-value="0"
>
</el-switch>
</el-form-item>
<el-form-item label="正则表达式" prop="textRegex" style="width: 100%">
<vue-json-editor
v-model="customRuleForm.textRegex"
style="width: 100%"
mode="code"
lang="zh"
></vue-json-editor>
</el-form-item>
</el-form>
<div class="el-form-item el-form--label-top" style="margin-bottom: 0">
<label for="" class="el-form-item__label">扩展信息</label>
<div class="el-form-item__content extra-info">
<vue-json-editor
ref="jsonRef"
v-model="ext"
style="width: 100%"
mode="code"
lang="zh"
></vue-json-editor>
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button
type="primary"
@click="save"
:disabled="operateType == 'detail'"
>
确定
</el-button>
</div>
</el-dialog>
</template>
<script>
import vueJsonEditor from 'vue-json-editor'
import archivesApi from '@/api/archive/index'
import dayjs from 'dayjs'
import { debounce } from 'lodash'
export default {
components: {
vueJsonEditor,
},
props: {
type: String,
},
data() {
return {
dialogVisible: false,
ruleForm: {
nameCn: '',
description: '',
},
rules: {
nameCn: [
{ required: true, message: '请输入活动名称', trigger: 'blur' },
{ max: 20, message: '长度不能超过20个字符', trigger: 'blur' },
],
},
formConfig: [],
customRuleForm: {
fromTypeList: null,
toTypeList: null,
msgTypeList: null,
chatTypeList: null,
roomOwnerIdList: null,
roomOwnerDeptList: null,
roomIdList: null,
roomExcludeList: null,
roomFocueList: null,
employeeList: null,
deptList: null,
enableWhite: 0,
textRegex: {},
},
filterOptions: {},
customRules: {},
ext: {},
hasJsonErrorFlag: false,
defalutValue: {
employeeList: [],
deptList: [],
},
isEdit: false,
operateType: null,
editIndex: null,
groupData: [],
title: {
add: '添加',
edit: '编辑',
detail: '查看',
},
roomOwnerDeptScroll: {
page: 1,
pageSize: 20,
loading: false,
noMore: false,
keyword: '',
total: 0,
},
}
},
watch: {
dialogVisible(newVal) {
if (!newVal) {
this.resetFiled()
}
},
},
mounted() {},
methods: {
// 获取筛选项
async getFilter(filter, ruleType, row = null, index) {
this.operateType = ruleType
this.isEdit = ruleType === 'edit' ? true : false
if (this.isEdit) {
this.editIndex = index
}
this.filterOptions = { ...filter }
this.resetScrollData()
await this.getRoomList(true)
await this.getOwnerDeptList(true)
if (ruleType === 'add' && row) {
this.$set(this.ruleForm, 'nameCn', row.nameCn)
} else if (row) {
this.$set(this.ruleForm, 'nameCn', row.nameCn)
this.$set(this.ruleForm, 'description', row.description)
this.customRuleForm = { ...row }
this.customRuleForm.textRegex = JSON.parse(row.textRegex)
if (row.ext) {
this.ext = JSON.parse(row.ext)
}
this.defalutValue.employeeList = row.employeeListIds?.map(
(item) => `_${item}` || []
)
this.defalutValue.deptList = row.deptList ? [...row.deptList] : []
await this.changeChatTypeList(true)
await this.changeRoomId(true)
if (row.roomOwnerDeptList) {
await this.handleMissingDepts(row.roomOwnerDeptList)
}
}
},
dealSelectAll(type) {
if (this.customRuleForm[type]?.includes(0)) {
this.customRuleForm[type] = [0]
}
},
// 获取群主列表或者群聊列表
async getRoomList(isEditInit) {
await archivesApi
.getRoomList({})
.then((res) => {
if (res.data.success) {
const data = res.data.data
this.groupData = [...data]
this.changeChatTypeList(isEditInit)
} else {
this.$message.error(res.data.msg || '获取失败')
}
})
.catch(() => {})
},
// 选择群聊类型时
changeChatTypeList(isEditInit = false) {
console.log('群聊类型isEditInit', isEditInit)
if (this.customRuleForm.chatTypeList?.includes(0)) {
this.$set(this.customRuleForm, 'chatTypeList', [0])
}
if (
this.customRuleForm.chatTypeList.includes(0) ||
this.customRuleForm.chatTypeList == null
) {
this.filterOptions.RoomOwnerIdListEnum = this.groupData.reduce(
(acc, item) => {
if (!acc.some((i) => i.ownerId === item.ownerId)) {
acc.push(item)
}
return acc
},
[]
)
this.filterOptions.RoomIdListEnum = this.groupData.reduce(
(acc, item) => {
if (!acc.some((i) => i.roomId === item.roomId)) {
acc.push(item)
}
return acc
},
[]
)
} else {
this.filterOptions.RoomOwnerIdListEnum = this.groupData
.filter((item) =>
this.customRuleForm.chatTypeList?.includes(item.chatType)
)
.reduce((acc, item) => {
if (!acc.some((i) => i.ownerId === item.ownerId)) {
acc.push(item)
}
return acc
}, [])
this.filterOptions.RoomIdListEnum = this.groupData
.filter((item) =>
this.customRuleForm.chatTypeList?.includes(item.chatType)
)
.reduce((acc, item) => {
if (!acc.some((i) => i.roomId === item.roomId)) {
acc.push(item)
}
return acc
}, [])
}
if (!isEditInit) {
this.customRuleForm.roomOwnerIdList = []
this.customRuleForm.roomIdList = []
this.customRuleForm.roomExcludeList = []
this.customRuleForm.roomFocueList = []
}
},
// 选择群列表
async changeRoomId(isEditInit = false) {
if (this.customRuleForm.roomIdList?.length) {
const params = {
roomIds: this.customRuleForm.roomIdList,
}
await archivesApi
.getRoomMemberList(params)
.then((res) => {
if (res.data.success) {
const data = res.data.data
this.$set(this.filterOptions, 'roomExcludeListEnum', data)
this.filterOptions.roomExcludeListEnum =
this.filterOptions.roomExcludeListEnum.reduce((acc, item) => {
if (!acc.some((i) => i.qwUserId === item.qwUserId)) {
acc.push(item)
}
return acc
}, [])
} else {
this.filterOptions.roomExcludeListEnum = []
this.$message.error(res.data.msg || '获取失败')
}
})
.catch(() => {})
console.log('群列表isEditInit', isEditInit)
if (!isEditInit) {
this.customRuleForm.roomExcludeList = []
this.customRuleForm.roomFocueList = []
}
} else {
this.filterOptions.roomExcludeListEnum = []
}
},
// 获取群主部门
async getOwnerDeptList(init = false) {
if (this.roomOwnerDeptScroll.loading) return
this.roomOwnerDeptScroll.loading = true
if (init) {
this.roomOwnerDeptScroll.page = 1
this.filterOptions.RoomOwnerDeptListEnum = []
this.roomOwnerDeptScroll.noMore = false
}
await archivesApi
.getOwnerDeptList({})
.then((res) => {
console.log('res', res)
if (res.data.success) {
const data = res.data.data
this.$set(this.filterOptions, 'RoomOwnerDeptListEnum', data)
this.roomOwnerDeptScroll.loading = false
this.roomOwnerDeptScroll.noMore = false
} else {
this.$message.error(res.data.msg || '获取失败')
}
})
.catch(() => {})
},
// 加载更多部门(滚动触发)
loadMoreDepts: debounce(function () {
console.log('加载更多部门')
if (
!this.roomOwnerDeptScroll.loading &&
!this.roomOwnerDeptScroll.noMore
) {
this.roomOwnerDeptScroll.page++
this.getOwnerDeptList()
}
}, 300),
// 部门搜索
searchDepts: debounce(function (query) {
this.roomOwnerDeptScroll.keyword = query
this.roomOwnerDeptScroll.page = 1
this.getOwnerDeptList(true)
}, 500),
// 处理编辑时缺失的部门选项(回显)
async handleMissingDepts(deptIds) {
// 找出当前不在列表中的部门ID
const missingIds = deptIds.filter(
(id) =>
!this.filterOptions.RoomOwnerDeptListEnum.some((opt) => opt.id === id)
)
// if (missingIds.length > 0) {
// try {
// const res = await archivesApi.getDeptsByIds({ ids: missingIds })
// if (res.data.success) {
// // 将缺失的部门添加到列表开头
// this.deptOptions = [...res.data.data, ...this.deptOptions]
// }
// } catch (e) {
// console.error('加载缺失部门失败', e)
// }
// }
},
// 重置滚动加载相关数据
resetScrollData() {
// 部门下拉框
this.filterOptions.RoomOwnerDeptListEnum = []
this.roomOwnerDeptScroll = {
page: 1,
pageSize: 20,
loading: false,
noMore: false,
keyword: '',
total: 0,
}
},
save() {
let isPass = true
this.$refs.ruleFormRef.validate((valid) => {
if (!valid) {
isPass = false
}
})
this.$refs.customRuleFormRef.validate((valid) => {
if (!valid) {
isPass = false
}
})
console.log('筛选项验证通过', this.ext)
if (this.$refs.jsonRef.error) {
isPass = false
this.$message.error('扩展信息JSON格式错误')
return
}
if (!isPass) {
return
}
const params = {
...this.customRuleForm,
...this.ruleForm,
textRegex: JSON.stringify(this.customRuleForm.textRegex),
ext: JSON.stringify(this.ext),
}
if (this.isEdit) {
params.gmtModified = dayjs().format('YYYY-MM-DD HH:mm:ss')
this.$emit('freshData', params, this.type, this.editIndex)
} else {
params.gmtCreate = dayjs().format('YYYY-MM-DD HH:mm:ss')
this.$emit('freshData', params, this.type)
}
this.resetFiled()
this.dialogVisible = false
console.log(isPass, 'isPass')
},
// 选择员工
choseEmployeeList(val) {
const { empList = [] } = val || {}
let checkedKey = []
let checkedEmployee = []
let checkedEmployeeIds = []
if (empList && empList.length) {
// 回显使用成员id
checkedKey = checkedKey.concat(empList.map((x) => `_${x.id}`))
checkedEmployee = checkedEmployee.concat(empList.map((x) => x.qwUserId))
checkedEmployeeIds = checkedEmployeeIds.concat(empList.map((x) => x.id))
}
this.defalutValue.employeeList = checkedKey
this.customRuleForm.employeeList = checkedEmployee
this.customRuleForm.employeeListIds = checkedEmployeeIds
},
// 选择部门
choseDeptList(val) {
const { deptList = [] } = val || {}
let checkedKey = []
// 员工回显
if (deptList && deptList.length) {
checkedKey = deptList.map((x) => x.nodeId)
}
this.defalutValue.deptList = checkedKey
this.customRuleForm.deptList = checkedKey
},
resetFiled() {
this.ruleForm = {
nameCn: '',
description: '',
}
this.customRuleForm = {
fromTypeList: null,
toTypeList: null,
msgTypeList: null,
chatTypeList: null,
roomOwnerIdList: null,
roomOwnerDeptList: null,
roomIdList: null,
roomExcludeList: null,
roomFocueList: null,
employeeList: null,
deptList: null,
enableWhite: 0,
textRegex: {},
employeeListIds: null,
}
this.defalutValue = {
employeeList: [],
deptList: [],
}
this.$refs.privateCloudMemberUse.reset()
this.$refs.privateCloudDeptUse.reset()
this.$refs.ruleFormRef.resetFields()
this.$refs.customRuleFormRef.resetFields()
this.ext = {}
},
},
}
</script>
<style lang="scss" scoped>
::v-deep .el-form-item__label {
line-height: 1;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
}
.extra-info {
display: flex;
margin-bottom: 10px;
.delete-icon {
margin-left: 10px;
}
}
::v-deep .el-dialog {
height: auto;
margin-top: 8vh;
.el-dialog__body {
height: 60vh;
overflow: auto;
}
}
.custom-ruleForm {
.el-form-item {
width: 30%;
.el-select {
width: 100%;
}
}
}
::v-deep a.jsoneditor-poweredBy {
display: none;
}
.loading-text {
padding: 4px 0;
text-align: center;
color: #999;
font-size: 12px;
}
</style>
el-select v-infinite-scroll不生效