commit
3b5475aab1
|
@ -14,4 +14,14 @@ from django.core.asgi import get_asgi_application
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'application.settings')
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'application.settings')
|
||||||
os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"
|
os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"
|
||||||
|
|
||||||
application = get_asgi_application()
|
from application.websocketConfig import websocket_application
|
||||||
|
|
||||||
|
http_application = get_asgi_application()
|
||||||
|
|
||||||
|
async def application(scope,receive,send):
|
||||||
|
if scope['type'] == 'http':
|
||||||
|
await http_application(scope, receive, send)
|
||||||
|
elif scope['type'] == 'websocket':
|
||||||
|
await websocket_application(scope, receive, send)
|
||||||
|
else:
|
||||||
|
raise Exception("未知的scope类型,"+ scope['type'])
|
|
@ -0,0 +1,114 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import django
|
||||||
|
|
||||||
|
django.setup()
|
||||||
|
import json
|
||||||
|
import urllib
|
||||||
|
|
||||||
|
#处理websocket传参
|
||||||
|
from jwt import InvalidSignatureError
|
||||||
|
|
||||||
|
from application import settings
|
||||||
|
from dvadmin.system.models import MessageCenter
|
||||||
|
|
||||||
|
|
||||||
|
def request_data(scope):
|
||||||
|
query_string = scope.get('query_string', b'').decode('utf-8')
|
||||||
|
qs = urllib.parse.parse_qs(query_string)
|
||||||
|
return qs
|
||||||
|
|
||||||
|
|
||||||
|
# 全部的websocket sender
|
||||||
|
CONNECTIONS = {}
|
||||||
|
|
||||||
|
|
||||||
|
# 判断用户是否已经连接
|
||||||
|
def check_connection(key):
|
||||||
|
return key in CONNECTIONS
|
||||||
|
|
||||||
|
|
||||||
|
# 发送消息结构体
|
||||||
|
def message(sender, msg_type, msg):
|
||||||
|
text = json.dumps({
|
||||||
|
'sender': sender,
|
||||||
|
'contentType': msg_type,
|
||||||
|
'content': msg,
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
'type': 'websocket.send',
|
||||||
|
'text': text
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def websocket_application(scope, receive, send):
|
||||||
|
while True:
|
||||||
|
event = await receive()
|
||||||
|
# print('[event] ', event)
|
||||||
|
qs = request_data(scope)
|
||||||
|
print(1,qs)
|
||||||
|
auth = qs.get('auth', [''])[0]
|
||||||
|
user_id = None
|
||||||
|
# 收到建立WebSocket连接的消息
|
||||||
|
if event['type'] == 'websocket.connect':
|
||||||
|
# 昵称验证
|
||||||
|
if not auth:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
import jwt
|
||||||
|
decoded_result = jwt.decode(auth, settings.SECRET_KEY, algorithms=["HS256"])
|
||||||
|
if decoded_result:
|
||||||
|
user_id = decoded_result.get('user_id')
|
||||||
|
# 记录
|
||||||
|
CONNECTIONS[user_id] = send
|
||||||
|
except InvalidSignatureError:
|
||||||
|
break
|
||||||
|
if auth in CONNECTIONS:
|
||||||
|
break
|
||||||
|
|
||||||
|
await send({'type': 'websocket.accept'})
|
||||||
|
await send(message('system', 'INFO', '连接成功'))
|
||||||
|
# # 发送好友列表
|
||||||
|
# friends_list = list(CONNECTIONS.keys())
|
||||||
|
# await send(message('system', 'INFO', friends_list))
|
||||||
|
#
|
||||||
|
# # 向其他人群发消息, 有人登录了
|
||||||
|
# for other in CONNECTIONS.values():
|
||||||
|
# await other(message('system', 'addFriend', auth))
|
||||||
|
|
||||||
|
|
||||||
|
# 收到中断WebSocket连接的消息
|
||||||
|
elif event['type'] == 'websocket.disconnect':
|
||||||
|
# 移除记录
|
||||||
|
if user_id in CONNECTIONS:
|
||||||
|
CONNECTIONS.pop(user_id)
|
||||||
|
|
||||||
|
# # 向其他人群发消息, 有人离线了
|
||||||
|
# for other in CONNECTIONS.values():
|
||||||
|
# await other(message('system', 'removeFriend', user_id))
|
||||||
|
|
||||||
|
# 其他情况,正常的WebSocket消息
|
||||||
|
elif event['type'] == 'websocket.receive':
|
||||||
|
print(11,event)
|
||||||
|
if event['text'] == 'ping':
|
||||||
|
await send(message('system', 'text', 'pong!'))
|
||||||
|
else:
|
||||||
|
receive_msg = json.loads(event['text'])
|
||||||
|
message_id = receive_msg.get('message_id', None)
|
||||||
|
_MessageCenter = MessageCenter.objects.filter(id=message_id).first()
|
||||||
|
if _MessageCenter:
|
||||||
|
user_list = _MessageCenter.target_user.values_list('id',flat=True)
|
||||||
|
for send_user in user_list:
|
||||||
|
if send_user in CONNECTIONS:
|
||||||
|
content_type = receive_msg.get('contentType', 'TEXT')
|
||||||
|
content = receive_msg.get('content', '')
|
||||||
|
msg = message(user_id, content_type, content)
|
||||||
|
await CONNECTIONS[send_user](msg)
|
||||||
|
else:
|
||||||
|
msg = message('system', 'text', '对方已下线或不存在')
|
||||||
|
await send(msg)
|
||||||
|
else:
|
||||||
|
print('a1a1a1')
|
||||||
|
pass
|
||||||
|
|
||||||
|
print('[disconnect]')
|
|
@ -44,3 +44,6 @@ LOGIN_NO_CAPTCHA_AUTH = True
|
||||||
# ================================================= #
|
# ================================================= #
|
||||||
|
|
||||||
ALLOWED_HOSTS = ["*"]
|
ALLOWED_HOSTS = ["*"]
|
||||||
|
|
||||||
|
# daphne启动命令
|
||||||
|
#daphne application.asgi:application -b 0.0.0.0 -p 8000
|
||||||
|
|
|
@ -272,10 +272,57 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "消息中心",
|
||||||
|
"icon": "bullhorn",
|
||||||
|
"sort": 7,
|
||||||
|
"is_link": false,
|
||||||
|
"is_catalog": false,
|
||||||
|
"web_path": "/messageCenter",
|
||||||
|
"component": "system/messageCenter/index",
|
||||||
|
"component_name": "messageCenter",
|
||||||
|
"status": true,
|
||||||
|
"cache": false,
|
||||||
|
"visible": true,
|
||||||
|
"parent": 277,
|
||||||
|
"children": [],
|
||||||
|
"menu_button": [
|
||||||
|
{
|
||||||
|
"name": "查询",
|
||||||
|
"value": "Search",
|
||||||
|
"api": "/api/system/message_center/",
|
||||||
|
"method": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "详情",
|
||||||
|
"value": "Retrieve",
|
||||||
|
"api": "/api/system/message_center/{id}/",
|
||||||
|
"method": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "新增",
|
||||||
|
"value": "Create",
|
||||||
|
"api": "/api/system/message_center/",
|
||||||
|
"method": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "编辑",
|
||||||
|
"value": "Update",
|
||||||
|
"api": "/api/system/message_center/{id}/",
|
||||||
|
"method": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "删除",
|
||||||
|
"value": "Delete",
|
||||||
|
"api": "/api/system/menu/{id}/",
|
||||||
|
"method": 3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "接口白名单",
|
"name": "接口白名单",
|
||||||
"icon": "compass",
|
"icon": "compass",
|
||||||
"sort": 7,
|
"sort": 8,
|
||||||
"is_link": false,
|
"is_link": false,
|
||||||
"is_catalog": false,
|
"is_catalog": false,
|
||||||
"web_path": "/apiWhiteList",
|
"web_path": "/apiWhiteList",
|
||||||
|
|
|
@ -34,8 +34,8 @@ class Users(CoreModel,AbstractUser):
|
||||||
user_type = models.IntegerField(
|
user_type = models.IntegerField(
|
||||||
choices=USER_TYPE, default=0, verbose_name="用户类型", null=True, blank=True, help_text="用户类型"
|
choices=USER_TYPE, default=0, verbose_name="用户类型", null=True, blank=True, help_text="用户类型"
|
||||||
)
|
)
|
||||||
post = models.ManyToManyField(to="Post", verbose_name="关联岗位", db_constraint=False, help_text="关联岗位")
|
post = models.ManyToManyField(to="Post",blank=True, verbose_name="关联岗位", db_constraint=False, help_text="关联岗位")
|
||||||
role = models.ManyToManyField(to="Role", verbose_name="关联角色", db_constraint=False, help_text="关联角色")
|
role = models.ManyToManyField(to="Role", blank=True,verbose_name="关联角色", db_constraint=False, help_text="关联角色")
|
||||||
dept = models.ForeignKey(
|
dept = models.ForeignKey(
|
||||||
to="Dept",
|
to="Dept",
|
||||||
verbose_name="所属部门",
|
verbose_name="所属部门",
|
||||||
|
@ -416,10 +416,10 @@ class MessageCenter(CoreModel):
|
||||||
title = models.CharField(max_length=100,verbose_name="标题",help_text="标题")
|
title = models.CharField(max_length=100,verbose_name="标题",help_text="标题")
|
||||||
content = models.TextField(verbose_name="内容",help_text="内容")
|
content = models.TextField(verbose_name="内容",help_text="内容")
|
||||||
target_type=models.IntegerField(default=0,verbose_name="目标类型",help_text="目标类型")
|
target_type=models.IntegerField(default=0,verbose_name="目标类型",help_text="目标类型")
|
||||||
target_user = models.ForeignKey(to=Users,related_name="target_user",null=True,blank=True,db_constraint=False,on_delete=models.CASCADE,verbose_name="目标用户",help_text="目标用户")
|
target_user = models.ManyToManyField(to=Users,related_name="target_user",blank=True,db_constraint=False,verbose_name="目标用户",help_text="目标用户")
|
||||||
target_dept = models.ForeignKey(to=Dept, null=True, blank=True, db_constraint=False, on_delete=models.CASCADE,
|
target_dept = models.ManyToManyField(to=Dept, null=True, blank=True, db_constraint=False,
|
||||||
verbose_name="目标部门", help_text="目标部门")
|
verbose_name="目标部门", help_text="目标部门")
|
||||||
target_role = models.ForeignKey(to=Role, null=True, blank=True, db_constraint=False, on_delete=models.CASCADE,
|
target_role = models.ManyToManyField(to=Role, blank=True, db_constraint=False,
|
||||||
verbose_name="目标角色", help_text="目标角色")
|
verbose_name="目标角色", help_text="目标角色")
|
||||||
is_read=models.BooleanField(default=False,blank=True,verbose_name="是否已读",help_text="是否已读")
|
is_read=models.BooleanField(default=False,blank=True,verbose_name="是否已读",help_text="是否已读")
|
||||||
|
|
||||||
|
@ -428,4 +428,3 @@ class MessageCenter(CoreModel):
|
||||||
verbose_name = "消息中心"
|
verbose_name = "消息中心"
|
||||||
verbose_name_plural = verbose_name
|
verbose_name_plural = verbose_name
|
||||||
ordering = ("-create_datetime",)
|
ordering = ("-create_datetime",)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from itertools import chain
|
||||||
|
|
||||||
|
from django_restql.fields import DynamicSerializerMethodField
|
||||||
|
from rest_framework.decorators import action, permission_classes
|
||||||
|
from rest_framework.permissions import IsAuthenticated, AllowAny
|
||||||
|
|
||||||
|
from dvadmin.system.models import MessageCenter, Users
|
||||||
|
from dvadmin.system.views.role import RoleSerializer
|
||||||
|
from dvadmin.system.views.user import UserSerializer
|
||||||
|
from dvadmin.utils.json_response import SuccessResponse
|
||||||
|
from dvadmin.utils.serializers import CustomModelSerializer
|
||||||
|
from dvadmin.utils.viewset import CustomModelViewSet
|
||||||
|
|
||||||
|
|
||||||
|
class MessageCenterSerializer(CustomModelSerializer):
|
||||||
|
"""
|
||||||
|
消息中心-序列化器
|
||||||
|
"""
|
||||||
|
role_info = DynamicSerializerMethodField()
|
||||||
|
user_info = DynamicSerializerMethodField()
|
||||||
|
def get_role_info(self, instance, parsed_query):
|
||||||
|
roles =instance.target_role.all()
|
||||||
|
# You can do what ever you want in here
|
||||||
|
# `parsed_query` param is passed to BookSerializer to allow further querying
|
||||||
|
serializer = RoleSerializer(
|
||||||
|
roles,
|
||||||
|
many=True,
|
||||||
|
parsed_query=parsed_query
|
||||||
|
)
|
||||||
|
return serializer.data
|
||||||
|
|
||||||
|
def get_user_info(self, instance, parsed_query):
|
||||||
|
users = instance.target_user.all()
|
||||||
|
# You can do what ever you want in here
|
||||||
|
# `parsed_query` param is passed to BookSerializer to allow further querying
|
||||||
|
serializer = UserSerializer(
|
||||||
|
users,
|
||||||
|
many=True,
|
||||||
|
parsed_query=parsed_query
|
||||||
|
)
|
||||||
|
return serializer.data
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = MessageCenter
|
||||||
|
fields = "__all__"
|
||||||
|
read_only_fields = ["id"]
|
||||||
|
|
||||||
|
|
||||||
|
class MessageCenterCreateSerializer(CustomModelSerializer):
|
||||||
|
"""
|
||||||
|
消息中心-新增-序列化器
|
||||||
|
"""
|
||||||
|
|
||||||
|
def save(self, **kwargs):
|
||||||
|
data = super().save(**kwargs)
|
||||||
|
initial_data = self.initial_data
|
||||||
|
target_type = initial_data.get('target_type')
|
||||||
|
# 在保存之前,根据目标类型,把目标用户查询出来并保存
|
||||||
|
users = initial_data.get('target_user',[])
|
||||||
|
if target_type in [1]:
|
||||||
|
target_role = initial_data.get('target_role')
|
||||||
|
users = Users.objects.exclude(is_deleted=True).filter(role__id__in=target_role).values_list('id',flat=True)
|
||||||
|
if target_type in [2]:
|
||||||
|
target_dept = initial_data.get('target_dept')
|
||||||
|
users = Users.objects.exclude(is_deleted=True).filter(dept__id__in=target_dept).values_list('id',flat=True)
|
||||||
|
data.save()
|
||||||
|
data.target_user.set(users)
|
||||||
|
return data
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = MessageCenter
|
||||||
|
fields = "__all__"
|
||||||
|
read_only_fields = ["id"]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class MessageCenterViewSet(CustomModelViewSet):
|
||||||
|
"""
|
||||||
|
消息中心接口
|
||||||
|
list:查询
|
||||||
|
create:新增
|
||||||
|
update:修改
|
||||||
|
retrieve:单例
|
||||||
|
destroy:删除
|
||||||
|
"""
|
||||||
|
queryset = MessageCenter.objects.all()
|
||||||
|
serializer_class = MessageCenterSerializer
|
||||||
|
create_serializer_class = MessageCenterCreateSerializer
|
||||||
|
extra_filter_backends = []
|
||||||
|
|
||||||
|
@action(methods=['GET'],detail=False,permission_classes=[IsAuthenticated])
|
||||||
|
def get_self_receive(self,request):
|
||||||
|
"""
|
||||||
|
获取接收到的消息
|
||||||
|
"""
|
||||||
|
self_user_id = self.request.user.id
|
||||||
|
queryset = MessageCenter.objects.filter(target_user__id=self_user_id)
|
||||||
|
page = self.paginate_queryset(queryset)
|
||||||
|
if page is not None:
|
||||||
|
serializer = self.get_serializer(page, many=True, request=request)
|
||||||
|
return self.get_paginated_response(serializer.data)
|
||||||
|
serializer = self.get_serializer(queryset, many=True, request=request)
|
||||||
|
return SuccessResponse(data=serializer.data, msg="获取成功")
|
|
@ -0,0 +1,69 @@
|
||||||
|
import ElementUI from 'element-ui'
|
||||||
|
import util from '@/libs/util'
|
||||||
|
function initWebSocket (e) {
|
||||||
|
const token = util.cookies.get('token')
|
||||||
|
if (token) {
|
||||||
|
const wsUri = 'ws://127.0.0.1:8000/?auth=' + token
|
||||||
|
this.socket = new WebSocket(wsUri)// 这里面的this都指向vue
|
||||||
|
this.socket.onerror = webSocketOnError
|
||||||
|
this.socket.onmessage = webSocketOnMessage
|
||||||
|
this.socket.onclose = closeWebsocket
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function webSocketOnError (e) {
|
||||||
|
ElementUI.Notification({
|
||||||
|
title: '',
|
||||||
|
message: 'WebSocket连接发生错误' + JSON.stringify(e),
|
||||||
|
type: 'error',
|
||||||
|
duration: 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
function webSocketOnMessage (e) {
|
||||||
|
const data = JSON.parse(e.data)
|
||||||
|
if (data.contentType === 'INFO') {
|
||||||
|
ElementUI.Notification({
|
||||||
|
title: 'websocket',
|
||||||
|
message: data.content,
|
||||||
|
type: 'success',
|
||||||
|
position: 'bottom-right',
|
||||||
|
duration: 3000
|
||||||
|
})
|
||||||
|
} else if (data.contentType === 'ERROR') {
|
||||||
|
ElementUI.Notification({
|
||||||
|
title: '',
|
||||||
|
message: data.content,
|
||||||
|
type: 'error',
|
||||||
|
position: 'bottom-right',
|
||||||
|
duration: 0
|
||||||
|
})
|
||||||
|
} else if (data.contentType === 'TEXT') {
|
||||||
|
ElementUI.Notification({
|
||||||
|
title: '温馨提示',
|
||||||
|
message: data.content,
|
||||||
|
type: 'success',
|
||||||
|
position: 'bottom-right',
|
||||||
|
duration: 0
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
console.log(data.content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 关闭websiocket
|
||||||
|
function closeWebsocket () {
|
||||||
|
console.log('连接已关闭...')
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
function close () {
|
||||||
|
this.socket.close() // 关闭 websocket
|
||||||
|
this.socket.onclose = function (e) {
|
||||||
|
console.log(e)// 监听关闭事件
|
||||||
|
console.log('关闭')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function webSocketSend (message) {
|
||||||
|
this.socket.send(JSON.stringify(message))
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
initWebSocket, close, webSocketSend
|
||||||
|
}
|
|
@ -191,6 +191,13 @@ export default {
|
||||||
this.showView = true // DOM更新后再通过v-if添加router-view节点
|
this.showView = true // DOM更新后再通过v-if添加router-view节点
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.$websocket.initWebSocket()
|
||||||
|
},
|
||||||
|
destroyed () {
|
||||||
|
// 离开路由之后断开websocket连接
|
||||||
|
this.$websocket.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
import { request } from '@/api/service'
|
||||||
|
export const urlPrefix = '/api/system/message_center/'
|
||||||
|
export function GetList (query) {
|
||||||
|
return request({
|
||||||
|
url: urlPrefix,
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取自己接收的消息
|
||||||
|
* @param query
|
||||||
|
* @returns {*}
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
export function GetSelfReceive (query) {
|
||||||
|
return request({
|
||||||
|
url: urlPrefix + 'get_self_receive/',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function GetObj (obj) {
|
||||||
|
return request({
|
||||||
|
url: urlPrefix + obj.id + '/',
|
||||||
|
method: 'get',
|
||||||
|
params: {}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function AddObj (obj) {
|
||||||
|
return request({
|
||||||
|
url: urlPrefix,
|
||||||
|
method: 'post',
|
||||||
|
data: obj
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function UpdateObj (obj) {
|
||||||
|
return request({
|
||||||
|
url: urlPrefix + obj.id + '/',
|
||||||
|
method: 'put',
|
||||||
|
data: obj
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export function DelObj (id) {
|
||||||
|
return request({
|
||||||
|
url: urlPrefix + id + '/',
|
||||||
|
method: 'delete',
|
||||||
|
data: { id }
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,301 @@
|
||||||
|
import { request } from '@/api/service'
|
||||||
|
|
||||||
|
export const crudOptions = (vm) => {
|
||||||
|
return {
|
||||||
|
indexRow: { // 或者直接传true,不显示title,不居中
|
||||||
|
title: '序号',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
height: '100%' // 表格高度100%, 使用toolbar必须设置
|
||||||
|
},
|
||||||
|
viewOptions: {
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
title: 'id',
|
||||||
|
key: 'id',
|
||||||
|
sortable: true,
|
||||||
|
width: 100,
|
||||||
|
form: { disabled: true }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '标题',
|
||||||
|
key: 'title',
|
||||||
|
search: {
|
||||||
|
disabled: false
|
||||||
|
},
|
||||||
|
width: 400,
|
||||||
|
form: {
|
||||||
|
rules: [ // 表单校验规则
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '必填项'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
component: { span: 24 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '目标类型',
|
||||||
|
key: 'target_type',
|
||||||
|
type: 'radio',
|
||||||
|
dict: { data: [{ value: 0, label: '按用户' }, { value: 1, label: '按角色' }, { value: 2, label: '按部门' }] },
|
||||||
|
form: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '必选项',
|
||||||
|
trigger: ['blur', 'change']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '目标用户',
|
||||||
|
key: 'target_user',
|
||||||
|
search: {
|
||||||
|
disabled: true
|
||||||
|
},
|
||||||
|
minWidth: 130,
|
||||||
|
type: 'table-selector',
|
||||||
|
dict: {
|
||||||
|
cache: false,
|
||||||
|
url: '/api/system/user/',
|
||||||
|
value: 'id', // 数据字典中value字段的属性名
|
||||||
|
label: 'name', // 数据字典中label字段的属性名
|
||||||
|
getData: (url, dict, {
|
||||||
|
form,
|
||||||
|
component
|
||||||
|
}) => {
|
||||||
|
return request({
|
||||||
|
url: url,
|
||||||
|
params: {
|
||||||
|
page: 1,
|
||||||
|
limit: 10
|
||||||
|
}
|
||||||
|
}).then(ret => {
|
||||||
|
component._elProps.page = ret.data.page
|
||||||
|
component._elProps.limit = ret.data.limit
|
||||||
|
component._elProps.total = ret.data.total
|
||||||
|
return ret.data.data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
rules: [ // 表单校验规则
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '必填项'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
itemProps: {
|
||||||
|
class: { yxtInput: true }
|
||||||
|
},
|
||||||
|
component: {
|
||||||
|
span: 24,
|
||||||
|
show (context) {
|
||||||
|
return context.form.target_type === 0
|
||||||
|
},
|
||||||
|
pagination: true,
|
||||||
|
props: { multiple: true },
|
||||||
|
elProps: {
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
field: 'name',
|
||||||
|
title: '用户名称'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'phone',
|
||||||
|
title: '用户电话'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
component: {
|
||||||
|
name: 'manyToMany',
|
||||||
|
valueBinding: 'user_info',
|
||||||
|
children: 'name'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '目标角色',
|
||||||
|
key: 'target_role',
|
||||||
|
search: {
|
||||||
|
disabled: true
|
||||||
|
},
|
||||||
|
|
||||||
|
minWidth: 130,
|
||||||
|
type: 'table-selector',
|
||||||
|
dict: {
|
||||||
|
cache: false,
|
||||||
|
url: '/api/system/role/',
|
||||||
|
value: 'id', // 数据字典中value字段的属性名
|
||||||
|
label: 'name', // 数据字典中label字段的属性名
|
||||||
|
getData: (url, dict, {
|
||||||
|
form,
|
||||||
|
component
|
||||||
|
}) => {
|
||||||
|
return request({
|
||||||
|
url: url,
|
||||||
|
params: {
|
||||||
|
page: 1,
|
||||||
|
limit: 10
|
||||||
|
}
|
||||||
|
}).then(ret => {
|
||||||
|
component._elProps.page = ret.data.page
|
||||||
|
component._elProps.limit = ret.data.limit
|
||||||
|
component._elProps.total = ret.data.total
|
||||||
|
return ret.data.data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
rules: [ // 表单校验规则
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '必填项'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
itemProps: {
|
||||||
|
class: { yxtInput: true }
|
||||||
|
},
|
||||||
|
component: {
|
||||||
|
span: 24,
|
||||||
|
show (context) {
|
||||||
|
return context.form.target_type === 1
|
||||||
|
},
|
||||||
|
pagination: true,
|
||||||
|
props: { multiple: true },
|
||||||
|
elProps: {
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
field: 'name',
|
||||||
|
title: '角色名称'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'key',
|
||||||
|
title: '权限标识'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
component: {
|
||||||
|
name: 'manyToMany',
|
||||||
|
valueBinding: 'role_info',
|
||||||
|
children: 'name'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '目标部门',
|
||||||
|
key: 'target_dept',
|
||||||
|
search: {
|
||||||
|
disabled: true
|
||||||
|
},
|
||||||
|
minWidth: 130,
|
||||||
|
type: 'table-selector',
|
||||||
|
dict: {
|
||||||
|
cache: false,
|
||||||
|
url: '/api/system/dept/',
|
||||||
|
isTree: true,
|
||||||
|
value: 'id', // 数据字典中value字段的属性名
|
||||||
|
label: 'name', // 数据字典中label字段的属性名
|
||||||
|
children: 'children', // 数据字典中children字段的属性名
|
||||||
|
getData: (url, dict, {
|
||||||
|
form,
|
||||||
|
component
|
||||||
|
}) => {
|
||||||
|
return request({
|
||||||
|
url: url,
|
||||||
|
params: {
|
||||||
|
page: 1,
|
||||||
|
limit: 999
|
||||||
|
}
|
||||||
|
}).then(ret => {
|
||||||
|
return ret.data.data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
rules: [ // 表单校验规则
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '必填项'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
itemProps: {
|
||||||
|
class: { yxtInput: true }
|
||||||
|
},
|
||||||
|
component: {
|
||||||
|
span: 24,
|
||||||
|
show (context) {
|
||||||
|
return context.form.target_type === 2
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
multiple: true,
|
||||||
|
elProps: {
|
||||||
|
treeConfig: {
|
||||||
|
transform: true,
|
||||||
|
rowField: 'id',
|
||||||
|
parentField: 'parent',
|
||||||
|
expandAll: true
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
field: 'name',
|
||||||
|
title: '部门名称',
|
||||||
|
treeNode: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'status_label',
|
||||||
|
title: '状态'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'parent_name',
|
||||||
|
title: '父级部门'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
component: {
|
||||||
|
name: 'manyToMany',
|
||||||
|
valueBinding: 'dept_info',
|
||||||
|
children: 'name'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '内容',
|
||||||
|
key: 'content',
|
||||||
|
width: 300,
|
||||||
|
type: 'editor-quill', // 富文本图片上传依赖file-uploader,请先配置好file-uploader
|
||||||
|
form: {
|
||||||
|
rules: [ // 表单校验规则
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '必填项'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
component: {
|
||||||
|
disabled: () => {
|
||||||
|
return vm.getEditForm().disable
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
uploader: {
|
||||||
|
type: 'form' // 上传后端类型【cos,aliyun,oss,form】
|
||||||
|
}
|
||||||
|
},
|
||||||
|
events: {
|
||||||
|
'text-change': (event) => {
|
||||||
|
console.log('text-change:', event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
<template>
|
||||||
|
<d2-container :class="{'page-compact':crud.pageOptions.compact}">
|
||||||
|
|
||||||
|
<d2-crud-x
|
||||||
|
ref="d2Crud"
|
||||||
|
v-bind="_crudProps"
|
||||||
|
v-on="_crudListeners"
|
||||||
|
@form-component-ready="handleFormComponentReady"
|
||||||
|
>
|
||||||
|
<div slot="header">
|
||||||
|
<crud-search ref="search" :options="crud.searchOptions" @submit="handleSearch" />
|
||||||
|
<el-button size="small" type="primary" @click="addRow"><i class="el-icon-plus"/> 新增</el-button>
|
||||||
|
<el-tabs v-model="tabActivted" @tab-click="onTabClick">
|
||||||
|
<el-tab-pane label="我的发布" name="send"></el-tab-pane>
|
||||||
|
<el-tab-pane label="我的接收" name="receive"></el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
<crud-toolbar :search.sync="crud.searchOptions.show"
|
||||||
|
:compact.sync="crud.pageOptions.compact"
|
||||||
|
:columns="crud.columns"
|
||||||
|
@refresh="doRefresh()"
|
||||||
|
@columns-filter-changed="handleColumnsFilterChanged"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</d2-crud-x>
|
||||||
|
</d2-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { AddObj, GetObj, GetList, UpdateObj, DelObj, GetSelfReceive } from './api'
|
||||||
|
import { crudOptions } from './crud'
|
||||||
|
import { d2CrudPlus } from 'd2-crud-plus'
|
||||||
|
export default {
|
||||||
|
name: 'messageCenter',
|
||||||
|
components: {},
|
||||||
|
mixins: [d2CrudPlus.crud],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
tabActivted: 'send'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
// 配置编辑前获取详情
|
||||||
|
this.crud.options.fetchDetail = this.fetchDetail
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getCrudOptions () {
|
||||||
|
return crudOptions(this)
|
||||||
|
},
|
||||||
|
pageRequest (query) {
|
||||||
|
if (this.tabActivted === 'receive') {
|
||||||
|
return GetSelfReceive({ ...query })
|
||||||
|
}
|
||||||
|
return GetList(query)
|
||||||
|
},
|
||||||
|
infoRequest (query) {
|
||||||
|
return GetObj(query)
|
||||||
|
},
|
||||||
|
addRequest (row) {
|
||||||
|
return AddObj(row).then(res => {
|
||||||
|
const message = {
|
||||||
|
message_id: res.data.id,
|
||||||
|
contentType: 'TEXT',
|
||||||
|
content: '您有新的消息,请到消息中心查看~'
|
||||||
|
}
|
||||||
|
this.$websocket.webSocketSend(message)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
updateRequest (row) {
|
||||||
|
return UpdateObj(row)
|
||||||
|
},
|
||||||
|
delRequest (row) {
|
||||||
|
return DelObj(row.id)
|
||||||
|
},
|
||||||
|
// 编辑对话框打开前获取详情
|
||||||
|
fetchDetail (index, row) {
|
||||||
|
if (index == null) {
|
||||||
|
// 添加
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
return GetObj(row).then(res => {
|
||||||
|
return res.data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleFormComponentReady (event, key, form) {
|
||||||
|
// console.log('form component ready:', event, key, form)
|
||||||
|
},
|
||||||
|
onTabClick (obj) {
|
||||||
|
this.doRefresh()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
Loading…
Reference in New Issue