mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-10 18:02:55 +00:00
feat: 转发消息 - 添加来源显示
This commit is contained in:
parent
bc250ad4b8
commit
5fdd5adef8
@ -1358,9 +1358,11 @@ class DialogController extends AbstractController
|
||||
* @apiGroup dialog
|
||||
* @apiName msg__forward
|
||||
*
|
||||
* @apiParam {Number} msg_id 消息ID
|
||||
* @apiParam {Array} dialogids 转发给的对话ID
|
||||
* @apiParam {Array} userids 转发给的成员ID
|
||||
* @apiParam {Number} msg_id 消息ID
|
||||
* @apiParam {Array} dialogids 转发给的对话ID
|
||||
* @apiParam {Array} userids 转发给的成员ID
|
||||
* @apiParam {Number} show_source 是否显示原发送者信息
|
||||
* @apiParam {Array} leave_message 转发留言
|
||||
*
|
||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||
@ -1373,6 +1375,8 @@ class DialogController extends AbstractController
|
||||
$msg_id = intval(Request::input("msg_id"));
|
||||
$dialogids = Request::input('dialogids');
|
||||
$userids = Request::input('userids');
|
||||
$show_source = intval(Request::input("show_source"));
|
||||
$leave_message = Request::input('leave_message');
|
||||
//
|
||||
if (empty($dialogids) && empty($userids)) {
|
||||
return Base::retError("请选择转发对话或成员");
|
||||
@ -1384,7 +1388,7 @@ class DialogController extends AbstractController
|
||||
}
|
||||
WebSocketDialog::checkDialog($msg->dialog_id);
|
||||
//
|
||||
return $msg->forwardMsg($dialogids, $userids, $user);
|
||||
return $msg->forwardMsg($dialogids, $userids, $user, $show_source, $leave_message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -72,6 +72,7 @@ class WebSocketDialogMsg extends AbstractModel
|
||||
protected $appends = [
|
||||
'percentage',
|
||||
'reply_data',
|
||||
'forward_data',
|
||||
];
|
||||
|
||||
protected $hidden = [
|
||||
@ -114,6 +115,21 @@ class WebSocketDialogMsg extends AbstractModel
|
||||
return $this->appendattrs['reply_data'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 转发消息详情
|
||||
* @return WebSocketDialogMsg|null
|
||||
*/
|
||||
public function getForwardDataAttribute()
|
||||
{
|
||||
if (!isset($this->appendattrs['forward_data'])) {
|
||||
$this->appendattrs['forward_data'] = null;
|
||||
if ($this->forward_id > 0) {
|
||||
$this->appendattrs['forward_data'] = self::find($this->forward_id, ['id', 'userid', 'type', 'msg'])?->cancelAppend() ?: null;
|
||||
}
|
||||
}
|
||||
return $this->appendattrs['forward_data'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息格式化
|
||||
* @param $value
|
||||
@ -369,11 +385,13 @@ class WebSocketDialogMsg extends AbstractModel
|
||||
* @param array|int $dialogids
|
||||
* @param array|int $userids
|
||||
* @param User $user 发送的会员
|
||||
* @param int $showSource 是否显示原发送者信息
|
||||
* @param string $leaveMessage 转发留言
|
||||
* @return mixed
|
||||
*/
|
||||
public function forwardMsg($dialogids, $userids, $user)
|
||||
public function forwardMsg($dialogids, $userids, $user, $showSource = 1, $leaveMessage = '')
|
||||
{
|
||||
return AbstractModel::transaction(function() use ($dialogids, $user, $userids) {
|
||||
return AbstractModel::transaction(function() use ($dialogids, $user, $userids, $showSource, $leaveMessage) {
|
||||
$originalMsg = Base::json2array($this->getRawOriginal('msg'));
|
||||
$msgs = [];
|
||||
$already = [];
|
||||
@ -382,11 +400,14 @@ class WebSocketDialogMsg extends AbstractModel
|
||||
$dialogids = [$dialogids];
|
||||
}
|
||||
foreach ($dialogids as $dialogid) {
|
||||
$res = self::sendMsg(null, $dialogid, $this->type, $originalMsg, $user->userid);
|
||||
$res = self::sendMsg('forward-'.( $showSource ? 1 : 0).'-'.($this->forward_id ?: $this->id), $dialogid, $this->type, $originalMsg, $user->userid);
|
||||
if (Base::isSuccess($res)) {
|
||||
$msgs[] = $res['data'];
|
||||
$already[] = $dialogid;
|
||||
}
|
||||
if($leaveMessage){
|
||||
self::sendMsg(null, $dialogid, 'text', ['text' => $leaveMessage], $user->userid);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($userids) {
|
||||
@ -399,10 +420,13 @@ class WebSocketDialogMsg extends AbstractModel
|
||||
}
|
||||
$dialog = WebSocketDialog::checkUserDialog($user, $userid);
|
||||
if ($dialog && !in_array($dialog->id, $already)) {
|
||||
$res = self::sendMsg(null, $dialog->id, $this->type, $originalMsg, $user->userid);
|
||||
$res = self::sendMsg('forward-'.( $showSource ? 1 : 0).'-'.($this->forward_id ?: $this->id), $dialog->id, $this->type, $originalMsg, $user->userid);
|
||||
if (Base::isSuccess($res)) {
|
||||
$msgs[] = $res['data'];
|
||||
}
|
||||
if($leaveMessage){
|
||||
self::sendMsg(null, $dialog->id, 'text', ['text' => $leaveMessage], $user->userid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -772,6 +796,7 @@ class WebSocketDialogMsg extends AbstractModel
|
||||
* - reply-98:回复消息ID=98
|
||||
* - update-99:更新消息ID=99(标记修改)
|
||||
* - change-99:更新消息ID=99(不标记修改)
|
||||
* - forward-99:转发消息ID=99
|
||||
* @param int $dialog_id 会话ID(即 聊天室ID)
|
||||
* @param string $type 消息类型
|
||||
* @param array $msg 发送的消息
|
||||
@ -812,6 +837,7 @@ class WebSocketDialogMsg extends AbstractModel
|
||||
$update_id = preg_match("/^update-(\d+)$/", $action, $match) ? $match[1] : 0;
|
||||
$change_id = preg_match("/^change-(\d+)$/", $action, $match) ? $match[1] : 0;
|
||||
$reply_id = preg_match("/^reply-(\d+)$/", $action, $match) ? $match[1] : 0;
|
||||
$forward_id = preg_match("/^forward-(\d+)-(\d+)$/", $action, $match) ? $match[2] : 0;
|
||||
$sender = $sender === null ? User::userid() : $sender;
|
||||
//
|
||||
$dialog = WebSocketDialog::find($dialog_id);
|
||||
@ -862,6 +888,10 @@ class WebSocketDialogMsg extends AbstractModel
|
||||
if ($reply_id && !self::whereId($reply_id)->increment('reply_num')) {
|
||||
throw new ApiException('回复的消息不存在');
|
||||
}
|
||||
// 转发
|
||||
if ($forward_id && !self::whereId($forward_id)->increment('forward_num')) {
|
||||
throw new ApiException('转发的消息不存在');
|
||||
}
|
||||
//
|
||||
$dialogMsg = self::createInstance([
|
||||
'dialog_id' => $dialog_id,
|
||||
@ -873,6 +903,8 @@ class WebSocketDialogMsg extends AbstractModel
|
||||
'link' => $link,
|
||||
'msg' => $msg,
|
||||
'read' => 0,
|
||||
'forward_id' => $forward_id,
|
||||
'forward_show' => $forward_id ? $match[1] : 1,
|
||||
]);
|
||||
AbstractModel::transaction(function () use ($dialog, $dialogMsg) {
|
||||
$dialog->last_at = Carbon::now();
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class WebSocketDialogMsgsAddForwardId extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('web_socket_dialog_msgs', function (Blueprint $table) {
|
||||
if (!Schema::hasColumn('web_socket_dialog_msgs', 'forward_id')) {
|
||||
$table->bigInteger('forward_id')->nullable()->default(0)->after('reply_id')->comment('转发ID');
|
||||
$table->bigInteger('forward_num')->nullable()->default(0)->after('forward_id')->comment('被转发多少次');
|
||||
$table->boolean('forward_show')->nullable()->default(1)->after('forward_num')->comment('是否显示转发的来源');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('web_socket_dialog_msgs', function (Blueprint $table) {
|
||||
$table->dropColumn("forward_id");
|
||||
$table->dropColumn("forward_num");
|
||||
$table->dropColumn("forward_show");
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1420,3 +1420,7 @@ APP推送
|
||||
任务协助人
|
||||
搜索项目名称
|
||||
服务器版本过低,请升级服务器。
|
||||
|
||||
不显示原发送者信息
|
||||
转发给:
|
||||
留言
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
<div v-if="isFullscreen" class="user-modal-header">
|
||||
<div class="user-modal-close" @click="showModal=false">{{$L('关闭')}}</div>
|
||||
<div class="user-modal-title"><span>{{localTitle}}</span></div>
|
||||
<div class="user-modal-submit" @click="onSubmit">
|
||||
<div class="user-modal-submit" @click="onSubmit(1)">
|
||||
<div v-if="submittIng > 0" class="submit-loading"><Loading /></div>
|
||||
{{$L('确定')}}
|
||||
<template v-if="selects.length > 0">
|
||||
@ -134,7 +134,7 @@
|
||||
|
||||
<!-- 底部 -->
|
||||
<template #footer>
|
||||
<Button type="primary" :loading="submittIng > 0" @click="onSubmit">
|
||||
<Button type="primary" :loading="submittIng > 0" @click="onSubmit(1)">
|
||||
{{$L('确定')}}
|
||||
<template v-if="selects.length > 0">
|
||||
({{selects.length}}<span v-if="multipleMax">/{{multipleMax}}</span>)
|
||||
@ -142,6 +142,42 @@
|
||||
</Button>
|
||||
</template>
|
||||
</Modal>
|
||||
|
||||
<!-- 二次确认 -->
|
||||
<Modal
|
||||
v-model="showAffirmModal"
|
||||
:title="twiceAffirmTitle"
|
||||
class-name="common-user-select-modal twice-affirm-modal"
|
||||
:mask-closable="false"
|
||||
width="420">
|
||||
<div class="user-modal-search twice-affirm">
|
||||
<Scrollbar class="search-selected" v-if="selects?.length > 0" enable-x :enable-y="false">
|
||||
<ul>
|
||||
<li v-for="item in formatSelect(selects)" :data-id="item.userid">
|
||||
<template v-if="item.type=='group'">
|
||||
<EAvatar v-if="item.avatar" class="img-avatar" :src="item.avatar" :size="32"></EAvatar>
|
||||
<i v-else-if="item.group_type=='department'" class="taskfont icon-avatar department"></i>
|
||||
<i v-else-if="item.group_type=='project'" class="taskfont icon-avatar project"></i>
|
||||
<i v-else-if="item.group_type=='task'" class="taskfont icon-avatar task"></i>
|
||||
<i v-else-if="item.group_type=='okr'" class="taskfont icon-avatar task"></i>
|
||||
<Icon v-else class="icon-avatar" type="ios-people" />
|
||||
</template>
|
||||
<UserAvatar v-else :userid="item.userid" :size="32" :show-name="selects?.length == 1" tooltip-disabled />
|
||||
</li>
|
||||
</ul>
|
||||
</Scrollbar>
|
||||
</div>
|
||||
<div class="twice-affirm-body-extend">
|
||||
<slot name="twice-affirm-body-extend"></slot>
|
||||
</div>
|
||||
<template #footer>
|
||||
<slot name="twice-affirm-footer-extend"></slot>
|
||||
<Button type="primary" :loading="submittIng > 0" @click="onSubmit(2)">
|
||||
{{$L('确定')}}
|
||||
<template v-if="selects.length > 0">({{selects.length}})</template>
|
||||
</Button>
|
||||
</template>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -253,147 +289,147 @@ export default {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
// 是否禁用
|
||||
disable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
// 是否禁用
|
||||
submitBtnTwoText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 是否需要确认
|
||||
twiceAffirm: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 确认标题
|
||||
twiceAffirmTitle: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 提交前的回调
|
||||
beforeSubmit: Function
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
switchItems: [
|
||||
{key: 'recent', label: '最近'},
|
||||
{key: 'contact', label: '通讯录'},
|
||||
{key: 'project', label: '项目成员'},
|
||||
{ key: 'recent', label: '最近' },
|
||||
{ key: 'contact', label: '通讯录' },
|
||||
{ key: 'project', label: '项目成员' },
|
||||
],
|
||||
switchActive: 'recent',
|
||||
|
||||
loadIng: 0, // 搜索框等待效果
|
||||
waitIng: 0, // 页面等待效果
|
||||
submittIng: 0, // 提交按钮等待效果
|
||||
|
||||
loadIng: 0,
|
||||
waitIng: 0,
|
||||
submittIng: 0,
|
||||
values: [],
|
||||
selects: [],
|
||||
|
||||
recents: [],
|
||||
contacts: [],
|
||||
projects: [],
|
||||
|
||||
showModal: false,
|
||||
|
||||
searchKey: null,
|
||||
searchCache: [],
|
||||
}
|
||||
showAffirmModal: false,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler(value) {
|
||||
if (typeof value === 'number') {
|
||||
this.$emit('input', value > 0 ? [value] : [])
|
||||
} else if (typeof value === 'string') {
|
||||
value = value.indexOf(',') > -1 ? value.split(',') : [value]
|
||||
this.$emit('input', value.map(item => $A.runNum(item)).filter(item => item > 0))
|
||||
this.$emit('input', value > 0 ? [value] : []);
|
||||
}
|
||||
this.values = value
|
||||
else if (typeof value === 'string') {
|
||||
value = value.indexOf(',') > -1 ? value.split(',') : [value];
|
||||
this.$emit('input', value.map(item => $A.runNum(item)).filter(item => item > 0));
|
||||
}
|
||||
this.values = value;
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
|
||||
isWhole: {
|
||||
handler(value) {
|
||||
if (value) {
|
||||
this.switchActive = 'recent'
|
||||
} else {
|
||||
this.switchActive = 'contact'
|
||||
this.switchActive = 'recent';
|
||||
}
|
||||
else {
|
||||
this.switchActive = 'contact';
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
|
||||
showModal(value) {
|
||||
if (value) {
|
||||
this.searchBefore()
|
||||
} else {
|
||||
this.searchKey = ""
|
||||
this.searchBefore();
|
||||
}
|
||||
this.$emit("on-show-change",value,this.values)
|
||||
else {
|
||||
this.searchKey = "";
|
||||
}
|
||||
this.$emit("on-show-change", value, this.values);
|
||||
},
|
||||
|
||||
searchKey() {
|
||||
this.searchBefore()
|
||||
this.searchBefore();
|
||||
},
|
||||
|
||||
switchActive() {
|
||||
this.searchBefore()
|
||||
this.searchBefore();
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapState([
|
||||
'cacheDialogs',
|
||||
]),
|
||||
|
||||
isFullscreen({windowWidth}) {
|
||||
return windowWidth < 576
|
||||
isFullscreen({ windowWidth }) {
|
||||
return windowWidth < 576;
|
||||
},
|
||||
|
||||
isWhole({projectId, noProjectId, dialogId}) {
|
||||
return projectId === 0 && noProjectId === 0 && dialogId === 0
|
||||
isWhole({ projectId, noProjectId, dialogId }) {
|
||||
return projectId === 0 && noProjectId === 0 && dialogId === 0;
|
||||
},
|
||||
|
||||
lists({switchActive, searchKey, recents, contacts, projects}) {
|
||||
lists({ switchActive, searchKey, recents, contacts, projects }) {
|
||||
switch (switchActive) {
|
||||
case 'recent':
|
||||
if (searchKey) {
|
||||
return recents.filter(item => {
|
||||
return `${item.name}`.indexOf(searchKey) > -1
|
||||
})
|
||||
return `${item.name}`.indexOf(searchKey) > -1;
|
||||
});
|
||||
}
|
||||
return recents
|
||||
|
||||
return recents;
|
||||
case 'contact':
|
||||
return contacts
|
||||
|
||||
return contacts;
|
||||
case 'project':
|
||||
return projects
|
||||
return projects;
|
||||
}
|
||||
return []
|
||||
return [];
|
||||
},
|
||||
|
||||
isSelectAll({lists, selects}) {
|
||||
isSelectAll({ lists, selects }) {
|
||||
return lists.length > 0 && lists.filter(item => selects.includes(item.userid)).length === lists.length;
|
||||
},
|
||||
|
||||
warpClass() {
|
||||
return {
|
||||
'select-module': this.module,
|
||||
'select-border': this.border,
|
||||
'select-whole': this.isWhole,
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
addStyle({avatarSize}) {
|
||||
addStyle({ avatarSize }) {
|
||||
return {
|
||||
width: avatarSize + 'px',
|
||||
height: avatarSize + 'px',
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
localTitle({title}) {
|
||||
localTitle({ title }) {
|
||||
if (title === undefined) {
|
||||
return this.$L('选择会员')
|
||||
} else {
|
||||
return this.$L('选择会员');
|
||||
}
|
||||
else {
|
||||
return title;
|
||||
}
|
||||
},
|
||||
|
||||
localPlaceholder({placeholder}) {
|
||||
localPlaceholder({ placeholder }) {
|
||||
if (placeholder === undefined) {
|
||||
return this.$L('搜索')
|
||||
} else {
|
||||
return this.$L('搜索');
|
||||
}
|
||||
else {
|
||||
return placeholder;
|
||||
}
|
||||
}
|
||||
@ -405,32 +441,29 @@ export default {
|
||||
}
|
||||
return this.uncancelable.includes(value);
|
||||
},
|
||||
|
||||
isDisabled(userid) {
|
||||
if (this.disabledChoice.length === 0) {
|
||||
return false;
|
||||
}
|
||||
return this.disabledChoice.includes(userid)
|
||||
return this.disabledChoice.includes(userid);
|
||||
},
|
||||
|
||||
formatSelect(list) {
|
||||
return list.map(userid => {
|
||||
if ($A.leftExists(userid, 'd:')) {
|
||||
return this.recents.find(item => item.userid === userid)
|
||||
return this.recents.find(item => item.userid === userid);
|
||||
}
|
||||
return {
|
||||
type: 'user',
|
||||
userid,
|
||||
}
|
||||
})
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
selectIcon(value) {
|
||||
if (value === 'all') {
|
||||
return this.isSelectAll ? 'ios-checkmark-circle' : 'ios-radio-button-off';
|
||||
}
|
||||
if ($A.isArray(value) && value.length > 0) {
|
||||
const len = value.filter(value => this.selects.includes(value)).length
|
||||
const len = value.filter(value => this.selects.includes(value)).length;
|
||||
if (len === value.length) {
|
||||
return 'ios-checkmark-circle';
|
||||
}
|
||||
@ -440,7 +473,6 @@ export default {
|
||||
}
|
||||
return 'ios-radio-button-off';
|
||||
},
|
||||
|
||||
selectClass(value) {
|
||||
switch (this.selectIcon(value)) {
|
||||
case 'ios-checkmark-circle':
|
||||
@ -450,29 +482,29 @@ export default {
|
||||
}
|
||||
return '';
|
||||
},
|
||||
|
||||
searchBefore() {
|
||||
if (!this.showModal) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
if (this.switchActive === 'recent') {
|
||||
this.searchRecent()
|
||||
} else if (this.switchActive === 'contact') {
|
||||
this.searchContact()
|
||||
} else if (this.switchActive === 'project') {
|
||||
this.searchProject()
|
||||
this.searchRecent();
|
||||
}
|
||||
else if (this.switchActive === 'contact') {
|
||||
this.searchContact();
|
||||
}
|
||||
else if (this.switchActive === 'project') {
|
||||
this.searchProject();
|
||||
}
|
||||
},
|
||||
|
||||
searchRecent() {
|
||||
this.recents = this.cacheDialogs.filter(dialog => {
|
||||
if (dialog.name === undefined || dialog.dialog_delete === 1) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
if (!this.showBot && dialog.bot) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
return this.showDialog || dialog.type === 'user'
|
||||
return this.showDialog || dialog.type === 'user';
|
||||
}).sort((a, b) => {
|
||||
if (a.top_at || b.top_at) {
|
||||
return $A.Date(b.top_at) - $A.Date(a.top_at);
|
||||
@ -481,33 +513,32 @@ export default {
|
||||
return b.todo_num - a.todo_num;
|
||||
}
|
||||
return $A.Date(b.last_at) - $A.Date(a.last_at);
|
||||
}).map(({id, name, type, group_type, avatar, dialog_user}) => {
|
||||
}).map(({ id, name, type, group_type, avatar, dialog_user }) => {
|
||||
return {
|
||||
name,
|
||||
type,
|
||||
group_type,
|
||||
avatar,
|
||||
userid: type === 'user' ? dialog_user.userid : `d:${id}`,
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
searchContact() {
|
||||
let key = this.searchKey;
|
||||
const cache = this.searchCache.find(item => item.type === 'contact' && item.key == key);
|
||||
if (cache) {
|
||||
this.contacts = cache.data
|
||||
this.contacts = cache.data;
|
||||
}
|
||||
//
|
||||
this.waitIng++
|
||||
this.waitIng++;
|
||||
setTimeout(() => {
|
||||
if (this.searchKey != key) {
|
||||
this.waitIng--
|
||||
this.waitIng--;
|
||||
return;
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.loadIng++
|
||||
}, 300)
|
||||
this.loadIng++;
|
||||
}, 300);
|
||||
this.$store.dispatch("call", {
|
||||
url: 'users/search',
|
||||
data: {
|
||||
@ -521,43 +552,43 @@ export default {
|
||||
},
|
||||
take: 50
|
||||
},
|
||||
}).then(({data}) => {
|
||||
data = data.map(item => Object.assign(item, {type: 'user'}))
|
||||
this.contacts = data
|
||||
}).then(({ data }) => {
|
||||
data = data.map(item => Object.assign(item, { type: 'user' }));
|
||||
this.contacts = data;
|
||||
//
|
||||
const index = this.searchCache.findIndex(item => item.key == key);
|
||||
const tmpData = {type: 'contact', key, data, time: $A.Time()};
|
||||
const tmpData = { type: 'contact', key, data, time: $A.Time() };
|
||||
if (index > -1) {
|
||||
this.searchCache.splice(index, 1, tmpData)
|
||||
} else {
|
||||
this.searchCache.push(tmpData)
|
||||
this.searchCache.splice(index, 1, tmpData);
|
||||
}
|
||||
}).catch(({msg}) => {
|
||||
this.contacts = []
|
||||
$A.messageWarning(msg)
|
||||
else {
|
||||
this.searchCache.push(tmpData);
|
||||
}
|
||||
}).catch(({ msg }) => {
|
||||
this.contacts = [];
|
||||
$A.messageWarning(msg);
|
||||
}).finally(_ => {
|
||||
this.loadIng--;
|
||||
this.waitIng--;
|
||||
});
|
||||
}, this.searchCache.length > 0 ? 300 : 0)
|
||||
}, this.searchCache.length > 0 ? 300 : 0);
|
||||
},
|
||||
|
||||
searchProject() {
|
||||
let key = this.searchKey;
|
||||
const cache = this.searchCache.find(item => item.type === 'project' && item.key == key);
|
||||
if (cache) {
|
||||
this.projects = cache.data
|
||||
this.projects = cache.data;
|
||||
}
|
||||
//
|
||||
this.waitIng++
|
||||
this.waitIng++;
|
||||
setTimeout(() => {
|
||||
if (this.searchKey != key) {
|
||||
this.waitIng--
|
||||
this.waitIng--;
|
||||
return;
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.loadIng++
|
||||
}, 300)
|
||||
this.loadIng++;
|
||||
}, 300);
|
||||
this.$store.dispatch("call", {
|
||||
url: 'project/lists',
|
||||
data: {
|
||||
@ -568,137 +599,146 @@ export default {
|
||||
getuserid: 'yes',
|
||||
getstatistics: 'no'
|
||||
},
|
||||
}).then(({data}) => {
|
||||
data = data.data.map(item => Object.assign(item, {type: 'project'}))
|
||||
this.projects = data
|
||||
}).then(({ data }) => {
|
||||
data = data.data.map(item => Object.assign(item, { type: 'project' }));
|
||||
this.projects = data;
|
||||
//
|
||||
const index = this.searchCache.findIndex(item => item.key == key);
|
||||
const tmpData = {type: 'project', key, data, time: $A.Time()};
|
||||
const tmpData = { type: 'project', key, data, time: $A.Time() };
|
||||
if (index > -1) {
|
||||
this.searchCache.splice(index, 1, tmpData)
|
||||
} else {
|
||||
this.searchCache.push(tmpData)
|
||||
this.searchCache.splice(index, 1, tmpData);
|
||||
}
|
||||
}).catch(({msg}) => {
|
||||
this.projects = []
|
||||
$A.messageWarning(msg)
|
||||
else {
|
||||
this.searchCache.push(tmpData);
|
||||
}
|
||||
}).catch(({ msg }) => {
|
||||
this.projects = [];
|
||||
$A.messageWarning(msg);
|
||||
}).finally(_ => {
|
||||
this.loadIng--;
|
||||
this.waitIng--;
|
||||
});
|
||||
}, this.searchCache.length > 0 ? 300 : 0)
|
||||
}, this.searchCache.length > 0 ? 300 : 0);
|
||||
},
|
||||
|
||||
onSelection() {
|
||||
if(this.disable){
|
||||
return
|
||||
if (this.disable) {
|
||||
return;
|
||||
}
|
||||
this.$nextTick(_ => {
|
||||
this.selects = $A.cloneJSON(this.values)
|
||||
this.showModal = true
|
||||
})
|
||||
this.selects = $A.cloneJSON(this.values);
|
||||
this.showModal = true;
|
||||
});
|
||||
},
|
||||
|
||||
onSelectAll() {
|
||||
if (this.isSelectAll) {
|
||||
this.selects = $A.cloneJSON(this.uncancelable)
|
||||
return
|
||||
this.selects = $A.cloneJSON(this.uncancelable);
|
||||
return;
|
||||
}
|
||||
this.lists.some(item => {
|
||||
if (this.isDisabled(item.userid)) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
if (this.multipleMax && this.selects.length >= this.multipleMax) {
|
||||
$A.messageWarning("已超过最大选择数量")
|
||||
return true
|
||||
$A.messageWarning("已超过最大选择数量");
|
||||
return true;
|
||||
}
|
||||
if (!this.selects.includes(item.userid)) {
|
||||
this.selects.push(item.userid)
|
||||
this.selects.push(item.userid);
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
onSelectItem({userid}) {
|
||||
onSelectItem({ userid }) {
|
||||
if (this.selects.includes(userid)) {
|
||||
if (this.isUncancelable(userid)) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
this.selects = this.selects.filter(value => value != userid)
|
||||
} else {
|
||||
this.selects = this.selects.filter(value => value != userid);
|
||||
}
|
||||
else {
|
||||
if (this.isDisabled(userid)) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
if (this.multipleMax && this.selects.length >= this.multipleMax) {
|
||||
$A.messageWarning("已超过最大选择数量")
|
||||
return
|
||||
$A.messageWarning("已超过最大选择数量");
|
||||
return;
|
||||
}
|
||||
this.selects.push(userid)
|
||||
this.selects.push(userid);
|
||||
// 滚动到选中的位置
|
||||
this.$nextTick(() => {
|
||||
$A.scrollIntoViewIfNeeded(this.$refs.selected.querySelector(`li[data-id="${userid}"]`))
|
||||
})
|
||||
$A.scrollIntoViewIfNeeded(this.$refs.selected.querySelector(`li[data-id="${userid}"]`));
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
onSelectProject(userid_list) {
|
||||
switch (this.selectIcon(userid_list)) {
|
||||
case 'ios-checkmark-circle':
|
||||
// 去除
|
||||
const removeList = userid_list.filter(userid => !this.isUncancelable(userid))
|
||||
const removeList = userid_list.filter(userid => !this.isUncancelable(userid));
|
||||
if (removeList.length != userid_list.length) {
|
||||
$A.messageWarning("部分成员禁止取消")
|
||||
$A.messageWarning("部分成员禁止取消");
|
||||
}
|
||||
this.selects = this.selects.filter(userid => !removeList.includes(userid))
|
||||
this.selects = this.selects.filter(userid => !removeList.includes(userid));
|
||||
break;
|
||||
default:
|
||||
// 添加
|
||||
const addList = userid_list.filter(userid => !this.isDisabled(userid))
|
||||
const addList = userid_list.filter(userid => !this.isDisabled(userid));
|
||||
if (addList.length != userid_list.length) {
|
||||
$A.messageWarning("部分成员禁止选择")
|
||||
$A.messageWarning("部分成员禁止选择");
|
||||
}
|
||||
this.selects = this.selects.concat(addList.filter(userid => !this.selects.includes(userid)))
|
||||
this.selects = this.selects.concat(addList.filter(userid => !this.selects.includes(userid)));
|
||||
// 超过最大数量
|
||||
if (this.multipleMax && this.selects.length > this.multipleMax) {
|
||||
$A.messageWarning("已超过最大选择数量")
|
||||
this.selects = this.selects.slice(0, this.multipleMax)
|
||||
$A.messageWarning("已超过最大选择数量");
|
||||
this.selects = this.selects.slice(0, this.multipleMax);
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
onRemoveItem(userid) {
|
||||
if (this.isUncancelable(userid)) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
this.selects = this.selects.filter(value => value != userid)
|
||||
this.selects = this.selects.filter(value => value != userid);
|
||||
},
|
||||
|
||||
onSubmit() {
|
||||
onSubmit(index) {
|
||||
if (this.submittIng > 0) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
const clone = $A.cloneJSON(this.values)
|
||||
this.values = $A.cloneJSON(this.selects)
|
||||
this.$emit('input', this.values)
|
||||
this.$emit('onSubmit', this.values)
|
||||
|
||||
const clone = $A.cloneJSON(this.values);
|
||||
this.values = $A.cloneJSON(this.selects);
|
||||
//
|
||||
if (index !=2 && this.twiceAffirm) {
|
||||
if (this.values.length < 1) {
|
||||
$A.messageError("请选择对话或成员");
|
||||
return;
|
||||
}
|
||||
this.showAffirmModal = true;
|
||||
return;
|
||||
}
|
||||
//
|
||||
this.$emit('input', this.values);
|
||||
this.$emit('onSubmit', this.values);
|
||||
if (!this.beforeSubmit) {
|
||||
this.showModal = false
|
||||
return
|
||||
this.showModal = false;
|
||||
this.showAffirmModal = false;
|
||||
return;
|
||||
}
|
||||
const before = this.beforeSubmit();
|
||||
if (before && before.then) {
|
||||
this.submittIng++
|
||||
this.submittIng++;
|
||||
before.then(() => {
|
||||
this.showModal = false
|
||||
this.showModal = false;
|
||||
this.showAffirmModal = false;
|
||||
}).catch(() => {
|
||||
this.values = clone
|
||||
this.$emit('input', this.values)
|
||||
this.values = clone;
|
||||
this.$emit('input', this.values);
|
||||
}).finally(() => {
|
||||
this.submittIng--
|
||||
})
|
||||
} else {
|
||||
this.showModal = false
|
||||
this.submittIng--;
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.showModal = false;
|
||||
this.showAffirmModal = false;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
{{source.msg.notice}}
|
||||
</div>
|
||||
<template v-else>
|
||||
<div class="dialog-avatar">
|
||||
<div class="dialog-avatar" v-if="dialogAvatar">
|
||||
<UserAvatar
|
||||
v-longpress="{callback: onMention, delay: 300}"
|
||||
@open-dialog="onOpenDialog"
|
||||
@ -94,6 +94,10 @@ export default {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
dialogAvatar: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
|
||||
@ -14,6 +14,10 @@
|
||||
<UserAvatar :userid="msgData.reply_data.userid" :show-icon="false" :show-name="true" :tooltip-disabled="true"/>
|
||||
<div class="reply-desc" v-html="$A.getMsgSimpleDesc(msgData.reply_data, 'image-preview')"></div>
|
||||
</div>
|
||||
<!--转发-->
|
||||
<div v-if="msgData.forward_show && msgData.forward_data && msgData.forward_data.userid" class="dialog-reply no-dark-content" @click="openDialog(msgData.forward_data.userid)">
|
||||
<UserAvatar :userid="msgData.forward_data.userid" :show-icon="false" :show-name="true" :tooltip-disabled="true"/>
|
||||
</div>
|
||||
<!--详情-->
|
||||
<div ref="content" class="dialog-content" :class="contentClass">
|
||||
<!--文本-->
|
||||
@ -453,6 +457,14 @@ export default {
|
||||
});
|
||||
},
|
||||
|
||||
openDialog(userid) {
|
||||
this.$store.dispatch("openDialogUserid", userid).then(_ => {
|
||||
this.goForward({name: 'manage-messenger'})
|
||||
}).catch(({msg}) => {
|
||||
$A.modalError(msg)
|
||||
});
|
||||
},
|
||||
|
||||
viewReply() {
|
||||
this.$emit("on-view-reply", {
|
||||
msg_id: this.msgData.id,
|
||||
|
||||
@ -391,10 +391,32 @@
|
||||
v-model="forwardData"
|
||||
:multiple-max="50"
|
||||
:title="$L('转发')"
|
||||
:twice-affirm="true"
|
||||
:twice-affirm-title="$L('转发给:')"
|
||||
:before-submit="onForward"
|
||||
:show-select-all="false"
|
||||
show-dialog
|
||||
module/>
|
||||
module>
|
||||
<template #twice-affirm-body-extend>
|
||||
<div class="dialog-wrapper-forward-body">
|
||||
<div class="dialog-wrapper ">
|
||||
<div class="dialog-scroller">
|
||||
<DialogItem :source="operateItem" simpleView :dialogAvatar="false"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="leave-message">
|
||||
<Input type="textarea" :autosize="{minRows: 1,maxRows: 3}" v-model="forwardLeaveMessage" :placeholder="$L('留言')" clearable />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #twice-affirm-footer-extend>
|
||||
<div class="dialog-wrapper-forward-footer" :class="{'selected': !forwardShowOriginal}" @click="forwardShowOriginal = !forwardShowOriginal">
|
||||
<Icon v-if="!forwardShowOriginal" class="user-modal-icon" type="ios-checkmark-circle" />
|
||||
<Icon v-else class="user-modal-icon" type="ios-radio-button-off" />
|
||||
{{$L('不显示原发送者信息')}}
|
||||
</div>
|
||||
</template>
|
||||
</UserSelect>
|
||||
|
||||
<!-- 设置待办 -->
|
||||
<Modal
|
||||
@ -601,6 +623,8 @@ export default {
|
||||
modifyLoad: 0,
|
||||
|
||||
forwardData: [],
|
||||
forwardShowOriginal: true,
|
||||
forwardLeaveMessage: '',
|
||||
|
||||
openId: 0,
|
||||
dialogDrag: false,
|
||||
@ -662,7 +686,7 @@ export default {
|
||||
approveDetailsShow: false,
|
||||
approvaUserStatus: '',
|
||||
|
||||
mountedNow: 0,
|
||||
mountedNow: 0
|
||||
}
|
||||
},
|
||||
|
||||
@ -2203,6 +2227,7 @@ export default {
|
||||
reject();
|
||||
return
|
||||
}
|
||||
|
||||
const dialogids = this.forwardData.filter(value => $A.leftExists(value, 'd:')).map(value => value.replace('d:', ''));
|
||||
const userids = this.forwardData.filter(value => !$A.leftExists(value, 'd:'));
|
||||
this.$store.dispatch("call", {
|
||||
@ -2210,7 +2235,9 @@ export default {
|
||||
data: {
|
||||
dialogids,
|
||||
userids,
|
||||
msg_id: this.operateItem.id
|
||||
msg_id: this.operateItem.id,
|
||||
show_source: this.forwardShowOriginal ? 1 : 0,
|
||||
leave_message: this.forwardLeaveMessage
|
||||
}
|
||||
}).then(({data, msg}) => {
|
||||
this.$store.dispatch("saveDialogMsg", data.msgs);
|
||||
@ -2433,6 +2460,8 @@ export default {
|
||||
|
||||
case "forward":
|
||||
this.forwardData = [];
|
||||
this.forwardLeaveMessage = '';
|
||||
this.forwardShowOriginal = true;
|
||||
this.$refs.forwardSelect.onSelection()
|
||||
break;
|
||||
|
||||
|
||||
@ -172,6 +172,13 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.twice-affirm{
|
||||
padding-bottom: 20px;
|
||||
.search-selected{
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.user-modal-switch {
|
||||
@ -416,12 +423,19 @@
|
||||
border-radius: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.twice-affirm-body-extend{
|
||||
margin: 0 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.ivu-modal-footer {
|
||||
border-top: 1px solid #f2f2f2 !important;
|
||||
padding: 12px 0 !important;
|
||||
margin: 0 24px !important;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
&.ivu-modal-fullscreen {
|
||||
@ -462,4 +476,10 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
&.twice-affirm-modal{
|
||||
.ivu-modal {
|
||||
max-width: 90%;
|
||||
margin: 10px auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1448,6 +1448,51 @@
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-wrapper-forward-body{
|
||||
.dialog-wrapper{
|
||||
position: relative !important;
|
||||
.dialog-scroller{
|
||||
padding: 0 !important;
|
||||
.dialog-view{
|
||||
width: 100%;
|
||||
max-width: 100% !important;
|
||||
margin: 0 !important;
|
||||
.dialog-head{
|
||||
width: 100%;
|
||||
border-radius: 8px !important;
|
||||
}
|
||||
.dialog-foot{
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.leave-message{
|
||||
padding-bottom: 16px;
|
||||
textarea{
|
||||
background: #f7f7f7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-wrapper-forward-footer{
|
||||
display: flex;
|
||||
line-height: 34px;
|
||||
cursor: pointer;
|
||||
.user-modal-icon {
|
||||
flex-shrink: 0;
|
||||
font-size: 22px;
|
||||
margin-right: 5px;
|
||||
color: rgba($primary-desc-color, 0.7);
|
||||
margin-top: 6px;
|
||||
}
|
||||
&.selected {
|
||||
.user-modal-icon {
|
||||
color: $primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-wrapper-read-poptip {
|
||||
width: 360px;
|
||||
max-width: 72%;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user