perf: 优化用户选择器

This commit is contained in:
kuaifan 2023-12-22 16:33:44 +08:00 committed by Pang
parent 7de575e236
commit d4ef140c8e
6 changed files with 340 additions and 360 deletions

View File

@ -19,20 +19,15 @@
<!-- 顶部 --> <!-- 顶部 -->
<template #header> <template #header>
<div v-if="isFullscreen" class="user-modal-header"> <div v-if="isFullscreen" class="user-modal-header">
<div class="user-modal-close" @click="[ !multipleChoice && showMultiple ? showMultiple=false : showModal=false]"> <div class="user-modal-close" @click="showModal=false">{{$L('关闭')}}</div>
{{ !multipleChoice && showMultiple ? $L('取消') : $L('关闭') }}
</div>
<div class="user-modal-title"><span>{{localTitle}}</span></div> <div class="user-modal-title"><span>{{localTitle}}</span></div>
<div v-if="showMultiple" class="user-modal-submit" @click="onSubmit(1)"> <div class="user-modal-submit" @click="onSubmit">
<div v-if="submittIng > 0" class="submit-loading"><Loading /></div> <div v-if="submittIng > 0" class="submit-loading"><Loading /></div>
{{$L('确定')}} {{$L('确定')}}
<template v-if="selects.length > 0"> <template v-if="selects.length > 0">
({{selects.length}}<span v-if="multipleMax">/{{multipleMax}}</span>) ({{selects.length}}<span v-if="multipleMax">/{{multipleMax}}</span>)
</template> </template>
</div> </div>
<div v-else-if="!forcedRadio" class="user-modal-submit" @click="showMultiple = true">
{{$L('多选')}}
</div>
</div> </div>
<div v-else class="ivu-modal-header-inner">{{localTitle}}</div> <div v-else class="ivu-modal-header-inner">{{localTitle}}</div>
</template> </template>
@ -42,7 +37,7 @@
<!-- 搜索 --> <!-- 搜索 -->
<div class="user-modal-search"> <div class="user-modal-search">
<Scrollbar ref="selected" class="search-selected" v-if="showMultiple && selects.length > 0" enable-x :enable-y="false"> <Scrollbar ref="selected" class="search-selected" v-if="selects.length > 0" enable-x :enable-y="false">
<ul> <ul>
<li v-for="item in formatSelect(selects)" :data-id="item.userid" @click.stop="onRemoveItem(item.userid)"> <li v-for="item in formatSelect(selects)" :data-id="item.userid" @click.stop="onRemoveItem(item.userid)">
<template v-if="item.type=='group'"> <template v-if="item.type=='group'">
@ -69,7 +64,6 @@
<ul v-if="isWhole" class="user-modal-switch"> <ul v-if="isWhole" class="user-modal-switch">
<li <li
v-for="item in switchItems" :key="item.key" v-for="item in switchItems" :key="item.key"
v-if="!(forcedRadio && !showMultiple && item.key == 'project')"
:class="{active:switchActive===item.key}" :class="{active:switchActive===item.key}"
@click="switchActive=item.key">{{ $L(item.label) }}</li> @click="switchActive=item.key">{{ $L(item.label) }}</li>
</ul> </ul>
@ -82,19 +76,15 @@
v-for="item in lists" v-for="item in lists"
:class="selectClass(item.userid_list)" :class="selectClass(item.userid_list)"
@click="onSelectProject(item.userid_list)"> @click="onSelectProject(item.userid_list)">
<template v-if="showMultiple">
<Icon class="user-modal-icon" :type="selectIcon(item.userid_list)" /> <Icon class="user-modal-icon" :type="selectIcon(item.userid_list)" />
</template>
<div class="user-modal-avatar"> <div class="user-modal-avatar">
<i class="taskfont icon-avatar">&#xe6f9;</i> <i class="taskfont icon-avatar">&#xe6f9;</i>
<div class="project-name"> <div class="project-name">
<div class="label">{{item.name}}</div> <div class="label">{{item.name}}</div>
<div class="subtitle"> <div class="subtitle">
{{item.userid_list.length}} {{$L('项目成员')}} {{item.userid_list.length}} {{$L('项目成员')}}
<template v-if="showMultiple">
<em class="all">{{$L('已全选')}}</em> <em class="all">{{$L('已全选')}}</em>
<em class="some">{{$L('已选部分')}}</em> <em class="some">{{$L('已选部分')}}</em>
</template>
</div> </div>
</div> </div>
</div> </div>
@ -103,7 +93,7 @@
<!-- 会员会话 --> <!-- 会员会话 -->
<ul v-else> <ul v-else>
<li <li
v-if="showMultiple && showSelectAll" v-if="showSelectAll"
:class="selectClass('all')" :class="selectClass('all')"
@click="onSelectAll"> @click="onSelectAll">
<Icon class="user-modal-icon" :type="selectIcon('all')" /> <Icon class="user-modal-icon" :type="selectIcon('all')" />
@ -116,10 +106,8 @@
disabled: isUncancelable(item.userid) || isDisabled(item.userid) disabled: isUncancelable(item.userid) || isDisabled(item.userid)
}" }"
@click="onSelectItem(item)"> @click="onSelectItem(item)">
<template v-if="showMultiple">
<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" />
</template>
<div v-if="item.type=='group'" class="user-modal-avatar"> <div v-if="item.type=='group'" class="user-modal-avatar">
<EAvatar v-if="item.avatar" class="img-avatar" :src="item.avatar" :size="40"></EAvatar> <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">&#xe75c;</i> <i v-else-if="item.group_type=='department'" class="taskfont icon-avatar department">&#xe75c;</i>
@ -146,57 +134,12 @@
<!-- 底部 --> <!-- 底部 -->
<template #footer> <template #footer>
<Button v-if="!forcedRadio && !multipleChoice && showMultiple" @click="showMultiple = false"> <Button type="primary" :loading="submittIng > 0" @click="onSubmit">
{{$L('取消')}}
</Button>
<Button v-if="!forcedRadio && showMultiple" type="primary" :loading="submittIng > 0" @click="onSubmit(1)">
{{$L('确定')}} {{$L('确定')}}
<template v-if="selects.length > 0"> <template v-if="selects.length > 0">
({{selects.length}}<span v-if="multipleMax">/{{multipleMax}}</span>) ({{selects.length}}<span v-if="multipleMax">/{{multipleMax}}</span>)
</template> </template>
</Button> </Button>
<Button v-else-if="!forcedRadio" type="primary" @click="showMultiple = true">
{{$L('多选')}}
</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">
<div v-if="item.type=='group'" class="user-modal-avatar">
<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">&#xe75c;</i>
<i v-else-if="item.group_type=='project'" class="taskfont icon-avatar project">&#xe6f9;</i>
<i v-else-if="item.group_type=='task'" class="taskfont icon-avatar task">&#xe6f4;</i>
<i v-else-if="item.group_type=='okr'" class="taskfont icon-avatar task">&#xe6f4;</i>
<Icon v-else class="icon-avatar" type="ios-people" />
<div v-if="selects?.length == 1" class="avatar-name">
<span>{{item.name}}</span>
</div>
</div>
<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> </template>
</Modal> </Modal>
</div> </div>
@ -311,40 +254,14 @@ export default {
default: false default: false
}, },
// //
disable: { disabled: {
type: Boolean, type: Boolean,
default: false default: false
}, },
// //
submitBtnTwoText: { onlyGroup: {
type: String,
default: ''
},
//
twiceAffirm: {
type: Boolean,
default: false
},
//
twiceAffirmTitle: {
type: String,
default: ''
},
//
multipleChoice: {
type: Boolean,
default: true
},
//
forcedRadio: {
type: Boolean,
default: false
},
//
group: {
type: Boolean, type: Boolean,
default: false default: false
}, },
@ -360,9 +277,11 @@ export default {
{key: 'project', label: '项目成员'}, {key: 'project', label: '项目成员'},
], ],
switchActive: 'recent', switchActive: 'recent',
loadIng: 0,
waitIng: 0, loadIng: 0, //
submittIng: 0, waitIng: 0, //
submittIng: 0, //
values: [], values: [],
selects: [], selects: [],
@ -374,10 +293,7 @@ export default {
searchKey: null, searchKey: null,
searchCache: [], searchCache: [],
}
showAffirmModal: false,
showMultiple: true,
};
}, },
watch: { watch: {
value: { value: {
@ -395,7 +311,7 @@ export default {
isWhole: { isWhole: {
handler(value) { handler(value) {
if (value || this.group) { if (value || this.onlyGroup) {
this.switchActive = 'recent' this.switchActive = 'recent'
} else { } else {
this.switchActive = 'contact' this.switchActive = 'contact'
@ -407,14 +323,10 @@ export default {
showModal(value) { showModal(value) {
if (value) { if (value) {
this.searchBefore() this.searchBefore()
this.showMultiple = this.multipleChoice
if(this.forcedRadio){
this.showMultiple = false
}
} else { } else {
this.searchKey = "" this.searchKey = ""
} }
this.$emit("on-show-change", value, this.values) this.$emit("on-show-change", value)
}, },
searchKey() { searchKey() {
@ -434,8 +346,8 @@ export default {
return windowWidth < 576 return windowWidth < 576
}, },
isWhole({ projectId, noProjectId, dialogId }) { isWhole({projectId, noProjectId, dialogId, onlyGroup}) {
return projectId === 0 && noProjectId === 0 && dialogId === 0 && !this.group return projectId === 0 && noProjectId === 0 && dialogId === 0 && !onlyGroup
}, },
lists({switchActive, searchKey, recents, contacts, projects}) { lists({switchActive, searchKey, recents, contacts, projects}) {
@ -560,7 +472,7 @@ export default {
searchRecent() { searchRecent() {
this.recents = this.cacheDialogs.filter(dialog => { this.recents = this.cacheDialogs.filter(dialog => {
if(this.group && dialog.type != 'group'){ if (this.onlyGroup && dialog.type != 'group') {
return false return false
} }
if (dialog.name === undefined || dialog.dialog_delete === 1) { if (dialog.name === undefined || dialog.dialog_delete === 1) {
@ -667,7 +579,7 @@ export default {
}, },
}).then(({data}) => { }).then(({data}) => {
data = data.data.map(item => Object.assign(item, {type: 'project'})) data = data.data.map(item => Object.assign(item, {type: 'project'}))
this.projects = data; this.projects = data
// //
const index = this.searchCache.findIndex(item => item.key == key); 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()};
@ -687,7 +599,7 @@ export default {
}, },
onSelection() { onSelection() {
if (this.disable) { if (this.disabled) {
return return
} }
this.$nextTick(_ => { this.$nextTick(_ => {
@ -716,9 +628,6 @@ export default {
}, },
onSelectItem({userid}) { onSelectItem({userid}) {
if (!this.showMultiple) {
this.selects = []
}
if (this.selects.includes(userid)) { if (this.selects.includes(userid)) {
if (this.isUncancelable(userid)) { if (this.isUncancelable(userid)) {
return return
@ -735,18 +644,12 @@ export default {
this.selects.push(userid) this.selects.push(userid)
// //
this.$nextTick(() => { this.$nextTick(() => {
$A.scrollIntoViewIfNeeded(this.$refs.selected?.querySelector(`li[data-id="${userid}"]`)) $A.scrollIntoViewIfNeeded(this.$refs.selected.querySelector(`li[data-id="${userid}"]`))
}) })
} }
if(!this.showMultiple){
this.onSubmit(1)
}
}, },
onSelectProject(userid_list) { onSelectProject(userid_list) {
if (!this.showMultiple) {
this.selects = []
}
switch (this.selectIcon(userid_list)) { switch (this.selectIcon(userid_list)) {
case 'ios-checkmark-circle': case 'ios-checkmark-circle':
// //
@ -770,9 +673,6 @@ export default {
} }
break; break;
} }
if (!this.showMultiple) {
this.onSubmit(1)
}
}, },
onRemoveItem(userid) { onRemoveItem(userid) {
@ -782,36 +682,24 @@ export default {
this.selects = this.selects.filter(value => value != userid) this.selects = this.selects.filter(value => value != userid)
}, },
onSubmit(index) { onSubmit() {
if (this.submittIng > 0) { if (this.submittIng > 0) {
return 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)
//
if (index !=2 && this.twiceAffirm) {
if (this.values.length < 1) {
$A.messageError("请选择对话或成员")
return
}
this.showAffirmModal = true
return
}
//
this.$emit('input', this.values) this.$emit('input', this.values)
this.$emit('onSubmit', this.values) this.$emit('on-submit', this.values)
if (!this.beforeSubmit) { if (!this.beforeSubmit) {
this.showModal = false this.hide()
this.showAffirmModal = false
return return
} }
const before = this.beforeSubmit(); const before = this.beforeSubmit();
if (before && before.then) { if (before && before.then) {
this.submittIng++ this.submittIng++
before.then(() => { before.then(() => {
this.showModal = false this.hide()
this.showAffirmModal = false
}).catch(() => { }).catch(() => {
this.values = clone this.values = clone
this.$emit('input', this.values) this.$emit('input', this.values)
@ -819,10 +707,17 @@ export default {
this.submittIng-- this.submittIng--
}) })
} else { } else {
this.showModal = false this.hide()
this.showAffirmModal = false
} }
}, },
show() {
this.onSelection()
},
hide() {
this.showModal = false
},
} }
}; };
</script> </script>

View File

@ -189,16 +189,15 @@
</div> </div>
</Modal> </Modal>
<!-- 发起接龙 --> <!-- 发起群投票接龙 -->
<UserSelect <UserSelect
ref="wordChainAndVoteRef" ref="wordChainAndVoteRef"
v-model="sendData" v-model="sendData"
:multiple-max="50" :multiple-max="1"
:title="sendType == 'vote' ? $L('选择群组发起投票') : $L('选择群组发起接龙')" :title="sendType == 'vote' ? $L('选择群组发起投票') : $L('选择群组发起接龙')"
:before-submit="goWordChainAndVote" :before-submit="goWordChainAndVote"
:show-select-all="false" :show-select-all="false"
:forced-radio="true" :only-group="true"
:group="true"
show-dialog show-dialog
module/> module/>
@ -586,9 +585,10 @@ export default {
// //
goWordChainAndVote() { goWordChainAndVote() {
const dialog_id = Number(this.sendData[0].replace('d:', '')) const dialog_id = Number(this.sendData[0].replace('d:', ''))
const type = this.sendType == 'word-chain' ? 'dialogDroupWordChain' : 'dialogGroupVote'
if (this.windowPortrait) { if (this.windowPortrait) {
this.$store.dispatch("openDialog", dialog_id).then(() => { this.$store.dispatch("openDialog", dialog_id).then(() => {
this.$store.state[ this.sendType == 'word-chain' ?'dialogDroupWordChain' : 'dialogGroupVote'] = { this.$store.state[type] = {
type: 'create', type: 'create',
dialog_id: dialog_id dialog_id: dialog_id
} }
@ -596,7 +596,7 @@ export default {
} else { } else {
this.goForward({name: 'manage-messenger', params: {dialog_id: dialog_id}}); this.goForward({name: 'manage-messenger', params: {dialog_id: dialog_id}});
setTimeout(() => { setTimeout(() => {
this.$store.state[ this.sendType == 'word-chain' ?'dialogDroupWordChain' : 'dialogGroupVote'] = { this.$store.state[type] = {
type: 'create', type: 'create',
dialog_id: dialog_id dialog_id: dialog_id
} }

View File

@ -387,20 +387,44 @@
</div> </div>
</Modal> </Modal>
<!-- 转发 --> <!-- 转发选择 -->
<UserSelect <UserSelect
ref="forwardSelect" ref="forwardSelect"
v-model="forwardData"
:multiple-max="50" :multiple-max="50"
:title="$L('转发')" :title="$L('转发')"
:twice-affirm="true" :before-submit="onForwardBefore"
:twice-affirm-title="$L('转发给:')"
:before-submit="onForward"
:show-select-all="false" :show-select-all="false"
:multiple-choice="false"
show-dialog show-dialog
module> module/>
<template #twice-affirm-body-extend>
<!-- 转发确认 -->
<Modal
v-model="forwardhow"
:title="$L('转发给:')"
class-name="common-user-select-modal dialog-forward-message-modal"
:mask-closable="false"
width="420">
<div class="user-modal-search">
<Scrollbar class="search-selected" enable-x :enable-y="false">
<ul>
<li v-for="item in forwardData" :data-id="item.userid">
<div v-if="item.type=='group'" class="user-modal-avatar">
<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">&#xe75c;</i>
<i v-else-if="item.group_type=='project'" class="taskfont icon-avatar project">&#xe6f9;</i>
<i v-else-if="item.group_type=='task'" class="taskfont icon-avatar task">&#xe6f4;</i>
<i v-else-if="item.group_type=='okr'" class="taskfont icon-avatar task">&#xe6f4;</i>
<Icon v-else class="icon-avatar" type="ios-people" />
<div v-if="forwardData.length == 1" class="avatar-name">
<span>{{item.name}}</span>
</div>
</div>
<UserAvatar v-else :userid="item.userid" :size="32" :show-name="forwardData.length == 1" tooltip-disabled />
</li>
</ul>
</Scrollbar>
</div>
<div class="twice-affirm-body-extend">
<div class="dialog-wrapper-forward-body"> <div class="dialog-wrapper-forward-body">
<div class="dialog-wrapper "> <div class="dialog-wrapper ">
<div class="dialog-scroller"> <div class="dialog-scroller">
@ -408,18 +432,22 @@
</div> </div>
</div> </div>
<div class="leave-message"> <div class="leave-message">
<Input type="textarea" :autosize="{minRows: 1,maxRows: 3}" v-model="forwardLeaveMessage" :placeholder="$L('留言')" clearable /> <Input type="textarea" :autosize="{minRows: 1,maxRows: 3}" v-model="forwardMessage" :placeholder="$L('留言')" clearable />
</div> </div>
</div> </div>
</template> </div>
<template #twice-affirm-footer-extend> <template #footer>
<div class="dialog-wrapper-forward-footer" :class="{'selected': !forwardShowOriginal}" @click="forwardShowOriginal = !forwardShowOriginal"> <div class="dialog-wrapper-forward-footer" :class="{selected: !forwardSource}" @click="forwardSource = !forwardSource">
<Icon v-if="!forwardShowOriginal" class="user-modal-icon" type="ios-checkmark-circle" /> <Icon class="user-modal-icon" :type="forwardSource ? 'ios-radio-button-off' : 'ios-checkmark-circle'" />
<Icon v-else class="user-modal-icon" type="ios-radio-button-off" />
{{$L('不显示原发送者信息')}} {{$L('不显示原发送者信息')}}
</div> </div>
<Button type="primary" :loading="forwardLoad > 0" @click="onForwardAffirm">
{{$L('确定')}}
<template v-if="forwardData.length > 0">({{forwardData.length}})</template>
</Button>
</template> </template>
</UserSelect> </Modal>
<!-- 设置待办 --> <!-- 设置待办 -->
<Modal <Modal
@ -633,9 +661,11 @@ export default {
modifyData: {}, modifyData: {},
modifyLoad: 0, modifyLoad: 0,
forwardhow: false,
forwardData: [], forwardData: [],
forwardShowOriginal: true, forwardLoad: 0,
forwardLeaveMessage: '', forwardMessage: '',
forwardSource: true,
openId: 0, openId: 0,
dialogDrag: false, dialogDrag: false,
@ -2353,34 +2383,49 @@ export default {
} }
}, },
onForward() { onForwardBefore() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.forwardData = this.$refs.forwardSelect.formatSelect(this.$refs.forwardSelect.selects);
if (this.forwardData.length === 0) { if (this.forwardData.length === 0) {
$A.messageError("请选择转发对话或成员"); $A.messageError("请选择转发对话或成员");
} else {
this.forwardMessage = '';
this.forwardSource = true;
this.forwardhow = true;
}
reject(); reject();
})
},
onForwardAffirm() {
const selects = this.$refs.forwardSelect.selects;
if (selects.length === 0) {
$A.messageError("请选择转发对话或成员");
return return
} }
const dialogids = this.forwardData.filter(value => $A.leftExists(value, 'd:')).map(value => value.replace('d:', '')); const dialogids = selects.filter(value => $A.leftExists(value, 'd:')).map(value => value.replace('d:', ''));
const userids = this.forwardData.filter(value => !$A.leftExists(value, 'd:')); const userids = selects.filter(value => !$A.leftExists(value, 'd:'));
this.forwardLoad++;
this.$store.dispatch("call", { this.$store.dispatch("call", {
url: 'dialog/msg/forward', url: 'dialog/msg/forward',
data: { data: {
dialogids, dialogids,
userids, userids,
msg_id: this.operateItem.id, msg_id: this.operateItem.id,
show_source: this.forwardShowOriginal ? 1 : 0, show_source: this.forwardSource ? 1 : 0,
leave_message: this.forwardLeaveMessage leave_message: this.forwardMessage
} }
}).then(({data, msg}) => { }).then(({data, msg}) => {
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(); this.$refs.forwardSelect.hide()
this.forwardhow = false;
}).catch(({msg}) => { }).catch(({msg}) => {
$A.modalError(msg); $A.modalError(msg);
reject(); }).finally(_ => {
this.forwardLoad--;
}); });
})
}, },
onActivity(activity) { onActivity(activity) {
@ -2580,9 +2625,6 @@ export default {
break; break;
case "forward": case "forward":
this.forwardData = [];
this.forwardLeaveMessage = '';
this.forwardShowOriginal = true;
this.$refs.forwardSelect.onSelection() this.$refs.forwardSelect.onSelection()
break; break;

View File

@ -21,23 +21,23 @@
</div> </div>
<div class="task-move-row" :class="{'not-flex': windowPortrait}"> <div class="task-move-row" :class="{'not-flex': windowPortrait}">
<span class="label">{{$L('负责人')}}:</span> <span class="label">{{$L('负责人')}}:</span>
<UserSelect class="item-content user" <UserSelect
v-model="ownerUserids" v-model="ownerUserids"
class="item-content user"
:avatar-size="28" :avatar-size="28"
:project-id="task.project_id" :project-id="task.project_id"
:add-icon="false" :add-icon="false"
disable disabled/>
/>
</div> </div>
<div class="task-move-row" :class="{'not-flex': windowPortrait}"> <div class="task-move-row" :class="{'not-flex': windowPortrait}">
<span class="label">{{$L('协助人')}}:</span> <span class="label">{{$L('协助人')}}:</span>
<UserSelect class="item-content user" <UserSelect
class="item-content user"
v-model="assistUserids" v-model="assistUserids"
:avatar-size="28" :avatar-size="28"
:project-id="task.project_id" :project-id="task.project_id"
:add-icon="false" :add-icon="false"
disable disabled/>
/>
</div> </div>
</div> </div>
<div class="task-move-content-new"> <div class="task-move-content-new">
@ -66,8 +66,7 @@
:multiple-max="10" :multiple-max="10"
:avatar-size="28" :avatar-size="28"
:project-id="cascader[0]" :project-id="cascader[0]"
:add-icon="false" :add-icon="false"/>
/>
</div> </div>
</div> </div>
<div class="task-move-row" :class="{'not-flex': windowPortrait}"> <div class="task-move-row" :class="{'not-flex': windowPortrait}">
@ -79,8 +78,7 @@
:multiple-max="10" :multiple-max="10"
:avatar-size="28" :avatar-size="28"
:project-id="cascader[0]" :project-id="cascader[0]"
:add-icon="false" :add-icon="false"/>
/>
</div> </div>
</div> </div>
</div> </div>

View File

@ -172,21 +172,6 @@
} }
} }
} }
&.twice-affirm{
padding-bottom: 16px;
.search-selected{
max-width: 100%;
}
.user-modal-avatar{
display: flex;
align-items: center;
gap: 5px;
.avatar-name{
max-width: 90%;
}
}
}
} }
.user-modal-switch { .user-modal-switch {
@ -431,19 +416,12 @@
border-radius: 14px; border-radius: 14px;
} }
} }
.twice-affirm-body-extend{
margin: 0 24px;
}
} }
.ivu-modal-footer { .ivu-modal-footer {
border-top: 1px solid #f2f2f2 !important; border-top: 1px solid #f2f2f2 !important;
padding: 12px 0 !important; padding: 12px 0 !important;
margin: 0 24px !important; margin: 0 24px !important;
display: flex;
justify-content: flex-end;
gap: 20px;
} }
&.ivu-modal-fullscreen { &.ivu-modal-fullscreen {
@ -484,10 +462,4 @@
} }
} }
} }
&.twice-affirm-modal{
.ivu-modal {
max-width: 90%;
margin: 10px auto;
}
}
} }

View File

@ -447,8 +447,7 @@
.dialog-tag, .dialog-tag,
.dialog-todo, .dialog-todo,
.dialog-notice, .dialog-notice {
.dialog-new {
font-size: 12px; font-size: 12px;
max-width: 80%; max-width: 80%;
margin: 0 auto; margin: 0 auto;
@ -969,29 +968,36 @@
ul { ul {
list-style-type: none; list-style-type: none;
margin-top: 20px; margin-top: 20px;
li { li {
margin-top: 5px; margin-top: 5px;
.expand { .expand {
cursor: pointer; cursor: pointer;
color: #0bc037; color: #0bc037;
} }
.shrink { .shrink {
display: none; display: none;
} }
} }
li.participate { li.participate {
cursor: pointer; cursor: pointer;
margin-top: 10px; margin-top: 10px;
color: #0bc037; color: #0bc037;
> span { > span {
font-size: 12px; font-size: 12px;
margin-left: 2px; margin-left: 2px;
} }
} }
&.expand, li:nth-last-child(2) { &.expand, li:nth-last-child(2) {
.expand { .expand {
display: none; display: none;
} }
.shrink { .shrink {
display: block; display: block;
} }
@ -1002,10 +1008,12 @@
.content-word-vote { .content-word-vote {
min-width: 200px; min-width: 200px;
max-width: 260px; max-width: 260px;
.vote-msg-head { .vote-msg-head {
margin-bottom: 8px; margin-bottom: 8px;
color: #0bc037; color: #0bc037;
line-height: 18px; line-height: 18px;
span { span {
padding: 2px 4px; padding: 2px 4px;
border-radius: 3px; border-radius: 3px;
@ -1015,43 +1023,54 @@
color: #7076e4; color: #7076e4;
} }
} }
.ivu-checkbox-group, .ivu-radio-group { .ivu-checkbox-group, .ivu-radio-group {
margin-top: 10px; margin-top: 10px;
width: 100%; width: 100%;
.ivu-checkbox-wrapper, .ivu-radio-wrapper { .ivu-checkbox-wrapper, .ivu-radio-wrapper {
display: block; display: block;
width: 100%; width: 100%;
height: 34px; height: 34px;
line-height: 34px; line-height: 34px;
.ivu-checkbox-inner { .ivu-checkbox-inner {
border-radius: 100%; border-radius: 100%;
} }
} }
} }
.vote-result-body { .vote-result-body {
font-size: 12px; font-size: 12px;
margin-top: 14px; margin-top: 14px;
ul { ul {
list-style-type: none; list-style-type: none;
li { li {
margin-bottom: 14px; margin-bottom: 14px;
.vote-option-title { .vote-option-title {
margin-bottom: 3px; margin-bottom: 3px;
} }
.ivu-progress-inner { .ivu-progress-inner {
background-color: #e2e2e2; background-color: #e2e2e2;
} }
.avatar-row { .avatar-row {
gap: 2px; gap: 2px;
margin-top: 2px; margin-top: 2px;
display: flex; display: flex;
overflow: auto; overflow: auto;
padding-bottom: 4px; padding-bottom: 4px;
&::-webkit-scrollbar { &::-webkit-scrollbar {
background: none; background: none;
width: 6px; width: 6px;
height: 6px; height: 6px;
} }
&::-webkit-scrollbar-thumb { &::-webkit-scrollbar-thumb {
background: #d4d4d4; background: #d4d4d4;
-webkit-border-radius: 10px; -webkit-border-radius: 10px;
@ -1060,19 +1079,23 @@
} }
} }
} }
li:last-child { li:last-child {
margin-bottom: 10px; margin-bottom: 10px;
} }
} }
> span, .ticket-num span { > span, .ticket-num span {
margin-right: 10px; margin-right: 10px;
} }
} }
.btn-row { .btn-row {
display: flex; display: flex;
text-align: center; text-align: center;
padding: 10px 0 5px 0; padding: 10px 0 5px 0;
gap: 10px; gap: 10px;
.ivu-btn { .ivu-btn {
flex: 1; flex: 1;
} }
@ -1355,7 +1378,8 @@
.content-word-chain { .content-word-chain {
ul { ul {
li.participate, li .expand{ li.participate,
li .expand {
color: #23241f; color: #23241f;
} }
} }
@ -1430,9 +1454,6 @@
height: 14px; height: 14px;
font-size: 14px; font-size: 14px;
line-height: 14px; line-height: 14px;
&.down{
transform: rotate(-180deg);
}
} }
} }
} }
@ -1621,48 +1642,86 @@
} }
} }
.dialog-forward-message-modal {
.ivu-modal {
margin: 10px auto;
.ivu-modal-body {
.user-modal-search {
padding-bottom: 16px;
.search-selected {
max-width: 100%;
}
.user-modal-avatar {
display: flex;
align-items: center;
gap: 5px;
.avatar-name {
max-width: 90%;
}
}
}
.twice-affirm-body-extend {
margin: 0 24px;
.dialog-wrapper-forward-body { .dialog-wrapper-forward-body {
.dialog-wrapper { .dialog-wrapper {
position: relative !important; position: relative !important;
.dialog-scroller { .dialog-scroller {
padding: 0 !important; padding: 0 !important;
.dialog-item { .dialog-item {
.dialog-view { .dialog-view {
width: 100%; width: 100%;
max-width: 100% !important; max-width: 100% !important;
margin: 0 !important; margin: 0 !important;
.dialog-head { .dialog-head {
width: 100%; width: 100%;
border-radius: 8px !important; border-radius: 8px !important;
} }
.dialog-foot { .dialog-foot {
display: none !important; display: none !important;
} }
} }
.dialog-avatar { .dialog-avatar {
display: none; display: none;
} }
&.self { &.self {
.dialog-head { .dialog-head {
background-color: #F4F5F7; background-color: #F4F5F7;
.content-text { .content-text {
color: #303133 !important; color: #303133 !important;
.markdown-body { .markdown-body {
color: #303133 !important; color: #303133 !important;
} }
} }
.dialog-reply { .dialog-reply {
&:after { &:after {
background-color: rgba(132, 197, 106, 0.7); background-color: rgba(132, 197, 106, 0.7);
} }
.bot, .common-avatar { .bot, .common-avatar {
color: #84C56A !important; color: #84C56A !important;
} }
} }
.dialog-emoji { .dialog-emoji {
.avatar-name { .avatar-name {
color: #818181; color: #818181;
} }
> li.hasme { > li.hasme {
background-color: #e1e1e1; background-color: #e1e1e1;
} }
@ -1672,18 +1731,28 @@
} }
} }
} }
.leave-message { .leave-message {
padding-bottom: 16px; padding-bottom: 16px;
textarea { textarea {
background: #f7f7f7; background: #f7f7f7;
} }
} }
} }
}
}
.ivu-modal-footer {
display: flex;
justify-content: flex-end;
gap: 20px;
.dialog-wrapper-forward-footer { .dialog-wrapper-forward-footer {
display: flex; display: flex;
line-height: 34px; line-height: 34px;
cursor: pointer; cursor: pointer;
.user-modal-icon { .user-modal-icon {
flex-shrink: 0; flex-shrink: 0;
font-size: 22px; font-size: 22px;
@ -1691,12 +1760,16 @@
color: rgba($primary-desc-color, 0.7); color: rgba($primary-desc-color, 0.7);
margin-top: 6px; margin-top: 6px;
} }
&.selected { &.selected {
.user-modal-icon { .user-modal-icon {
color: $primary-color; color: $primary-color;
} }
} }
} }
}
}
}
.dialog-wrapper-read-poptip { .dialog-wrapper-read-poptip {
width: 360px; width: 360px;