mirror of
https://github.com/kuaifan/dootask.git
synced 2026-01-20 07:58:12 +00:00
perf: 优化会员选择器
This commit is contained in:
parent
29bbbd804a
commit
04632182b4
@ -2,14 +2,18 @@
|
|||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
## [0.27.31]
|
## [0.27.36]
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
|
- 打开会话面板报错
|
||||||
- 子任务通知无法打开
|
- 子任务通知无法打开
|
||||||
|
|
||||||
### Performance
|
### Performance
|
||||||
|
|
||||||
|
- 优化会员选择器
|
||||||
|
- 优化会员选择器
|
||||||
|
- 优化图片压缩
|
||||||
- 回复图片显示图片搜略图
|
- 回复图片显示图片搜略图
|
||||||
- 优化会员选择器
|
- 优化会员选择器
|
||||||
- 会员选择下拉框提示
|
- 会员选择下拉框提示
|
||||||
|
|||||||
@ -56,9 +56,15 @@ class ProjectController extends AbstractController
|
|||||||
* - all:全部
|
* - all:全部
|
||||||
* - no:未归档(默认)
|
* - no:未归档(默认)
|
||||||
* - yes:已归档
|
* - yes:已归档
|
||||||
* @apiParam {String} [getcolumn] 同时取项目列表
|
* @apiParam {String} [getcolumn] 同时取列表
|
||||||
* - no:不取(默认)
|
* - no:不取(默认)
|
||||||
* - yes:取列表
|
* - yes:取列表
|
||||||
|
* @apiParam {String} [getuserid] 同时取成员ID
|
||||||
|
* - no:不取(默认)
|
||||||
|
* - yes:取列表
|
||||||
|
* @apiParam {String} [getstatistics] 同时取任务统计
|
||||||
|
* - no:不取
|
||||||
|
* - yes:取统计(默认)
|
||||||
* @apiParam {Object} [keys] 搜索条件
|
* @apiParam {Object} [keys] 搜索条件
|
||||||
* - keys.name: 项目名称
|
* - keys.name: 项目名称
|
||||||
* @apiParam {String} [timerange] 时间范围(如:1678248944,1678248944)
|
* @apiParam {String} [timerange] 时间范围(如:1678248944,1678248944)
|
||||||
@ -110,6 +116,8 @@ class ProjectController extends AbstractController
|
|||||||
$type = Request::input('type', 'all');
|
$type = Request::input('type', 'all');
|
||||||
$archived = Request::input('archived', 'no');
|
$archived = Request::input('archived', 'no');
|
||||||
$getcolumn = Request::input('getcolumn', 'no');
|
$getcolumn = Request::input('getcolumn', 'no');
|
||||||
|
$getuserid = Request::input('getuserid', 'no');
|
||||||
|
$getstatistics = Request::input('getstatistics', 'yes');
|
||||||
$keys = Request::input('keys');
|
$keys = Request::input('keys');
|
||||||
$timerange = TimeRange::parse(Request::input('timerange'));
|
$timerange = TimeRange::parse(Request::input('timerange'));
|
||||||
//
|
//
|
||||||
@ -151,8 +159,15 @@ class ProjectController extends AbstractController
|
|||||||
}
|
}
|
||||||
//
|
//
|
||||||
$list = $builder->orderByDesc('projects.id')->paginate(Base::getPaginate(100, 50));
|
$list = $builder->orderByDesc('projects.id')->paginate(Base::getPaginate(100, 50));
|
||||||
$list->transform(function (Project $project) use ($user) {
|
$list->transform(function (Project $project) use ($getstatistics, $getuserid, $user) {
|
||||||
return array_merge($project->toArray(), $project->getTaskStatistics($user->userid));
|
$array = $project->toArray();
|
||||||
|
if ($getuserid == 'yes') {
|
||||||
|
$array['userid_list'] = ProjectUser::whereProjectId($project->id)->pluck('userid')->toArray();
|
||||||
|
}
|
||||||
|
if ($getstatistics == 'yes') {
|
||||||
|
$array = array_merge($array, $project->getTaskStatistics($user->userid));
|
||||||
|
}
|
||||||
|
return $array;
|
||||||
});
|
});
|
||||||
//
|
//
|
||||||
$data = $list->toArray();
|
$data = $list->toArray();
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "DooTask",
|
"name": "DooTask",
|
||||||
"version": "0.27.31",
|
"version": "0.27.36",
|
||||||
"description": "DooTask is task management system.",
|
"description": "DooTask is task management system.",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "./cmd dev",
|
"start": "./cmd dev",
|
||||||
|
|||||||
@ -1,57 +1,151 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="common-user-select" :class="{'select-border': border}">
|
<div class="common-user-select" :class="warpClass">
|
||||||
<ul @click="onSelect(true)" :style="warpStyle">
|
<ul v-if="!module" @click="onSelection">
|
||||||
<li v-for="userid in values">
|
<li v-for="userid in values">
|
||||||
<UserAvatar :userid="userid" :size="avatarSize" :show-icon="avatarIcon" :show-name="avatarName" tooltip-disabled/>
|
<UserAvatar :userid="userid" :size="avatarSize" :show-icon="avatarIcon" :show-name="avatarName" tooltip-disabled/>
|
||||||
</li>
|
</li>
|
||||||
<li v-if="addIcon || values.length === 0" class="add-icon" :style="addStyle" @click.stop="onSelect"></li>
|
<li v-if="addIcon || values.length === 0" class="add-icon" :style="addStyle" @click.stop="onSelection"></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<Modal
|
<Modal
|
||||||
v-model="showModal"
|
v-model="showModal"
|
||||||
:mask-closable="false"
|
|
||||||
class-name="common-user-select-modal"
|
class-name="common-user-select-modal"
|
||||||
:title="localTitle"
|
:mask-closable="false"
|
||||||
:fullscreen="windowWidth < 576">
|
:closable="!isFullscreen"
|
||||||
|
:fullscreen="isFullscreen"
|
||||||
|
:footer-hide="isFullscreen"
|
||||||
|
width="640">
|
||||||
|
|
||||||
|
<!-- 顶部 -->
|
||||||
|
<template #header>
|
||||||
|
<div v-if="isFullscreen" class="user-modal-header">
|
||||||
|
<div class="user-modal-close" @click="showModal=false">{{$L('关闭')}}</div>
|
||||||
|
<div class="user-modal-title">{{localTitle}}</div>
|
||||||
|
<div class="user-modal-submit" @click="onSubmit">
|
||||||
|
<div v-if="loadIng > 0" class="submit-loading"><Loading /></div>
|
||||||
|
{{$L('确定')}}
|
||||||
|
<template v-if="selects.length > 0">
|
||||||
|
({{selects.length}}<span v-if="multipleMax">/{{multipleMax}}</span>)
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else class="ivu-modal-header-inner">{{localTitle}}</div>
|
||||||
|
</template>
|
||||||
|
<template #close>
|
||||||
|
<i class="ivu-icon ivu-icon-ios-close"></i>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 搜索 -->
|
||||||
<div class="user-modal-search">
|
<div class="user-modal-search">
|
||||||
<Input v-model="searchKey" :placeholder="localPlaceholder" clearable>
|
<Scrollbar ref="selected" 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" @click.stop="onRemoveItem(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>
|
||||||
|
<Icon v-else class="icon-avatar" type="ios-people" />
|
||||||
|
</template>
|
||||||
|
<UserAvatar v-else :userid="item.userid" tooltip-disabled/>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</Scrollbar>
|
||||||
|
<Input class="search-input" v-model="searchKey" :placeholder="localPlaceholder" clearable>
|
||||||
<div class="search-pre" slot="prefix">
|
<div class="search-pre" slot="prefix">
|
||||||
<Loading v-if="loadIng > 0"/>
|
<Loading v-if="loadIng > 0"/>
|
||||||
<Icon v-else type="ios-search" />
|
<Icon v-else type="ios-search" />
|
||||||
</div>
|
</div>
|
||||||
</Input>
|
</Input>
|
||||||
</div>
|
</div>
|
||||||
<Scrollbar class="user-modal-list">
|
|
||||||
<ul>
|
<!-- 切换 -->
|
||||||
|
<ul v-if="isWhole" class="user-modal-switch">
|
||||||
|
<li
|
||||||
|
v-for="item in switchItems" :key="item.key"
|
||||||
|
:class="{active:switchActive===item.key}"
|
||||||
|
@click="switchActive=item.key">{{ $L(item.label) }}</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<!-- 列表 -->
|
||||||
|
<Scrollbar v-if="lists.length > 0" class="user-modal-list">
|
||||||
|
<!-- 项目 -->
|
||||||
|
<ul v-if="switchActive == 'project'" class="user-modal-project">
|
||||||
|
<li
|
||||||
|
v-for="item in lists"
|
||||||
|
:class="selectClass(item.userid_list)"
|
||||||
|
@click="onSelectProject(item.userid_list)">
|
||||||
|
<Icon class="user-modal-icon" :type="selectIcon(item.userid_list)" />
|
||||||
|
<div class="user-modal-avatar">
|
||||||
|
<i class="taskfont icon-avatar"></i>
|
||||||
|
<div class="project-name">
|
||||||
|
<div class="label">{{item.name}}</div>
|
||||||
|
<div class="subtitle">
|
||||||
|
{{item.userid_list.length}} {{$L('项目成员')}}
|
||||||
|
<em class="all">{{$L('已全选')}}</em>
|
||||||
|
<em class="some">{{$L('已选部分')}}</em>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<!-- 会员、会话 -->
|
||||||
|
<ul v-else>
|
||||||
|
<li
|
||||||
|
v-if="showSelectAll"
|
||||||
|
:class="selectClass('all')"
|
||||||
|
@click="onSelectAll">
|
||||||
|
<Icon class="user-modal-icon" :type="selectIcon('all')" />
|
||||||
|
<div class="user-modal-all">{{$L('全选')}}</div>
|
||||||
|
</li>
|
||||||
<li
|
<li
|
||||||
v-for="item in lists"
|
v-for="item in lists"
|
||||||
:class="{
|
:class="{
|
||||||
selected: selects.includes(item.userid),
|
selected: selects.includes(item.userid),
|
||||||
disabled: inUncancelable(item.userid) || isDisabled(item.userid)
|
disabled: isUncancelable(item.userid) || isDisabled(item.userid)
|
||||||
}"
|
}"
|
||||||
@click="selectUser(item)">
|
@click="onSelectItem(item)">
|
||||||
<Icon v-if="selects.includes(item.userid)" class="user-modal-icon" type="ios-checkmark-circle" />
|
<Icon v-if="selects.includes(item.userid)" class="user-modal-icon" type="ios-checkmark-circle" />
|
||||||
<Icon v-else class="user-modal-icon" type="ios-radio-button-off" />
|
<Icon v-else class="user-modal-icon" type="ios-radio-button-off" />
|
||||||
<UserAvatar class="user-modal-avatar" :userid="item.userid" show-name tooltip-disabled/>
|
<div v-if="item.type=='group'" class="user-modal-avatar">
|
||||||
<div class="user-modal-userid">ID: {{item.userid}}</div>
|
<EAvatar v-if="item.avatar" class="img-avatar" :src="item.avatar" :size="40"></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>
|
||||||
|
<Icon v-else class="icon-avatar" type="ios-people" />
|
||||||
|
<div class="avatar-name">
|
||||||
|
<span>{{item.name}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<UserAvatar v-else class="user-modal-avatar" :userid="item.userid" :size="40" show-name tooltip-disabled/>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</Scrollbar>
|
</Scrollbar>
|
||||||
<div v-if="multipleMax" class="user-modal-multiple">
|
<!-- 空 -->
|
||||||
<Checkbox class="multiple-check" v-model="multipleCheck" @on-change="onMultipleChange" :disabled="lists.length === 0">{{$L(multipleCheck ? '取消全选' : '全选')}}</Checkbox>
|
<div v-else class="user-modal-empty">
|
||||||
<div class="multiple-text">
|
<Loading v-if="waitIng > 0"/>
|
||||||
<span>{{$L('最多只能选择' + multipleMax + '个')}}</span>
|
<template v-else>
|
||||||
<em v-if="selects.length">({{$L(`已选${selects.length}个`)}})</em>
|
<div class="empty-icon"><Icon type="ios-cafe-outline" /></div>
|
||||||
</div>
|
<div class="empty-text">{{$L('暂无结果')}}</div>
|
||||||
</div>
|
</template>
|
||||||
<div slot="footer" class="adaption">
|
|
||||||
<Button type="default" :loading="submittIng > 0" @click="showModal=false">{{$L('取消')}}</Button>
|
|
||||||
<Button type="primary" :loading="submittIng > 0" @click="onSubmit">{{$L('确定')}}</Button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 底部 -->
|
||||||
|
<template #footer>
|
||||||
|
<Button type="primary" :loading="submittIng > 0" @click="onSubmit">
|
||||||
|
{{$L('确定')}}
|
||||||
|
<template v-if="selects.length > 0">
|
||||||
|
({{selects.length}}<span v-if="multipleMax">/{{multipleMax}}</span>)
|
||||||
|
</template>
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
</Modal>
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import {mapState} from "vuex";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'UserSelect',
|
name: 'UserSelect',
|
||||||
props: {
|
props: {
|
||||||
@ -75,6 +169,7 @@ export default {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 指定项目ID
|
// 指定项目ID
|
||||||
projectId: {
|
projectId: {
|
||||||
type: Number,
|
type: Number,
|
||||||
@ -90,6 +185,7 @@ export default {
|
|||||||
type: Number,
|
type: Number,
|
||||||
default: 0
|
default: 0
|
||||||
},
|
},
|
||||||
|
|
||||||
// 是否显示机器人
|
// 是否显示机器人
|
||||||
showBot: {
|
showBot: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@ -120,16 +216,11 @@ export default {
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
// 是否显示添加按钮(已选择为空时一定是true)
|
// 是否显示添加按钮(已选择为空时强制true)
|
||||||
addIcon: {
|
addIcon: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
},
|
},
|
||||||
// 是否只有点击添加按钮才显示弹窗
|
|
||||||
onlyAddIconClick: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
// 显示边框
|
// 显示边框
|
||||||
border: {
|
border: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@ -145,25 +236,49 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 显示全选项
|
||||||
|
showSelectAll: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
// 显示所有会话(会话返回格式:d:{会话ID},建议配合 module=true 一起使用)
|
||||||
|
showDialog: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
// 模块化(通过 api 方法调用)
|
||||||
|
module: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
|
||||||
// 提交前的回调
|
// 提交前的回调
|
||||||
beforeSubmit: Function
|
beforeSubmit: Function
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loadIng: 0,
|
switchItems: [
|
||||||
submittIng: 0,
|
{key: 'recent', label: '最近'},
|
||||||
|
{key: 'contact', label: '通讯录'},
|
||||||
|
{key: 'project', label: '项目成员'},
|
||||||
|
],
|
||||||
|
switchActive: 'recent',
|
||||||
|
|
||||||
|
loadIng: 0, // 搜索框等待效果
|
||||||
|
waitIng: 0, // 页面等待效果
|
||||||
|
submittIng: 0, // 提交按钮等待效果
|
||||||
|
|
||||||
values: [],
|
values: [],
|
||||||
lists: [],
|
|
||||||
selects: [],
|
selects: [],
|
||||||
|
|
||||||
|
recents: [],
|
||||||
|
contacts: [],
|
||||||
|
projects: [],
|
||||||
|
|
||||||
showModal: false,
|
showModal: false,
|
||||||
|
|
||||||
multipleCheck: false,
|
|
||||||
|
|
||||||
searchTimer: null,
|
|
||||||
searchKey: null,
|
searchKey: null,
|
||||||
searchHistory: [],
|
searchCache: [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@ -179,73 +294,210 @@ export default {
|
|||||||
},
|
},
|
||||||
immediate: true
|
immediate: true
|
||||||
},
|
},
|
||||||
|
|
||||||
|
isWhole: {
|
||||||
|
handler(value) {
|
||||||
|
if (value) {
|
||||||
|
this.switchActive = 'recent'
|
||||||
|
} else {
|
||||||
|
this.switchActive = 'contact'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
},
|
||||||
|
|
||||||
showModal(value) {
|
showModal(value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
this.searchUser()
|
this.searchBefore()
|
||||||
} else {
|
} else {
|
||||||
this.searchKey = ""
|
this.searchKey = ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
searchKey() {
|
searchKey() {
|
||||||
this.searchUser()
|
this.searchBefore()
|
||||||
},
|
},
|
||||||
'lists.length'() {
|
|
||||||
this.calcMultiple()
|
switchActive() {
|
||||||
},
|
this.searchBefore()
|
||||||
'selects.length'() {
|
|
||||||
this.calcMultiple()
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
warpStyle() {
|
...mapState([
|
||||||
if (!this.onlyAddIconClick) {
|
'cacheDialogs',
|
||||||
return {
|
]),
|
||||||
cursor: 'pointer'
|
|
||||||
}
|
isFullscreen({windowWidth}) {
|
||||||
}
|
return windowWidth < 576
|
||||||
},
|
},
|
||||||
addStyle() {
|
|
||||||
|
isWhole({projectId, noProjectId, dialogId}) {
|
||||||
|
return projectId === 0 && noProjectId === 0 && dialogId === 0
|
||||||
|
},
|
||||||
|
|
||||||
|
lists({switchActive, searchKey, recents, contacts, projects}) {
|
||||||
|
switch (switchActive) {
|
||||||
|
case 'recent':
|
||||||
|
if (searchKey) {
|
||||||
|
return recents.filter(item => {
|
||||||
|
return `${item.name}`.indexOf(searchKey) > -1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return recents
|
||||||
|
|
||||||
|
case 'contact':
|
||||||
|
return contacts
|
||||||
|
|
||||||
|
case 'project':
|
||||||
|
return projects
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
},
|
||||||
|
|
||||||
|
isSelectAll({lists, selects}) {
|
||||||
|
return lists.length > 0 && lists.filter(item => selects.includes(item.userid)).length === lists.length;
|
||||||
|
},
|
||||||
|
|
||||||
|
warpClass() {
|
||||||
return {
|
return {
|
||||||
width: this.avatarSize + 'px',
|
'select-module': this.module,
|
||||||
height: this.avatarSize + 'px',
|
'select-border': this.border,
|
||||||
|
'select-whole': this.isWhole,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
localTitle() {
|
|
||||||
if (this.title === undefined) {
|
addStyle({avatarSize}) {
|
||||||
|
return {
|
||||||
|
width: avatarSize + 'px',
|
||||||
|
height: avatarSize + 'px',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
localTitle({title}) {
|
||||||
|
if (title === undefined) {
|
||||||
return this.$L('选择会员')
|
return this.$L('选择会员')
|
||||||
} else {
|
} else {
|
||||||
return this.title;
|
return title;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
localPlaceholder() {
|
|
||||||
if (this.placeholder === undefined) {
|
localPlaceholder({placeholder}) {
|
||||||
return this.$L('搜索会员')
|
if (placeholder === undefined) {
|
||||||
|
return this.$L('搜索')
|
||||||
} else {
|
} else {
|
||||||
return this.placeholder;
|
return placeholder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
searchUser() {
|
isUncancelable(value) {
|
||||||
|
if (this.uncancelable.length === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return this.uncancelable.includes(value);
|
||||||
|
},
|
||||||
|
|
||||||
|
isDisabled(userid) {
|
||||||
|
if (this.disabledChoice.length === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
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 {
|
||||||
|
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
|
||||||
|
if (len === value.length) {
|
||||||
|
return 'ios-checkmark-circle';
|
||||||
|
}
|
||||||
|
if (len > 0) {
|
||||||
|
return 'ios-radio-button-on';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 'ios-radio-button-off';
|
||||||
|
},
|
||||||
|
|
||||||
|
selectClass(value) {
|
||||||
|
switch (this.selectIcon(value)) {
|
||||||
|
case 'ios-checkmark-circle':
|
||||||
|
return 'selected';
|
||||||
|
case 'ios-radio-button-on':
|
||||||
|
return 'somed';
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
},
|
||||||
|
|
||||||
|
searchBefore() {
|
||||||
if (!this.showModal) {
|
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()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
searchRecent() {
|
||||||
|
this.recents = this.cacheDialogs.filter(dialog => {
|
||||||
|
if (dialog.name === undefined || dialog.dialog_delete === 1) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (!this.showBot && dialog.bot) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
if (a.todo_num > 0 || b.todo_num > 0) {
|
||||||
|
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}) => {
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
type,
|
||||||
|
group_type,
|
||||||
|
avatar,
|
||||||
|
userid: type === 'user' ? dialog_user.userid : `d:${id}`,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
searchContact() {
|
||||||
let key = this.searchKey;
|
let key = this.searchKey;
|
||||||
const history = this.searchHistory.find(item => item.key == key);
|
const cache = this.searchCache.find(item => item.type === 'contact' && item.key == key);
|
||||||
if (history) {
|
if (cache) {
|
||||||
this.lists = history.data
|
this.contacts = cache.data
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
if (this.searchTimer) {
|
this.waitIng++
|
||||||
clearTimeout(this.searchTimer);
|
setTimeout(() => {
|
||||||
}
|
|
||||||
this.searchTimer = setTimeout(() => {
|
|
||||||
if (this.searchKey != key) {
|
if (this.searchKey != key) {
|
||||||
|
this.waitIng--
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.loadIng++;
|
this.loadIng++
|
||||||
}, 300)
|
}, 300)
|
||||||
this.$store.dispatch("call", {
|
this.$store.dispatch("call", {
|
||||||
url: 'users/search',
|
url: 'users/search',
|
||||||
@ -261,35 +513,154 @@ export default {
|
|||||||
take: 50
|
take: 50
|
||||||
},
|
},
|
||||||
}).then(({data}) => {
|
}).then(({data}) => {
|
||||||
this.lists = data
|
data = data.map(item => Object.assign(item, {type: 'user'}))
|
||||||
|
this.contacts = data
|
||||||
//
|
//
|
||||||
const index = this.searchHistory.findIndex(item => item.key == key);
|
const index = this.searchCache.findIndex(item => item.key == key);
|
||||||
const tmpData = {key, data, time: $A.Time()};
|
const tmpData = {type: 'contact', key, data, time: $A.Time()};
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
this.searchHistory.splice(index, 1, tmpData)
|
this.searchCache.splice(index, 1, tmpData)
|
||||||
} else {
|
} else {
|
||||||
this.searchHistory.push(tmpData)
|
this.searchCache.push(tmpData)
|
||||||
}
|
}
|
||||||
}).catch(({msg}) => {
|
}).catch(({msg}) => {
|
||||||
this.lists = []
|
this.contacts = []
|
||||||
$A.messageWarning(msg)
|
$A.messageWarning(msg)
|
||||||
}).finally(_ => {
|
}).finally(_ => {
|
||||||
this.loadIng--;
|
this.loadIng--;
|
||||||
|
this.waitIng--;
|
||||||
});
|
});
|
||||||
}, this.searchHistory.length > 0 ? 300 : 0)
|
}, this.searchCache.length > 0 ? 300 : 0)
|
||||||
},
|
},
|
||||||
|
|
||||||
onSelect(warp = false) {
|
searchProject() {
|
||||||
if (warp === true) {
|
let key = this.searchKey;
|
||||||
if (this.onlyAddIconClick) {
|
const cache = this.searchCache.find(item => item.type === 'project' && item.key == key);
|
||||||
|
if (cache) {
|
||||||
|
this.projects = cache.data
|
||||||
|
}
|
||||||
|
//
|
||||||
|
this.waitIng++
|
||||||
|
setTimeout(() => {
|
||||||
|
if (this.searchKey != key) {
|
||||||
|
this.waitIng--
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
this.loadIng++
|
||||||
|
}, 300)
|
||||||
|
this.$store.dispatch("call", {
|
||||||
|
url: 'project/lists',
|
||||||
|
data: {
|
||||||
|
type: 'team',
|
||||||
|
keys: {
|
||||||
|
name: key,
|
||||||
|
},
|
||||||
|
getuserid: 'yes',
|
||||||
|
getstatistics: 'no'
|
||||||
|
},
|
||||||
|
}).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()};
|
||||||
|
if (index > -1) {
|
||||||
|
this.searchCache.splice(index, 1, tmpData)
|
||||||
|
} else {
|
||||||
|
this.searchCache.push(tmpData)
|
||||||
|
}
|
||||||
|
}).catch(({msg}) => {
|
||||||
|
this.projects = []
|
||||||
|
$A.messageWarning(msg)
|
||||||
|
}).finally(_ => {
|
||||||
|
this.loadIng--;
|
||||||
|
this.waitIng--;
|
||||||
|
});
|
||||||
|
}, this.searchCache.length > 0 ? 300 : 0)
|
||||||
|
},
|
||||||
|
|
||||||
|
onSelection() {
|
||||||
|
this.$nextTick(_ => {
|
||||||
|
this.selects = $A.cloneJSON(this.values)
|
||||||
|
this.showModal = true
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
onSelectAll() {
|
||||||
|
if (this.isSelectAll) {
|
||||||
|
this.selects = $A.cloneJSON(this.uncancelable)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let optional = this.multipleMax - this.selects.length
|
||||||
|
this.lists.some(item => {
|
||||||
|
if (this.isUncancelable(item.userid)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (this.isDisabled(item.userid)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (optional <= 0) {
|
||||||
|
$A.messageWarning("已超过最大选择数量")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (!this.selects.includes(item.userid)) {
|
||||||
|
this.selects.push(item.userid)
|
||||||
|
optional--
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
onSelectItem({userid}) {
|
||||||
|
if (this.selects.includes(userid)) {
|
||||||
|
if (this.isUncancelable(userid)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
this.selects = this.selects.filter(value => value != userid)
|
||||||
|
} else {
|
||||||
|
if (this.isDisabled(userid)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (this.multipleMax && this.selects.length >= this.multipleMax) {
|
||||||
|
$A.messageWarning("已超过最大选择数量")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.selects.push(userid)
|
||||||
|
this.$nextTick(() => {
|
||||||
|
$A.scrollIntoViewIfNeeded(this.$refs.selected.querySelector(`li[data-id="${userid}"]`))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
this.selects = $A.cloneJSON(this.values)
|
},
|
||||||
this.showModal = true
|
|
||||||
|
onSelectProject(userid_list) {
|
||||||
|
switch (this.selectIcon(userid_list)) {
|
||||||
|
case 'ios-checkmark-circle':
|
||||||
|
// 去除
|
||||||
|
const removeList = userid_list.filter(userid => !this.isUncancelable(userid))
|
||||||
|
if (removeList.length != userid_list.length) {
|
||||||
|
$A.messageWarning("部分成员禁止取消")
|
||||||
|
}
|
||||||
|
this.selects = this.selects.filter(userid => !removeList.includes(userid))
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// 添加
|
||||||
|
const addList = userid_list.filter(userid => !this.isDisabled(userid))
|
||||||
|
if (addList.length != userid_list.length) {
|
||||||
|
$A.messageWarning("部分成员禁止选择")
|
||||||
|
}
|
||||||
|
this.selects = this.selects.concat(addList.filter(userid => !this.selects.includes(userid)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onRemoveItem(userid) {
|
||||||
|
this.selects = this.selects.filter(value => value != userid)
|
||||||
},
|
},
|
||||||
|
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
|
if (this.submittIng > 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
const clone = $A.cloneJSON(this.values)
|
const clone = $A.cloneJSON(this.values)
|
||||||
this.values = $A.cloneJSON(this.selects)
|
this.values = $A.cloneJSON(this.selects)
|
||||||
this.$emit('input', this.values)
|
this.$emit('input', this.values)
|
||||||
@ -313,69 +684,6 @@ export default {
|
|||||||
this.showModal = false
|
this.showModal = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onMultipleChange(check) {
|
|
||||||
if (check) {
|
|
||||||
let optional = this.multipleMax - this.selects.length
|
|
||||||
this.lists.some(item => {
|
|
||||||
if (this.inUncancelable(item.userid)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (this.isDisabled(item.userid)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (optional <= 0) {
|
|
||||||
$A.messageWarning("已超过最大选择数量")
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if (!this.selects.includes(item.userid)) {
|
|
||||||
this.selects.push(item.userid)
|
|
||||||
optional--
|
|
||||||
}
|
|
||||||
})
|
|
||||||
this.calcMultiple()
|
|
||||||
} else {
|
|
||||||
this.selects = $A.cloneJSON(this.uncancelable)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
calcMultiple() {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.multipleCheck = this.lists.length > 0 && this.lists.filter(item => this.selects.includes(item.userid)).length === this.lists.length;
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
selectUser(item) {
|
|
||||||
if (this.selects.includes(item.userid)) {
|
|
||||||
if (this.inUncancelable(item.userid)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.selects = this.selects.filter(userid => userid != item.userid)
|
|
||||||
} else {
|
|
||||||
if (this.isDisabled(item.userid)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (this.multipleMax && this.selects.length >= this.multipleMax) {
|
|
||||||
$A.messageWarning("已超过最大选择数量")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.selects.push(item.userid)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
inUncancelable(value) {
|
|
||||||
if (this.uncancelable.length === 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return this.uncancelable.includes(value);
|
|
||||||
},
|
|
||||||
|
|
||||||
isDisabled(userid) {
|
|
||||||
if (this.disabledChoice.length === 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return this.disabledChoice.includes(userid)
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,78 +0,0 @@
|
|||||||
<template>
|
|
||||||
<Form ref="forwardForm" :model="value" label-width="auto" @submit.native.prevent>
|
|
||||||
<FormItem prop="dialogids" :label="$L('最近聊天')">
|
|
||||||
<Select
|
|
||||||
v-model="value.dialogids"
|
|
||||||
:placeholder="$L('选择转发最近聊天')"
|
|
||||||
:multiple-max="20"
|
|
||||||
multiple
|
|
||||||
filterable
|
|
||||||
class="dialog-wrapper-dialogids"
|
|
||||||
transfer-class-name="dialog-wrapper-forward">
|
|
||||||
<div slot="drop-prepend" class="forward-drop-prepend">{{$L('最多只能选择20个')}}</div>
|
|
||||||
<Option
|
|
||||||
v-for="(dialog, key) in dialogList"
|
|
||||||
:value="dialog.id"
|
|
||||||
:key="key"
|
|
||||||
:key-value="dialog.name"
|
|
||||||
:label="dialog.name">
|
|
||||||
<div class="forward-option">
|
|
||||||
<div class="forward-avatar">
|
|
||||||
<template v-if="dialog.type=='group'">
|
|
||||||
<i v-if="dialog.group_type=='department'" class="taskfont icon-avatar department"></i>
|
|
||||||
<i v-else-if="dialog.group_type=='project'" class="taskfont icon-avatar project"></i>
|
|
||||||
<i v-else-if="dialog.group_type=='task'" class="taskfont icon-avatar task"></i>
|
|
||||||
<Icon v-else class="icon-avatar" type="ios-people" />
|
|
||||||
</template>
|
|
||||||
<div v-else-if="dialog.dialog_user" class="user-avatar"><UserAvatar :userid="dialog.dialog_user.userid" :size="26"/></div>
|
|
||||||
<Icon v-else class="icon-avatar" type="md-person" />
|
|
||||||
</div>
|
|
||||||
<div class="forward-name">{{ dialog.name }}</div>
|
|
||||||
</div>
|
|
||||||
</Option>
|
|
||||||
</Select>
|
|
||||||
</FormItem>
|
|
||||||
<FormItem prop="userids" :label="`(${$L('或')}) ${$L('指定成员')}`">
|
|
||||||
<UserSelect v-model="value.userids" :multiple-max="20" :avatar-size="24" :title="$L('选择转发指定成员')" border/>
|
|
||||||
</FormItem>
|
|
||||||
</Form>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
import {mapState} from "vuex";
|
|
||||||
import UserSelect from "../../../components/UserSelect.vue";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "DialogSelect",
|
|
||||||
components: {UserSelect},
|
|
||||||
props: {
|
|
||||||
value: {
|
|
||||||
type: Object,
|
|
||||||
default: () => {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
|
||||||
...mapState([
|
|
||||||
'cacheDialogs',
|
|
||||||
]),
|
|
||||||
|
|
||||||
dialogList() {
|
|
||||||
return this.cacheDialogs.filter(dialog => {
|
|
||||||
return !(dialog.name === undefined || dialog.dialog_delete === 1);
|
|
||||||
}).sort((a, b) => {
|
|
||||||
if (a.top_at || b.top_at) {
|
|
||||||
return $A.Date(b.top_at) - $A.Date(a.top_at);
|
|
||||||
}
|
|
||||||
if (a.todo_num > 0 || b.todo_num > 0) {
|
|
||||||
return b.todo_num - a.todo_num;
|
|
||||||
}
|
|
||||||
return $A.Date(b.last_at) - $A.Date(a.last_at);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@ -376,16 +376,15 @@
|
|||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<!-- 转发 -->
|
<!-- 转发 -->
|
||||||
<Modal
|
<UserSelect
|
||||||
v-model="forwardShow"
|
ref="forwardSelect"
|
||||||
|
v-model="forwardData"
|
||||||
|
:multiple-max="50"
|
||||||
:title="$L('转发')"
|
:title="$L('转发')"
|
||||||
:mask-closable="false">
|
:before-submit="onForward"
|
||||||
<DialogSelect v-model="forwardData"/>
|
:show-select-all="false"
|
||||||
<div slot="footer" class="adaption">
|
show-dialog
|
||||||
<Button type="default" @click="forwardShow=false">{{$L('取消')}}</Button>
|
module/>
|
||||||
<Button type="primary" :loading="forwardLoad" @click="onForward('submit')">{{$L('转发')}}</Button>
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
|
|
||||||
<!-- 设置待办 -->
|
<!-- 设置待办 -->
|
||||||
<Modal
|
<Modal
|
||||||
@ -517,7 +516,6 @@ import ChatInput from "./ChatInput";
|
|||||||
|
|
||||||
import VirtualList from 'vue-virtual-scroll-list-hi'
|
import VirtualList from 'vue-virtual-scroll-list-hi'
|
||||||
import {Store} from "le5le-store";
|
import {Store} from "le5le-store";
|
||||||
import DialogSelect from "./DialogSelect";
|
|
||||||
import ImgUpload from "../../../components/ImgUpload.vue";
|
import ImgUpload from "../../../components/ImgUpload.vue";
|
||||||
import {choiceEmojiOne} from "./ChatInput/one";
|
import {choiceEmojiOne} from "./ChatInput/one";
|
||||||
|
|
||||||
@ -529,7 +527,6 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
UserSelect,
|
UserSelect,
|
||||||
ImgUpload,
|
ImgUpload,
|
||||||
DialogSelect,
|
|
||||||
DialogRespond,
|
DialogRespond,
|
||||||
DialogItem,
|
DialogItem,
|
||||||
VirtualList,
|
VirtualList,
|
||||||
@ -592,12 +589,7 @@ export default {
|
|||||||
modifyData: {},
|
modifyData: {},
|
||||||
modifyLoad: 0,
|
modifyLoad: 0,
|
||||||
|
|
||||||
forwardShow: false,
|
forwardData: [],
|
||||||
forwardLoad: false,
|
|
||||||
forwardData: {
|
|
||||||
dialogids: [],
|
|
||||||
userids: [],
|
|
||||||
},
|
|
||||||
|
|
||||||
openId: 0,
|
openId: 0,
|
||||||
dialogDrag: false,
|
dialogDrag: false,
|
||||||
@ -2045,34 +2037,32 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onForward(type) {
|
onForward() {
|
||||||
if (type === 'open') {
|
return new Promise((resolve, reject) => {
|
||||||
this.forwardData = {
|
if (this.forwardData.length === 0) {
|
||||||
dialogids: [],
|
$A.messageError("请选择转发对话或成员");
|
||||||
userids: [],
|
reject();
|
||||||
msg_id: this.operateItem.id
|
|
||||||
};
|
|
||||||
this.forwardShow = true;
|
|
||||||
} else if (type === 'submit') {
|
|
||||||
if ($A.arrayLength(this.forwardData.dialogids) === 0 && $A.arrayLength(this.forwardData.userids) === 0) {
|
|
||||||
$A.messageWarning("请选择转发对话或成员");
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.forwardLoad = true;
|
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", {
|
this.$store.dispatch("call", {
|
||||||
url: 'dialog/msg/forward',
|
url: 'dialog/msg/forward',
|
||||||
data: this.forwardData
|
data: {
|
||||||
|
dialogids,
|
||||||
|
userids,
|
||||||
|
msg_id: this.operateItem.id
|
||||||
|
}
|
||||||
}).then(({data, msg}) => {
|
}).then(({data, msg}) => {
|
||||||
this.forwardShow = false;
|
|
||||||
this.$store.dispatch("saveDialogMsg", data.msgs);
|
this.$store.dispatch("saveDialogMsg", data.msgs);
|
||||||
this.$store.dispatch("updateDialogLastMsg", data.msgs);
|
this.$store.dispatch("updateDialogLastMsg", data.msgs);
|
||||||
$A.messageSuccess(msg);
|
$A.messageSuccess(msg);
|
||||||
|
resolve();
|
||||||
}).catch(({msg}) => {
|
}).catch(({msg}) => {
|
||||||
$A.modalError(msg);
|
$A.modalError(msg);
|
||||||
}).finally(_ => {
|
reject();
|
||||||
this.forwardLoad = false;
|
|
||||||
});
|
});
|
||||||
}
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
onScroll(event) {
|
onScroll(event) {
|
||||||
@ -2237,7 +2227,8 @@ export default {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case "forward":
|
case "forward":
|
||||||
this.onForward('open')
|
this.forwardData = [];
|
||||||
|
this.$refs.forwardSelect.onSelection()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "withdraw":
|
case "withdraw":
|
||||||
|
|||||||
@ -322,16 +322,15 @@
|
|||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<!-- 文件发送 -->
|
<!-- 文件发送 -->
|
||||||
<Modal
|
<UserSelect
|
||||||
v-model="sendShow"
|
ref="sendFile"
|
||||||
|
v-model="sendData"
|
||||||
|
:multiple-max="50"
|
||||||
:title="$L('发送文件')"
|
:title="$L('发送文件')"
|
||||||
:mask-closable="false">
|
:before-submit="onSendFile"
|
||||||
<DialogSelect v-model="sendData"/>
|
:show-select-all="false"
|
||||||
<div slot="footer" class="adaption">
|
show-dialog
|
||||||
<Button type="default" @click="sendShow=false">{{$L('取消')}}</Button>
|
module/>
|
||||||
<Button type="primary" :loading="sendLoad" @click="onSendFile">{{$L('发送文件')}}</Button>
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
|
|
||||||
<!--文件链接-->
|
<!--文件链接-->
|
||||||
<Modal
|
<Modal
|
||||||
@ -401,7 +400,6 @@ import {sortBy} from "lodash";
|
|||||||
import DrawerOverlay from "../../components/DrawerOverlay";
|
import DrawerOverlay from "../../components/DrawerOverlay";
|
||||||
import PreviewImage from "../../components/PreviewImage";
|
import PreviewImage from "../../components/PreviewImage";
|
||||||
import longpress from "../../directives/longpress";
|
import longpress from "../../directives/longpress";
|
||||||
import DialogSelect from "./components/DialogSelect";
|
|
||||||
import UserSelect from "../../components/UserSelect.vue";
|
import UserSelect from "../../components/UserSelect.vue";
|
||||||
|
|
||||||
const FilePreview = () => import('./components/FilePreview');
|
const FilePreview = () => import('./components/FilePreview');
|
||||||
@ -409,7 +407,7 @@ const FileContent = () => import('./components/FileContent');
|
|||||||
const FileObject = {sort: null, mode: null, shared: null};
|
const FileObject = {sort: null, mode: null, shared: null};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {UserSelect, DialogSelect, PreviewImage, FilePreview, DrawerOverlay, FileContent},
|
components: {UserSelect, PreviewImage, FilePreview, DrawerOverlay, FileContent},
|
||||||
directives: {longpress},
|
directives: {longpress},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -477,12 +475,8 @@ export default {
|
|||||||
shareList: [],
|
shareList: [],
|
||||||
shareLoad: 0,
|
shareLoad: 0,
|
||||||
|
|
||||||
sendShow: false,
|
sendFileId: 0,
|
||||||
sendLoad: false,
|
sendData: [],
|
||||||
sendData: {
|
|
||||||
dialogids: [],
|
|
||||||
userids: [],
|
|
||||||
},
|
|
||||||
|
|
||||||
linkShow: false,
|
linkShow: false,
|
||||||
linkData: {},
|
linkData: {},
|
||||||
@ -1197,12 +1191,9 @@ export default {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'send':
|
case 'send':
|
||||||
this.sendData = {
|
this.sendFileId = item.id;
|
||||||
dialogids: [],
|
this.sendData = [];
|
||||||
userids: [],
|
this.$refs.sendFile.onSelection()
|
||||||
file_id: item.id
|
|
||||||
};
|
|
||||||
this.sendShow = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'share':
|
case 'share':
|
||||||
@ -1269,24 +1260,31 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
onSendFile() {
|
onSendFile() {
|
||||||
if ($A.arrayLength(this.sendData.dialogids) === 0 && $A.arrayLength(this.sendData.userids) === 0) {
|
return new Promise((resolve, reject) => {
|
||||||
$A.messageWarning("请选择转发对话或成员");
|
if (this.sendData.length === 0) {
|
||||||
return
|
$A.messageError("请选择转发对话或成员");
|
||||||
}
|
reject();
|
||||||
this.sendLoad = true;
|
return
|
||||||
this.$store.dispatch("call", {
|
}
|
||||||
url: 'dialog/msg/sendfileid',
|
const dialogids = this.sendData.filter(value => $A.leftExists(value, 'd:')).map(value => value.replace('d:', ''));
|
||||||
data: this.sendData
|
const userids = this.sendData.filter(value => !$A.leftExists(value, 'd:'));
|
||||||
}).then(({data, msg}) => {
|
this.$store.dispatch("call", {
|
||||||
this.sendShow = false;
|
url: 'dialog/msg/sendfileid',
|
||||||
this.$store.dispatch("saveDialogMsg", data.msgs);
|
data: {
|
||||||
this.$store.dispatch("updateDialogLastMsg", data.msgs);
|
dialogids,
|
||||||
$A.messageSuccess(msg);
|
userids,
|
||||||
}).catch(({msg}) => {
|
file_id: this.sendFileId
|
||||||
$A.modalError(msg);
|
}
|
||||||
}).finally(_ => {
|
}).then(({data, msg}) => {
|
||||||
this.sendLoad = false;
|
this.$store.dispatch("saveDialogMsg", data.msgs);
|
||||||
});
|
this.$store.dispatch("updateDialogLastMsg", data.msgs);
|
||||||
|
$A.messageSuccess(msg);
|
||||||
|
resolve();
|
||||||
|
}).catch(({msg}) => {
|
||||||
|
$A.modalError(msg);
|
||||||
|
reject();
|
||||||
|
});
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
linkGet(refresh) {
|
linkGet(refresh) {
|
||||||
|
|||||||
531
resources/assets/sass/components/user-select.scss
vendored
531
resources/assets/sass/components/user-select.scss
vendored
@ -1,152 +1,447 @@
|
|||||||
.common-user-select {
|
.common-user-select {
|
||||||
|
&.select-module {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
&.select-border {
|
&.select-border {
|
||||||
border: 1px solid #e8e8e8;
|
border: 1px solid #e8e8e8;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 0 6px;
|
padding: 0 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
> ul {
|
> ul {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
> li {
|
> li {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 3px 6px 3px 0;
|
margin: 3px 6px 3px 0;
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.add-icon {
|
&.add-icon {
|
||||||
cursor: pointer;
|
|
||||||
border-radius: 50%;
|
|
||||||
width: 26px;
|
width: 26px;
|
||||||
height: 26px;
|
height: 26px;
|
||||||
background: #F2F3F5 url("data:image/svg+xml;base64,PHN2ZyB0PSIxNjg2NjIxNjA3NDE0IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik04NzQuNjY2NjY3IDQ3My42aC0zMjQuMjY2NjY3VjE0OS4zMzMzMzNjMC0yMS4zMzMzMzMtMTcuMDY2NjY3LTM4LjQtMzguNC0zOC40cy0zOC40IDE3LjA2NjY2Ny0zOC40IDM4LjR2MzI0LjI2NjY2N0gxNDkuMzMzMzMzYy0yMS4zMzMzMzMgMC0zOC40IDE3LjA2NjY2Ny0zOC40IDM4LjRzMTcuMDY2NjY3IDM4LjQgMzguNCAzOC40aDMyNC4yNjY2Njd2MzI0LjI2NjY2N2MwIDIxLjMzMzMzMyAxNy4wNjY2NjcgMzguNCAzOC40IDM4LjRzMzguNC0xNy4wNjY2NjcgMzguNC0zOC40di0zMjQuMjY2NjY3aDMyNC4yNjY2NjdjMjEuMzMzMzMzIDAgMzguNC0xNy4wNjY2NjcgMzguNC0zOC40cy0xNy4wNjY2NjctMzguNC0zOC40LTM4LjR6IiAgZmlsbD0iIzYwNjI2NiI+PC9wYXRoPjwvc3ZnPg==") no-repeat center;
|
background: #F2F3F5 url("data:image/svg+xml;base64,PHN2ZyB0PSIxNjg2NjIxNjA3NDE0IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik04NzQuNjY2NjY3IDQ3My42aC0zMjQuMjY2NjY3VjE0OS4zMzMzMzNjMC0yMS4zMzMzMzMtMTcuMDY2NjY3LTM4LjQtMzguNC0zOC40cy0zOC40IDE3LjA2NjY2Ny0zOC40IDM4LjR2MzI0LjI2NjY2N0gxNDkuMzMzMzMzYy0yMS4zMzMzMzMgMC0zOC40IDE3LjA2NjY2Ny0zOC40IDM4LjRzMTcuMDY2NjY3IDM4LjQgMzguNCAzOC40aDMyNC4yNjY2Njd2MzI0LjI2NjY2N2MwIDIxLjMzMzMzMyAxNy4wNjY2NjcgMzguNCAzOC40IDM4LjRzMzguNC0xNy4wNjY2NjcgMzguNC0zOC40di0zMjQuMjY2NjY3aDMyNC4yNjY2NjdjMjEuMzMzMzMzIDAgMzguNC0xNy4wNjY2NjcgMzguNC0zOC40cy0xNy4wNjY2NjctMzguNC0zOC40LTM4LjR6IiAgZmlsbD0iIzYwNjI2NiI+PC9wYXRoPjwvc3ZnPg==") no-repeat center;
|
||||||
background-size: 50%;
|
background-size: 50%;
|
||||||
}
|
border-radius: 50%;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.common-user-select-modal {
|
|
||||||
.ivu-modal-body {
|
|
||||||
padding: 0 16px !important;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
.user-modal-search {
|
|
||||||
flex-shrink: 0;
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
z-index: 9;
|
|
||||||
padding: 8px 16px;
|
|
||||||
background: #ffffff;
|
|
||||||
.search-pre {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
.common-loading {
|
|
||||||
width: 14px;
|
|
||||||
height: 14px;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.user-modal-list {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
max-height: 400px;
|
|
||||||
ul {
|
|
||||||
padding: 8px 0;
|
|
||||||
> li {
|
|
||||||
list-style: none;
|
|
||||||
padding: 8px 16px;
|
|
||||||
margin: 0;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
border-radius: 6px;
|
|
||||||
cursor: pointer;
|
|
||||||
&:hover {
|
|
||||||
background: #f3f3f3;
|
|
||||||
}
|
|
||||||
&.selected {
|
|
||||||
.user-modal-icon {
|
|
||||||
color: $primary-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.disabled,
|
|
||||||
&.disabled:hover {
|
|
||||||
color: #c5c8ce;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
.user-modal-icon {
|
|
||||||
flex-shrink: 0;
|
|
||||||
font-size: 24px;
|
|
||||||
margin-right: 10px;
|
|
||||||
color: rgba($primary-desc-color, 0.7);
|
|
||||||
}
|
|
||||||
.user-modal-avatar {
|
|
||||||
flex: 1;
|
|
||||||
.avatar-name {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.user-modal-userid {
|
|
||||||
flex-shrink: 0;
|
|
||||||
margin-left: 10px;
|
|
||||||
font-size: 12px;
|
|
||||||
color: #cccccc;
|
|
||||||
transition: margin 0.1s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.user-modal-multiple {
|
|
||||||
flex-shrink: 0;
|
|
||||||
position: sticky;
|
|
||||||
bottom: 0;
|
|
||||||
z-index: 9;
|
|
||||||
padding: 6px 16px 0;
|
|
||||||
background: #ffffff;
|
|
||||||
color: $primary-desc-color;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
.multiple-check {
|
|
||||||
margin-left: 4px;
|
|
||||||
}
|
|
||||||
.multiple-text {
|
|
||||||
flex: 1;
|
|
||||||
text-align: right;
|
|
||||||
line-height: 20px;
|
|
||||||
font-size: 12px;
|
|
||||||
padding-left: 6px;
|
|
||||||
> em {
|
|
||||||
padding-left: 2px;
|
|
||||||
font-style: normal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ivu-modal-fullscreen {
|
|
||||||
.ivu-modal-content {
|
|
||||||
margin-top: 46px;
|
|
||||||
border-top-left-radius: 18px !important;
|
|
||||||
border-top-right-radius: 18px !important;
|
|
||||||
.ivu-modal-body {
|
|
||||||
bottom: 80px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 576px) {
|
.common-user-select-modal {
|
||||||
.common-user-select-modal {
|
.ivu-modal {
|
||||||
|
max-width: 90%;
|
||||||
|
|
||||||
|
.user-modal-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
.user-modal-close {
|
||||||
|
flex-shrink: 0;
|
||||||
|
color: $primary-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-modal-title {
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 16px;
|
||||||
|
padding: 0 16px;
|
||||||
|
color: $primary-title-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-modal-submit {
|
||||||
|
flex-shrink: 0;
|
||||||
|
color: $primary-color;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.submit-loading {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.ivu-modal-body {
|
.ivu-modal-body {
|
||||||
|
padding: 0 24px !important;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.user-modal-search {
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.search-selected {
|
||||||
|
flex: none;
|
||||||
|
height: auto;
|
||||||
|
flex-shrink: 0;
|
||||||
|
max-width: 60%;
|
||||||
|
margin-right: 12px;
|
||||||
|
|
||||||
|
ul {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
> li {
|
||||||
|
list-style: none;
|
||||||
|
margin-right: 6px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-avatar,
|
||||||
|
.icon-avatar {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 50%;
|
||||||
|
font-size: 20px;
|
||||||
|
background-color: #61B2F9;
|
||||||
|
color: #ffffff;
|
||||||
|
|
||||||
|
&.department {
|
||||||
|
background-color: #5BC7B0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.project {
|
||||||
|
background-color: #6E99EB;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.task {
|
||||||
|
background-color: #9B96DF;
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input {
|
||||||
|
.ivu-input {
|
||||||
|
height: 36px;
|
||||||
|
border-color: #f4f5f7;
|
||||||
|
background-color: #f4f5f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-pre {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.common-loading {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-modal-switch {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 12px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #F4F5F7;
|
||||||
|
|
||||||
|
> li {
|
||||||
|
flex: 1;
|
||||||
|
list-style: none;
|
||||||
|
color: $primary-text-color;
|
||||||
|
border-radius: 2px;
|
||||||
|
margin: 2px;
|
||||||
|
padding: 4px;
|
||||||
|
height: 28px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
font-weight: 500;
|
||||||
|
color: $primary-title-color;
|
||||||
|
background: #ffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.user-modal-list {
|
.user-modal-list {
|
||||||
max-height: none;
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
max-height: 400px;
|
||||||
|
|
||||||
|
ul {
|
||||||
|
padding: 16px 0;
|
||||||
|
|
||||||
|
&.user-modal-project {
|
||||||
|
> li {
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
.user-modal-avatar {
|
||||||
|
.project-name {
|
||||||
|
&:before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> li {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 16px 0 0;
|
||||||
|
height: 46px;
|
||||||
|
box-sizing: content-box;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
.user-modal-icon {
|
||||||
|
color: $primary-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-modal-avatar {
|
||||||
|
.project-name {
|
||||||
|
.subtitle {
|
||||||
|
> em.all {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.somed {
|
||||||
|
.user-modal-icon {
|
||||||
|
color: $primary-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-modal-avatar {
|
||||||
|
.project-name {
|
||||||
|
.subtitle {
|
||||||
|
> em.some {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.disabled,
|
||||||
|
&.disabled:hover {
|
||||||
|
color: #c5c8ce;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-modal-icon {
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-size: 22px;
|
||||||
|
margin-right: 10px;
|
||||||
|
color: rgba($primary-desc-color, 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-modal-all {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-modal-avatar {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.img-avatar,
|
||||||
|
.icon-avatar {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 50%;
|
||||||
|
font-size: 26px;
|
||||||
|
background-color: #61B2F9;
|
||||||
|
color: #ffffff;
|
||||||
|
|
||||||
|
&.department {
|
||||||
|
background-color: #5BC7B0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.project {
|
||||||
|
background-color: #6E99EB;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.task {
|
||||||
|
background-color: #9B96DF;
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-name,
|
||||||
|
.project-name {
|
||||||
|
flex: 1;
|
||||||
|
width: 0;
|
||||||
|
margin-left: 12px;
|
||||||
|
|
||||||
|
> span {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-name {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-name {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: -9px;
|
||||||
|
height: 1px;
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
padding-top: 2px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: $primary-desc-color;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
> em {
|
||||||
|
display: none;
|
||||||
|
font-style: normal;
|
||||||
|
padding-left: 4px;
|
||||||
|
color: $primary-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-modal-empty {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 36px 36px 20px;
|
||||||
|
min-height: 200px;
|
||||||
|
|
||||||
|
.empty-icon {
|
||||||
|
background-color: #f4f5f7;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 50%;
|
||||||
|
|
||||||
|
.ivu-icon {
|
||||||
|
color: #d1d8dd;
|
||||||
|
font-size: 46px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-text {
|
||||||
|
margin-top: 16px;
|
||||||
|
color: #bec6cc;
|
||||||
|
background-color: #f4f5f7;
|
||||||
|
padding: 4px 15px;
|
||||||
|
border-radius: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ivu-modal-footer {
|
||||||
|
border-top: 1px solid #f2f2f2 !important;
|
||||||
|
padding: 12px 0 !important;
|
||||||
|
margin: 0 24px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.ivu-modal-fullscreen {
|
||||||
|
max-width: none;
|
||||||
|
|
||||||
|
.ivu-modal-content {
|
||||||
|
margin-top: 46px;
|
||||||
|
border-top-left-radius: 18px !important;
|
||||||
|
border-top-right-radius: 18px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ivu-modal-header {
|
||||||
|
border-bottom: 1px solid #f2f2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ivu-modal-body {
|
||||||
|
top: 60px;
|
||||||
|
|
||||||
|
.user-modal-search {
|
||||||
|
padding-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-modal-list {
|
||||||
|
max-height: none;
|
||||||
|
|
||||||
|
ul {
|
||||||
|
> li {
|
||||||
|
&:last-child {
|
||||||
|
padding-bottom: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
87
resources/assets/sass/dark.scss
vendored
87
resources/assets/sass/dark.scss
vendored
@ -53,6 +53,7 @@ body.dark-mode-reverse {
|
|||||||
.overlay-close {
|
.overlay-close {
|
||||||
> a {
|
> a {
|
||||||
color: #323232;
|
color: #323232;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
@ -69,6 +70,7 @@ body.dark-mode-reverse {
|
|||||||
background-color: #000;
|
background-color: #000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.teditor-loadedstyle {
|
.teditor-loadedstyle {
|
||||||
.tox-sidebar-wrap {
|
.tox-sidebar-wrap {
|
||||||
box-shadow: none
|
box-shadow: none
|
||||||
@ -96,6 +98,7 @@ body.dark-mode-reverse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.project-column {
|
.project-column {
|
||||||
> ul {
|
> ul {
|
||||||
> li {
|
> li {
|
||||||
@ -107,6 +110,7 @@ body.dark-mode-reverse {
|
|||||||
color: #ed4014;
|
color: #ed4014;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.today {
|
&.today {
|
||||||
color: #ff9900;
|
color: #ff9900;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
@ -118,6 +122,7 @@ body.dark-mode-reverse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.project-table {
|
.project-table {
|
||||||
.project-table-body {
|
.project-table-body {
|
||||||
.task-row {
|
.task-row {
|
||||||
@ -128,6 +133,7 @@ body.dark-mode-reverse {
|
|||||||
color: #ed4014;
|
color: #ed4014;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.today {
|
&.today {
|
||||||
color: #ff9900;
|
color: #ff9900;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
@ -149,6 +155,7 @@ body.dark-mode-reverse {
|
|||||||
color: #1c1917;
|
color: #1c1917;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog-title {
|
.dialog-title {
|
||||||
.main-title {
|
.main-title {
|
||||||
> h2 {
|
> h2 {
|
||||||
@ -159,22 +166,26 @@ body.dark-mode-reverse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog-scroller {
|
.dialog-scroller {
|
||||||
.dialog-item {
|
.dialog-item {
|
||||||
.dialog-view {
|
.dialog-view {
|
||||||
.dialog-head {
|
.dialog-head {
|
||||||
background-color: #e1e1e1;
|
background-color: #e1e1e1;
|
||||||
|
|
||||||
.dialog-reply {
|
.dialog-reply {
|
||||||
.reply-desc {
|
.reply-desc {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog-content {
|
.dialog-content {
|
||||||
.content-text,
|
.content-text,
|
||||||
.content-record,
|
.content-record,
|
||||||
.content-meeting {
|
.content-meeting {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.open-approve-details {
|
.open-approve-details {
|
||||||
.cause {
|
.cause {
|
||||||
border-bottom: 1px solid #7f7f7f;
|
border-bottom: 1px solid #7f7f7f;
|
||||||
@ -182,9 +193,11 @@ body.dark-mode-reverse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog-emoji {
|
.dialog-emoji {
|
||||||
> li {
|
> li {
|
||||||
background-color: rgba(#f3f3f3, 0.5);
|
background-color: rgba(#f3f3f3, 0.5);
|
||||||
|
|
||||||
&.hasme {
|
&.hasme {
|
||||||
background-color: #f3f3f3;
|
background-color: #f3f3f3;
|
||||||
}
|
}
|
||||||
@ -192,18 +205,22 @@ body.dark-mode-reverse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.self {
|
&.self {
|
||||||
.dialog-view {
|
.dialog-view {
|
||||||
.dialog-head {
|
.dialog-head {
|
||||||
background-color: $primary-color;
|
background-color: $primary-color;
|
||||||
|
|
||||||
.dialog-content {
|
.dialog-content {
|
||||||
.content-text {
|
.content-text {
|
||||||
> pre {
|
> pre {
|
||||||
a {
|
a {
|
||||||
color: #0027a1;
|
color: #0027a1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mention {
|
.mention {
|
||||||
color: #000000;
|
color: #000000;
|
||||||
|
|
||||||
&.file,
|
&.file,
|
||||||
&[data-denotation-char="~"] {
|
&[data-denotation-char="~"] {
|
||||||
color: #0027a1 !important;
|
color: #0027a1 !important;
|
||||||
@ -212,16 +229,20 @@ body.dark-mode-reverse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog-emoji {
|
.dialog-emoji {
|
||||||
> li {
|
> li {
|
||||||
background-color: rgba(#b2ff93, 0.5);
|
background-color: rgba(#b2ff93, 0.5);
|
||||||
|
|
||||||
&.hasme {
|
&.hasme {
|
||||||
background-color: #b2ff93;
|
background-color: #b2ff93;
|
||||||
}
|
}
|
||||||
|
|
||||||
.emoji-users {
|
.emoji-users {
|
||||||
&:before {
|
&:before {
|
||||||
background-color: rgba(#000000, 0.7);
|
background-color: rgba(#000000, 0.7);
|
||||||
}
|
}
|
||||||
|
|
||||||
> ul {
|
> ul {
|
||||||
> li {
|
> li {
|
||||||
color: #000000;
|
color: #000000;
|
||||||
@ -253,73 +274,95 @@ body.dark-mode-reverse {
|
|||||||
&:before {
|
&:before {
|
||||||
background-image: url("../images/file/dark/other.svg");
|
background-image: url("../images/file/dark/other.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
&.archive:before {
|
&.archive:before {
|
||||||
background-image: url("../images/file/dark/archive.svg");
|
background-image: url("../images/file/dark/archive.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
&.cad:before {
|
&.cad:before {
|
||||||
background-image: url("../images/file/dark/cad.svg");
|
background-image: url("../images/file/dark/cad.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
&.code:before {
|
&.code:before {
|
||||||
background-image: url("../images/file/dark/code.svg");
|
background-image: url("../images/file/dark/code.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
&.document:before {
|
&.document:before {
|
||||||
background-image: url("../images/file/dark/document.svg");
|
background-image: url("../images/file/dark/document.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
&.drawio:before {
|
&.drawio:before {
|
||||||
background-image: url("../images/file/dark/drawio.svg");
|
background-image: url("../images/file/dark/drawio.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
&.excel:before {
|
&.excel:before {
|
||||||
background-image: url("../images/file/dark/excel.svg");
|
background-image: url("../images/file/dark/excel.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
&.flow:before {
|
&.flow:before {
|
||||||
background-image: url("../images/file/dark/flow.svg");
|
background-image: url("../images/file/dark/flow.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
&.folder {
|
&.folder {
|
||||||
&:before {
|
&:before {
|
||||||
background-image: url("../images/file/dark/folder.svg");
|
background-image: url("../images/file/dark/folder.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
&.share {
|
&.share {
|
||||||
&:before {
|
&:before {
|
||||||
background-image: url("../images/file/dark/folder-share.svg");
|
background-image: url("../images/file/dark/folder-share.svg");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.media:before {
|
&.media:before {
|
||||||
background-image: url("../images/file/dark/media.svg");
|
background-image: url("../images/file/dark/media.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
&.mind:before {
|
&.mind:before {
|
||||||
background-image: url("../images/file/dark/mind.svg");
|
background-image: url("../images/file/dark/mind.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
&.ofd:before {
|
&.ofd:before {
|
||||||
background-image: url("../images/file/dark/ofd.svg");
|
background-image: url("../images/file/dark/ofd.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
&.pdf:before {
|
&.pdf:before {
|
||||||
background-image: url("../images/file/dark/pdf.svg");
|
background-image: url("../images/file/dark/pdf.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
&.picture:before {
|
&.picture:before {
|
||||||
background-image: url("../images/file/dark/picture.svg");
|
background-image: url("../images/file/dark/picture.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
&.ppt:before {
|
&.ppt:before {
|
||||||
background-image: url("../images/file/dark/ppt.svg");
|
background-image: url("../images/file/dark/ppt.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
&.sheet:before {
|
&.sheet:before {
|
||||||
background-image: url("../images/file/dark/sheet.svg");
|
background-image: url("../images/file/dark/sheet.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
&.tif:before {
|
&.tif:before {
|
||||||
background-image: url("../images/file/dark/tif.svg");
|
background-image: url("../images/file/dark/tif.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
&.txt:before {
|
&.txt:before {
|
||||||
background-image: url("../images/file/dark/txt.svg");
|
background-image: url("../images/file/dark/txt.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
&.updir:before {
|
&.updir:before {
|
||||||
background-image: url("../images/file/dark/updir.svg");
|
background-image: url("../images/file/dark/updir.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
&.upload:before {
|
&.upload:before {
|
||||||
background-image: url("../images/file/dark/upload.svg");
|
background-image: url("../images/file/dark/upload.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
&.word:before {
|
&.word:before {
|
||||||
background-image: url("../images/file/dark/word.svg");
|
background-image: url("../images/file/dark/word.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
&.wps:before {
|
&.wps:before {
|
||||||
background-image: url("../images/file/dark/wps.svg");
|
background-image: url("../images/file/dark/wps.svg");
|
||||||
}
|
}
|
||||||
@ -353,10 +396,12 @@ body.dark-mode-reverse {
|
|||||||
color: rgba(0, 0, 0, 0.6);
|
color: rgba(0, 0, 0, 0.6);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.block-data {
|
.block-data {
|
||||||
.block-num {
|
.block-num {
|
||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.taskfont {
|
.taskfont {
|
||||||
color: rgba(0, 0, 0, 0.7);
|
color: rgba(0, 0, 0, 0.7);
|
||||||
}
|
}
|
||||||
@ -376,6 +421,7 @@ body.dark-mode-reverse {
|
|||||||
.icon-avatar {
|
.icon-avatar {
|
||||||
color: #1c1917;
|
color: #1c1917;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog-box {
|
.dialog-box {
|
||||||
.dialog-text {
|
.dialog-text {
|
||||||
color: #555;
|
color: #555;
|
||||||
@ -402,6 +448,7 @@ body.dark-mode-reverse {
|
|||||||
.page-index {
|
.page-index {
|
||||||
.page-warp {
|
.page-warp {
|
||||||
background-color: #efefef;
|
background-color: #efefef;
|
||||||
|
|
||||||
.page-header {
|
.page-header {
|
||||||
.header-nav {
|
.header-nav {
|
||||||
.header-nav-box {
|
.header-nav-box {
|
||||||
@ -409,28 +456,33 @@ body.dark-mode-reverse {
|
|||||||
.header-right-uplog {
|
.header-right-uplog {
|
||||||
color: #000000;
|
color: #000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-right-1 {
|
.header-right-1 {
|
||||||
.header-right-1-dropdown {
|
.header-right-1-dropdown {
|
||||||
color: #000000;
|
color: #000000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-right-2 {
|
.header-right-2 {
|
||||||
.header-right-2-dropdown {
|
.header-right-2-dropdown {
|
||||||
color: #000000;
|
color: #000000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-right-3 {
|
.header-right-3 {
|
||||||
color: #000000;
|
color: #000000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-content {
|
.header-content {
|
||||||
.header-title, .header-tips {
|
.header-title, .header-tips {
|
||||||
color: #000000;
|
color: #000000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.page-header-bottom{
|
|
||||||
|
.page-header-bottom {
|
||||||
background-color: #efefef;
|
background-color: #efefef;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -441,16 +493,19 @@ body.dark-mode-reverse {
|
|||||||
.ql-container {
|
.ql-container {
|
||||||
.ql-editor {
|
.ql-editor {
|
||||||
color: #ccc;
|
color: #ccc;
|
||||||
|
|
||||||
&.ql-blank {
|
&.ql-blank {
|
||||||
&::before {
|
&::before {
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mention {
|
.mention {
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-toolbar {
|
.chat-toolbar {
|
||||||
> li {
|
> li {
|
||||||
&.chat-send {
|
&.chat-send {
|
||||||
@ -462,4 +517,34 @@ body.dark-mode-reverse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.common-user-select-modal {
|
||||||
|
.ivu-modal {
|
||||||
|
.ivu-modal-body {
|
||||||
|
.user-modal-search {
|
||||||
|
.search-selected {
|
||||||
|
ul {
|
||||||
|
> li {
|
||||||
|
.icon-avatar {
|
||||||
|
color: #1c1917;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-modal-list {
|
||||||
|
ul {
|
||||||
|
> li {
|
||||||
|
.user-modal-avatar {
|
||||||
|
.icon-avatar {
|
||||||
|
color: #1c1917;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
Subproject commit 71ad67db7859b6e4488311a8b03d9f4851627166
|
Subproject commit 777a8d12477bda3e34ec6c9290ea5dfd84b8fd81
|
||||||
Loading…
x
Reference in New Issue
Block a user