perf: 任务操作菜单组件化
This commit is contained in:
parent
114b792300
commit
eb1f5f2632
@ -116,8 +116,7 @@
|
||||
<Icon type="md-trash" />{{$L('删除')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<EDropdownItem divided disabled>{{$L('颜色')}}</EDropdownItem>
|
||||
<EDropdownItem v-for="(c, k) in $store.state.columnColorList" :key="k" :command="c">
|
||||
<EDropdownItem v-for="(c, k) in $store.state.columnColorList" :key="k" :divided="k==0" :command="c">
|
||||
<div class="item">
|
||||
<i class="taskfont" :style="{color:c.color}" v-html="c.color == column.color ? '' : ''"></i>{{$L(c.name)}}
|
||||
</div>
|
||||
@ -154,42 +153,7 @@
|
||||
<div :class="['task-head', item.desc ? 'has-desc' : '']">
|
||||
<div class="task-title"><pre>{{item.name}}</pre></div>
|
||||
<div class="task-menu" @click.stop="">
|
||||
<div v-if="taskLoad[item.id] === true" class="loading"><Loading /></div>
|
||||
<EDropdown
|
||||
v-else
|
||||
trigger="click"
|
||||
size="small"
|
||||
@command="dropTask(item, $event)">
|
||||
<Icon type="ios-more" />
|
||||
<EDropdownMenu slot="dropdown" class="project-list-more-dropdown-menu">
|
||||
<EDropdownItem v-if="item.complete_at" command="uncomplete">
|
||||
<div class="item red">
|
||||
<Icon type="md-checkmark-circle-outline" />{{$L('标记未完成')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<EDropdownItem v-else command="complete">
|
||||
<div class="item">
|
||||
<Icon type="md-radio-button-off" />{{$L('完成')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<EDropdownItem command="archived">
|
||||
<div class="item">
|
||||
<Icon type="ios-filing" />{{$L('归档')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<EDropdownItem command="remove">
|
||||
<div class="item">
|
||||
<Icon type="md-trash" />{{$L('删除')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<EDropdownItem divided disabled>{{$L('背景色')}}</EDropdownItem>
|
||||
<EDropdownItem v-for="(c, k) in $store.state.taskColorList" :key="k" :command="c">
|
||||
<div class="item">
|
||||
<i class="taskfont" :style="{color:c.color||'#f9f9f9'}" v-html="c.color == item.color ? '' : ''"></i>{{$L(c.name)}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
</EDropdownMenu>
|
||||
</EDropdown>
|
||||
<TaskMenu :task="item" icon="ios-more"/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="item.desc" class="task-desc"><pre v-html="item.desc"></pre></div>
|
||||
@ -286,7 +250,7 @@
|
||||
<Col span="3"></Col>
|
||||
<Col span="3"></Col>
|
||||
</Row>
|
||||
<TaskRow v-if="projectParameter('showMy')" :list="transforTasks(myList)" open-key="my" @command="dropTask" @on-priority="addTaskOpen" fast-add-task/>
|
||||
<TaskRow v-if="projectParameter('showMy')" :list="transforTasks(myList)" open-key="my" @on-priority="addTaskOpen" fast-add-task/>
|
||||
</div>
|
||||
<!--协助的任务-->
|
||||
<div v-if="helpList.length" :class="['project-table-body', !projectParameter('showHelp') ? 'project-table-hide' : '']">
|
||||
@ -301,7 +265,7 @@
|
||||
<Col span="3"></Col>
|
||||
<Col span="3"></Col>
|
||||
</Row>
|
||||
<TaskRow v-if="projectParameter('showHelp')" :list="helpList" open-key="help" @command="dropTask" @on-priority="addTaskOpen"/>
|
||||
<TaskRow v-if="projectParameter('showHelp')" :list="helpList" open-key="help" @on-priority="addTaskOpen"/>
|
||||
</div>
|
||||
<!--未完成任务-->
|
||||
<div v-if="projectData.task_num > 0" :class="['project-table-body', !projectParameter('showUndone') ? 'project-table-hide' : '']">
|
||||
@ -316,7 +280,7 @@
|
||||
<Col span="3"></Col>
|
||||
<Col span="3"></Col>
|
||||
</Row>
|
||||
<TaskRow v-if="projectParameter('showUndone')" :list="unList" open-key="undone" @command="dropTask" @on-priority="addTaskOpen"/>
|
||||
<TaskRow v-if="projectParameter('showUndone')" :list="unList" open-key="undone" @on-priority="addTaskOpen"/>
|
||||
</div>
|
||||
<!--已完成任务-->
|
||||
<div v-if="projectData.task_num > 0" :class="['project-table-body', !projectParameter('showCompleted') ? 'project-table-hide' : '']">
|
||||
@ -331,7 +295,7 @@
|
||||
<Col span="3"></Col>
|
||||
<Col span="3">{{projectData.task_num > 0 && projectParameter('showCompleted') ? $L('完成时间') : ''}}</Col>
|
||||
</Row>
|
||||
<TaskRow v-if="projectParameter('showCompleted')" :list="completedList" open-key="completed" @command="dropTask" @on-priority="addTaskOpen" showCompleteAt/>
|
||||
<TaskRow v-if="projectParameter('showCompleted')" :list="completedList" open-key="completed" @on-priority="addTaskOpen" showCompleteAt/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -475,10 +439,12 @@ import TaskArchived from "./TaskArchived";
|
||||
import ProjectLog from "./ProjectLog";
|
||||
import DrawerOverlay from "../../../components/DrawerOverlay";
|
||||
import ProjectWorkflow from "./ProjectWorkflow";
|
||||
import TaskMenu from "./TaskMenu";
|
||||
|
||||
export default {
|
||||
name: "ProjectList",
|
||||
components: {
|
||||
TaskMenu,
|
||||
ProjectWorkflow,
|
||||
DrawerOverlay,
|
||||
ProjectLog, TaskArchived, TaskRow, Draggable, TaskAddSimple, UserInput, TaskAdd, TaskPriority},
|
||||
@ -489,9 +455,6 @@ export default {
|
||||
|
||||
columnLoad: {},
|
||||
columnTopShow: {},
|
||||
taskLoad: {},
|
||||
|
||||
tempShowTasks: [],
|
||||
|
||||
sortField: 'end_at',
|
||||
sortType: 'desc',
|
||||
@ -639,13 +602,13 @@ export default {
|
||||
},
|
||||
|
||||
myList() {
|
||||
const {projectId, cacheTasks, searchText, tempShowTasks, sortField, sortType} = this;
|
||||
const {projectId, cacheTasks, searchText, sortField, sortType} = this;
|
||||
const array = cacheTasks.filter((task) => {
|
||||
if (task.project_id != projectId) {
|
||||
return false;
|
||||
}
|
||||
if (!this.projectParameter('completedTask')) {
|
||||
if (task.complete_at && !tempShowTasks.find(({id}) => id == task.id)) {
|
||||
if (task.complete_at) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -672,13 +635,13 @@ export default {
|
||||
},
|
||||
|
||||
helpList() {
|
||||
const {projectId, cacheTasks, searchText, tempShowTasks, userId, sortField, sortType} = this;
|
||||
const {projectId, cacheTasks, searchText, userId, sortField, sortType} = this;
|
||||
const array = cacheTasks.filter((task) => {
|
||||
if (task.project_id != projectId || task.parent_id > 0) {
|
||||
return false;
|
||||
}
|
||||
if (!this.projectParameter('completedTask')) {
|
||||
if (task.complete_at && !tempShowTasks.find(({id}) => id == task.id)) {
|
||||
if (task.complete_at) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -767,9 +730,6 @@ export default {
|
||||
projectData() {
|
||||
this.sortData = this.getSort();
|
||||
},
|
||||
'$route'() {
|
||||
this.tempShowTasks = [];
|
||||
},
|
||||
searchShow(val) {
|
||||
if (val) {
|
||||
this.$nextTick(() => {
|
||||
@ -965,112 +925,6 @@ export default {
|
||||
});
|
||||
},
|
||||
|
||||
dropTask(task, command) {
|
||||
if ($A.isJson(command)) {
|
||||
if (command.name) {
|
||||
// 修改背景色
|
||||
this.updateTask(task, {
|
||||
color: command.color
|
||||
})
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ($A.leftExists(command, 'column::')) {
|
||||
// 修改列表
|
||||
this.updateTask(task, {
|
||||
column_id: $A.leftDelete(command, 'column::')
|
||||
})
|
||||
return;
|
||||
}
|
||||
if ($A.leftExists(command, 'priority::')) {
|
||||
// 修改优先级
|
||||
let data = this.taskPriority[parseInt($A.leftDelete(command, 'priority::'))];
|
||||
if (data) {
|
||||
this.updateTask(task, {
|
||||
p_level: data.priority,
|
||||
p_name: data.name,
|
||||
p_color: data.color,
|
||||
})
|
||||
}
|
||||
return;
|
||||
}
|
||||
switch (command) {
|
||||
case 'complete':
|
||||
if (task.complete_at) return;
|
||||
this.updateTask(task, {
|
||||
complete_at: $A.formatDate("Y-m-d H:i:s")
|
||||
}).then(() => {
|
||||
this.tempShowTasks.push(task)
|
||||
})
|
||||
break;
|
||||
|
||||
case 'uncomplete':
|
||||
if (!task.complete_at) return;
|
||||
this.updateTask(task, {
|
||||
complete_at: false
|
||||
}).then(() => {
|
||||
this.tempShowTasks = this.tempShowTasks.filter(({id}) => id != task.id)
|
||||
})
|
||||
break;
|
||||
|
||||
case 'archived':
|
||||
case 'remove':
|
||||
this.archivedOrRemoveTask(task, command);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
updateTask(task, updata) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.taskLoad[task.id] === true) {
|
||||
reject()
|
||||
return;
|
||||
}
|
||||
this.$set(this.taskLoad, task.id, true);
|
||||
//
|
||||
Object.keys(updata).forEach(key => this.$set(task, key, updata[key]));
|
||||
//
|
||||
this.$store.dispatch("taskUpdate", Object.assign(updata, {
|
||||
task_id: task.id,
|
||||
})).then(() => {
|
||||
this.$set(this.taskLoad, task.id, false);
|
||||
resolve()
|
||||
}).catch(({msg}) => {
|
||||
$A.modalError(msg);
|
||||
this.$set(this.taskLoad, task.id, false);
|
||||
this.$store.dispatch("getTaskOne", task.id);
|
||||
reject()
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
archivedOrRemoveTask(task, type) {
|
||||
let typeDispatch = type == 'remove' ? 'removeTask' : 'archivedTask';
|
||||
let typeName = type == 'remove' ? '删除' : '归档';
|
||||
let typeTask = task.parent_id > 0 ? '子任务' : '任务';
|
||||
$A.modalConfirm({
|
||||
title: typeName + typeTask,
|
||||
content: '你确定要' + typeName + typeTask + '【' + task.name + '】吗?',
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
if (this.taskLoad[task.id] === true) {
|
||||
this.$Modal.remove();
|
||||
return;
|
||||
}
|
||||
this.$set(this.taskLoad, task.id, true);
|
||||
this.$store.dispatch(typeDispatch, task.id).then(({msg}) => {
|
||||
$A.messageSuccess(msg);
|
||||
this.$Modal.remove();
|
||||
this.$set(this.taskLoad, task.id, false);
|
||||
}).catch(({msg}) => {
|
||||
$A.modalError(msg, 301);
|
||||
this.$Modal.remove();
|
||||
this.$set(this.taskLoad, task.id, false);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
onSort(field) {
|
||||
this.sortField = field;
|
||||
this.sortType = this.sortType == 'desc' ? 'asc' : 'desc';
|
||||
@ -1311,7 +1165,6 @@ export default {
|
||||
|
||||
toggleCompleted() {
|
||||
this.$store.dispatch('toggleProjectParameter', 'completedTask');
|
||||
this.tempShowTasks = [];
|
||||
},
|
||||
|
||||
expiresFormat(date) {
|
||||
|
@ -97,6 +97,13 @@ export default {
|
||||
title: this.$L('完成时间'),
|
||||
key: 'complete_at',
|
||||
width: 168,
|
||||
render: (h, {row}) => {
|
||||
return h('div', {
|
||||
style: {
|
||||
color: row.complete_at ? '' : '#f00'
|
||||
}
|
||||
}, row.complete_at || this.$L('未完成'));
|
||||
}
|
||||
},
|
||||
{
|
||||
title: this.$L('归档时间'),
|
||||
|
@ -2,40 +2,7 @@
|
||||
<!--子任务-->
|
||||
<li v-if="ready && taskDetail.parent_id > 0">
|
||||
<div class="subtask-icon">
|
||||
<div v-if="taskDetail.loading === true" class="loading"><Loading /></div>
|
||||
<EDropdown
|
||||
v-else
|
||||
trigger="click"
|
||||
placement="bottom"
|
||||
size="small"
|
||||
@command="dropTask">
|
||||
<div>
|
||||
<Icon v-if="taskDetail.complete_at" class="completed" type="md-checkmark-circle" />
|
||||
<Icon v-else type="md-radio-button-off" />
|
||||
</div>
|
||||
<EDropdownMenu slot="dropdown" class="project-list-more-dropdown-menu">
|
||||
<EDropdownItem v-if="taskDetail.complete_at" command="uncomplete">
|
||||
<div class="item red">
|
||||
<Icon type="md-checkmark-circle-outline" />{{$L('标记未完成')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<EDropdownItem v-else command="complete">
|
||||
<div class="item">
|
||||
<Icon type="md-radio-button-off" />{{$L('完成')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<EDropdownItem command="times">
|
||||
<div class="item">
|
||||
<Icon type="md-time" />{{$L('时间')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<EDropdownItem command="remove">
|
||||
<div class="item">
|
||||
<Icon type="md-trash" />{{$L('删除')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
</EDropdownMenu>
|
||||
</EDropdown>
|
||||
<TaskMenu :task="taskDetail" :load-status="taskDetail.loading === true"/>
|
||||
</div>
|
||||
<div class="subtask-name">
|
||||
<Input
|
||||
@ -58,9 +25,10 @@
|
||||
@on-clear="timeClear"
|
||||
@on-ok="timeOk"
|
||||
transfer>
|
||||
<div @click="openTime" :class="['time', taskDetail.today ? 'today' : '', taskDetail.overdue ? 'overdue' : '']">
|
||||
{{taskDetail.end_at && taskDetail.end_at != mainEndAt ? expiresFormat(taskDetail.end_at) : ' '}}
|
||||
<div v-if="taskDetail.end_at && taskDetail.end_at != mainEndAt" @click="openTime" :class="['time', taskDetail.today ? 'today' : '', taskDetail.overdue ? 'overdue' : '']">
|
||||
{{expiresFormat(taskDetail.end_at)}}
|
||||
</div>
|
||||
<Icon v-else class="clock" type="ios-clock-outline" @click="openTime" />
|
||||
</DatePicker>
|
||||
<Poptip
|
||||
ref="owner"
|
||||
@ -93,8 +61,7 @@
|
||||
<div v-else-if="ready" v-show="taskDetail.id > 0" :class="{'task-detail':true, 'open-dialog': hasOpenDialog, 'completed': taskDetail.complete_at}">
|
||||
<div class="task-info">
|
||||
<div class="head">
|
||||
<Icon v-if="taskDetail.complete_at" class="icon completed" type="md-checkmark-circle" @click="updateData('uncomplete')"/>
|
||||
<Icon v-else class="icon" type="md-radio-button-off" @click="updateData('complete')"/>
|
||||
<TaskMenu :task="taskDetail" class="icon" size="medium" :color-show="false" quick-completed/>
|
||||
<div class="nav">
|
||||
<p v-if="projectName"><span>{{projectName}}</span></p>
|
||||
<p v-if="columnName"><span>{{columnName}}</span></p>
|
||||
@ -130,34 +97,9 @@
|
||||
<ETooltip v-if="$Electron" :content="$L('新窗口打开')">
|
||||
<i class="taskfont open" @click="openNewWin"></i>
|
||||
</ETooltip>
|
||||
<EDropdown
|
||||
trigger="click"
|
||||
placement="bottom"
|
||||
@command="dropTask">
|
||||
<Icon class="menu" type="ios-more"/>
|
||||
<EDropdownMenu slot="dropdown">
|
||||
<EDropdownItem v-if="taskDetail.complete_at" command="uncomplete">
|
||||
<div class="item red">
|
||||
<Icon type="md-checkmark-circle-outline" />{{$L('标记未完成')}}
|
||||
<div class="menu">
|
||||
<TaskMenu :task="taskDetail" icon="ios-more" completed-icon="ios-more" size="medium" :color-show="false"/>
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<EDropdownItem v-else command="complete">
|
||||
<div class="item">
|
||||
<Icon type="md-radio-button-off" />{{$L('完成')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<EDropdownItem command="archived">
|
||||
<div class="item">
|
||||
<Icon type="ios-filing" />{{$L('归档')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<EDropdownItem command="remove">
|
||||
<div class="item">
|
||||
<Icon type="md-trash" />{{$L('删除')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
</EDropdownMenu>
|
||||
</EDropdown>
|
||||
</div>
|
||||
</div>
|
||||
<div class="scroller overlay-y">
|
||||
@ -428,10 +370,11 @@ import TaskUpload from "./TaskUpload";
|
||||
import DialogWrapper from "./DialogWrapper";
|
||||
import ProjectLog from "./ProjectLog";
|
||||
import {Store} from "le5le-store";
|
||||
import TaskMenu from "./TaskMenu";
|
||||
|
||||
export default {
|
||||
name: "TaskDetail",
|
||||
components: {ProjectLog, DialogWrapper, TaskUpload, UserInput, TaskPriority, TEditor},
|
||||
components: {TaskMenu, ProjectLog, DialogWrapper, TaskUpload, UserInput, TaskPriority, TEditor},
|
||||
props: {
|
||||
taskId: {
|
||||
type: Number,
|
||||
@ -794,34 +737,8 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
dropTask(command) {
|
||||
switch (command) {
|
||||
case 'complete':
|
||||
this.updateData('complete')
|
||||
break;
|
||||
case 'uncomplete':
|
||||
this.updateData('uncomplete')
|
||||
break;
|
||||
case 'times':
|
||||
this.openTime()
|
||||
break;
|
||||
case 'archived':
|
||||
case 'remove':
|
||||
this.archivedOrRemoveTask(command);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
updateData(action, params) {
|
||||
switch (action) {
|
||||
case 'complete':
|
||||
this.$set(this.taskDetail, 'complete_at', $A.formatDate());
|
||||
action = 'complete_at';
|
||||
break;
|
||||
case 'uncomplete':
|
||||
this.$set(this.taskDetail, 'complete_at', false);
|
||||
action = 'complete_at';
|
||||
break;
|
||||
case 'priority':
|
||||
this.$set(this.taskDetail, 'p_level', params.priority)
|
||||
this.$set(this.taskDetail, 'p_name', params.name)
|
||||
|
184
resources/assets/js/pages/manage/components/TaskMenu.vue
Normal file
184
resources/assets/js/pages/manage/components/TaskMenu.vue
Normal file
@ -0,0 +1,184 @@
|
||||
<template>
|
||||
<EDropdown
|
||||
trigger="click"
|
||||
:size="size"
|
||||
placement="bottom"
|
||||
@command="dropTask">
|
||||
<slot name="icon">
|
||||
<div class="task-menu-icon">
|
||||
<div v-if="loadIng" class="loading"><Loading /></div>
|
||||
<template v-else>
|
||||
<Icon v-if="task.complete_at" class="completed" :type="completedIcon" />
|
||||
<Icon v-else :type="icon" class="uncomplete"/>
|
||||
</template>
|
||||
</div>
|
||||
</slot>
|
||||
<EDropdownMenu slot="dropdown" class="task-menu-more-dropdown">
|
||||
<EDropdownItem v-if="task.complete_at" command="uncomplete">
|
||||
<div class="item red">
|
||||
<Icon type="md-checkmark-circle-outline" />{{$L('标记未完成')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<EDropdownItem v-else command="complete">
|
||||
<div class="item">
|
||||
<Icon type="md-radio-button-off" />{{$L('完成')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<EDropdownItem v-if="task.parent_id === 0" command="archived">
|
||||
<div class="item">
|
||||
<Icon type="ios-filing" />{{$L('归档')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<EDropdownItem command="remove">
|
||||
<div class="item">
|
||||
<Icon type="md-trash" />{{$L('删除')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<template v-if="task.parent_id === 0 && colorShow">
|
||||
<EDropdownItem v-for="(c, k) in $store.state.taskColorList" :key="k" :divided="k==0" :command="c">
|
||||
<div class="item">
|
||||
<i class="taskfont" :style="{color:c.color||'#f9f9f9'}" v-html="c.color == task.color ? '' : ''"></i>{{$L(c.name)}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
</template>
|
||||
</EDropdownMenu>
|
||||
</EDropdown>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState} from "vuex";
|
||||
|
||||
export default {
|
||||
name: "TaskMenu",
|
||||
props: {
|
||||
task: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
loadStatus: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
colorShow: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
quickCompleted: { // 如果没有任务流是快速完成
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: 'small'
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: 'md-radio-button-off'
|
||||
},
|
||||
completedIcon: {
|
||||
type: String,
|
||||
default: 'md-checkmark-circle'
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['taskLoading']),
|
||||
|
||||
loadIng() {
|
||||
if (this.loadStatus) {
|
||||
return true;
|
||||
}
|
||||
const load = this.taskLoading.find(({id}) => id == this.task.id);
|
||||
return load && load.num > 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
dropTask(command) {
|
||||
if ($A.isJson(command)) {
|
||||
if (command.name) {
|
||||
// 修改背景色
|
||||
this.updateTask({
|
||||
color: command.color
|
||||
})
|
||||
}
|
||||
return;
|
||||
}
|
||||
switch (command) {
|
||||
case 'complete':
|
||||
if (this.task.complete_at) return;
|
||||
this.updateTask({
|
||||
complete_at: $A.formatDate("Y-m-d H:i:s")
|
||||
}).then(() => {
|
||||
// 已完成
|
||||
})
|
||||
break;
|
||||
|
||||
case 'uncomplete':
|
||||
if (!this.task.complete_at) return;
|
||||
this.updateTask({
|
||||
complete_at: false
|
||||
}).then(() => {
|
||||
// 已未完成
|
||||
})
|
||||
break;
|
||||
|
||||
case 'archived':
|
||||
case 'remove':
|
||||
this.archivedOrRemoveTask(command);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
updateTask(updata) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.loadIng) {
|
||||
reject()
|
||||
return;
|
||||
}
|
||||
//
|
||||
Object.keys(updata).forEach(key => this.$set(this.task, key, updata[key]));
|
||||
//
|
||||
this.$store.dispatch("taskUpdate", Object.assign(updata, {
|
||||
task_id: this.task.id,
|
||||
})).then(() => {
|
||||
resolve()
|
||||
}).catch(({msg}) => {
|
||||
$A.modalError(msg);
|
||||
this.$store.dispatch("getTaskOne", this.task.id);
|
||||
reject()
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
archivedOrRemoveTask(type) {
|
||||
let typeDispatch = type == 'remove' ? 'removeTask' : 'archivedTask';
|
||||
let typeName = type == 'remove' ? '删除' : '归档';
|
||||
let typeTask = this.task.parent_id > 0 ? '子任务' : '任务';
|
||||
$A.modalConfirm({
|
||||
title: typeName + typeTask,
|
||||
content: '你确定要' + typeName + typeTask + '【' + this.task.name + '】吗?',
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
if (this.loadIng) {
|
||||
this.$Modal.remove();
|
||||
return;
|
||||
}
|
||||
this.$store.dispatch(typeDispatch, this.task.id).then(({msg}) => {
|
||||
$A.messageSuccess(msg);
|
||||
this.$Modal.remove();
|
||||
}).catch(({msg}) => {
|
||||
$A.modalError(msg, 301);
|
||||
this.$Modal.remove();
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
@ -9,47 +9,7 @@
|
||||
:class="['sub-icon', taskOpen[item.id] ? 'active' : '']"
|
||||
type="ios-arrow-forward"
|
||||
@click="getSublist(item)"/>
|
||||
<EDropdown
|
||||
trigger="click"
|
||||
size="small"
|
||||
placement="bottom"
|
||||
@command="dropTask(item, $event)">
|
||||
<div class="drop-icon">
|
||||
<Icon v-if="item.complete_at" class="completed" type="md-checkmark-circle" />
|
||||
<Icon v-else type="md-radio-button-off" />
|
||||
<div v-if="taskLoad[item.id] === true" class="loading"><Loading /></div>
|
||||
</div>
|
||||
<EDropdownMenu slot="dropdown" class="project-list-more-dropdown-menu">
|
||||
<EDropdownItem v-if="item.complete_at" command="uncomplete">
|
||||
<div class="item red">
|
||||
<Icon type="md-checkmark-circle-outline" />{{$L('标记未完成')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<EDropdownItem v-else command="complete">
|
||||
<div class="item">
|
||||
<Icon type="md-radio-button-off" />{{$L('完成')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<EDropdownItem v-if="item.parent_id === 0" command="archived">
|
||||
<div class="item">
|
||||
<Icon type="ios-filing" />{{$L('归档')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<EDropdownItem command="remove">
|
||||
<div class="item">
|
||||
<Icon type="md-trash" />{{$L('删除')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<template v-if="item.parent_id === 0">
|
||||
<EDropdownItem divided disabled>{{$L('背景色')}}</EDropdownItem>
|
||||
<EDropdownItem v-for="(c, k) in $store.state.taskColorList" :key="k" :command="c">
|
||||
<div class="item">
|
||||
<i class="taskfont" :style="{color:c.color||'#f9f9f9'}" v-html="c.color == item.color ? '' : ''"></i>{{$L(c.name)}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
</template>
|
||||
</EDropdownMenu>
|
||||
</EDropdown>
|
||||
<TaskMenu :ref="`taskMenu_${item.id}`" :task="item"/>
|
||||
<div class="item-title" @click="openTask(item)">
|
||||
<span v-if="item.sub_top === true">{{$L('子任务')}}</span>
|
||||
<span v-if="item.sub_my && item.sub_my.length > 0">+{{item.sub_my.length}}</span>
|
||||
@ -145,10 +105,11 @@ import TaskPriority from "./TaskPriority";
|
||||
import TaskAddSimple from "./TaskAddSimple";
|
||||
import {mapState} from "vuex";
|
||||
import {Store} from "le5le-store";
|
||||
import TaskMenu from "./TaskMenu";
|
||||
|
||||
export default {
|
||||
name: "TaskRow",
|
||||
components: {TaskAddSimple, TaskPriority},
|
||||
components: {TaskMenu, TaskAddSimple, TaskPriority},
|
||||
props: {
|
||||
list: {
|
||||
type: Array,
|
||||
@ -211,8 +172,31 @@ export default {
|
||||
return column ? column.name : '';
|
||||
},
|
||||
|
||||
|
||||
dropTask(task, command) {
|
||||
this.$emit("command", task, command)
|
||||
const el = this.$refs[`taskMenu_${task.id}`];
|
||||
if (!el) {
|
||||
return;
|
||||
}
|
||||
//
|
||||
if ($A.leftExists(command, 'column::')) {
|
||||
// 修改列表
|
||||
el[0].updateTask({
|
||||
column_id: $A.leftDelete(command, 'column::')
|
||||
})
|
||||
return;
|
||||
}
|
||||
if ($A.leftExists(command, 'priority::')) {
|
||||
// 修改优先级
|
||||
let data = this.taskPriority[parseInt($A.leftDelete(command, 'priority::'))];
|
||||
if (data) {
|
||||
el[0].updateTask({
|
||||
p_level: data.priority,
|
||||
p_name: data.name,
|
||||
p_color: data.color,
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onPriority(data) {
|
||||
|
@ -40,45 +40,11 @@
|
||||
v-if="item.p_name"
|
||||
class="priority-color"
|
||||
:style="{backgroundColor:item.p_color}"></em>
|
||||
<EDropdown
|
||||
trigger="click"
|
||||
size="small"
|
||||
placement="bottom"
|
||||
@command="dropTask(item, $event)">
|
||||
<div class="drop-icon" @click.stop="">
|
||||
<TaskMenu :task="item">
|
||||
<div slot="icon" class="drop-icon" @click.stop="">
|
||||
<i class="taskfont" v-html="item.complete_at ? '' : ''"></i>
|
||||
</div>
|
||||
<EDropdownMenu slot="dropdown" class="project-list-more-dropdown-menu">
|
||||
<EDropdownItem v-if="item.complete_at" command="uncomplete">
|
||||
<div class="item red">
|
||||
<Icon type="md-checkmark-circle-outline" />{{$L('标记未完成')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<EDropdownItem v-else command="complete">
|
||||
<div class="item">
|
||||
<Icon type="md-radio-button-off" />{{$L('完成')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<EDropdownItem v-if="item.parent_id === 0" command="archived">
|
||||
<div class="item">
|
||||
<Icon type="ios-filing" />{{$L('归档')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<EDropdownItem command="remove">
|
||||
<div class="item">
|
||||
<Icon type="md-trash" />{{$L('删除')}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<template v-if="item.parent_id === 0">
|
||||
<EDropdownItem divided disabled>{{$L('背景色')}}</EDropdownItem>
|
||||
<EDropdownItem v-for="(c, k) in $store.state.taskColorList" :key="k" :command="c">
|
||||
<div class="item">
|
||||
<i class="taskfont" :style="{color:c.color||'#f9f9f9'}" v-html="c.color == item.color ? '' : ''"></i>{{$L(c.name)}}
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
</template>
|
||||
</EDropdownMenu>
|
||||
</EDropdown>
|
||||
</TaskMenu>
|
||||
<div class="item-title">
|
||||
<span v-if="item.sub_top === true">{{$L('子任务')}}</span>
|
||||
<span v-if="item.sub_my && item.sub_my.length > 0">+{{item.sub_my.length}}</span>
|
||||
@ -107,9 +73,10 @@
|
||||
import {mapGetters, mapState} from "vuex";
|
||||
import AppDown from "../../components/AppDown";
|
||||
import {Store} from "le5le-store";
|
||||
import TaskMenu from "./components/TaskMenu";
|
||||
|
||||
export default {
|
||||
components: {AppDown},
|
||||
components: {TaskMenu, AppDown},
|
||||
data() {
|
||||
return {
|
||||
nowTime: $A.Time(),
|
||||
@ -117,10 +84,6 @@ export default {
|
||||
|
||||
loadIng: 0,
|
||||
dashboard: 'today',
|
||||
|
||||
taskLoad: {},
|
||||
|
||||
tempShowTasks: [],
|
||||
}
|
||||
},
|
||||
|
||||
@ -156,7 +119,7 @@ export default {
|
||||
},
|
||||
|
||||
list() {
|
||||
const {dashboard, tempShowTasks} = this;
|
||||
const {dashboard} = this;
|
||||
let data = [];
|
||||
switch (dashboard) {
|
||||
case 'today':
|
||||
@ -166,112 +129,17 @@ export default {
|
||||
data = this.transforTasks(this.dashboardTask.overdue);
|
||||
break
|
||||
}
|
||||
if (tempShowTasks.length > 0) {
|
||||
data.push(...tempShowTasks);
|
||||
}
|
||||
return data.sort((a, b) => {
|
||||
return $A.Date(a.end_at) - $A.Date(b.end_at);
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
'$route'() {
|
||||
this.tempShowTasks = [];
|
||||
},
|
||||
dashboard() {
|
||||
this.tempShowTasks = [];
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
dropTask(task, command) {
|
||||
switch (command) {
|
||||
case 'complete':
|
||||
if (task.complete_at) return;
|
||||
this.updateTask(task, {
|
||||
complete_at: $A.formatDate("Y-m-d H:i:s")
|
||||
}).then(() => {
|
||||
this.tempShowTasks.push(task)
|
||||
})
|
||||
break;
|
||||
case 'uncomplete':
|
||||
if (!task.complete_at) return;
|
||||
this.updateTask(task, {
|
||||
complete_at: false
|
||||
}).then(() => {
|
||||
this.tempShowTasks = this.tempShowTasks.filter(({id}) => id != task.id)
|
||||
})
|
||||
break;
|
||||
case 'archived':
|
||||
case 'remove':
|
||||
this.archivedOrRemoveTask(task, command);
|
||||
break;
|
||||
default:
|
||||
if (command.name) {
|
||||
this.updateTask(task, {
|
||||
color: command.color
|
||||
})
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
openTask(task) {
|
||||
this.$store.dispatch("openTask", task)
|
||||
},
|
||||
|
||||
updateTask(task, updata) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.taskLoad[task.id] === true) {
|
||||
reject()
|
||||
return;
|
||||
}
|
||||
this.$set(this.taskLoad, task.id, true);
|
||||
//
|
||||
Object.keys(updata).forEach(key => this.$set(task, key, updata[key]));
|
||||
//
|
||||
this.$store.dispatch("taskUpdate", Object.assign(updata, {
|
||||
task_id: task.id,
|
||||
})).then(() => {
|
||||
this.$set(this.taskLoad, task.id, false);
|
||||
resolve()
|
||||
}).catch(({msg}) => {
|
||||
$A.modalError(msg);
|
||||
this.$set(this.taskLoad, task.id, false);
|
||||
this.$store.dispatch("getTaskOne", task.id);
|
||||
reject();
|
||||
});
|
||||
})
|
||||
},
|
||||
|
||||
archivedOrRemoveTask(task, type) {
|
||||
let typeDispatch = type == 'remove' ? 'removeTask' : 'archivedTask';
|
||||
let typeName = type == 'remove' ? '删除' : '归档';
|
||||
let typeTask = task.parent_id > 0 ? '子任务' : '任务';
|
||||
$A.modalConfirm({
|
||||
title: typeName + typeTask,
|
||||
content: '你确定要' + typeName + typeTask + '【' + task.name + '】吗?',
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
if (this.taskLoad[task.id] === true) {
|
||||
this.$Modal.remove();
|
||||
return;
|
||||
}
|
||||
this.$set(this.taskLoad, task.id, true);
|
||||
this.$store.dispatch(typeDispatch, task.id).then(({msg}) => {
|
||||
$A.messageSuccess(msg);
|
||||
this.$Modal.remove();
|
||||
this.$set(this.taskLoad, task.id, false);
|
||||
}).catch(({msg}) => {
|
||||
$A.modalError(msg, 301);
|
||||
this.$Modal.remove();
|
||||
this.$set(this.taskLoad, task.id, false);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
expiresFormat(date) {
|
||||
return $A.countDownFormat(date, this.nowTime)
|
||||
},
|
||||
|
49
resources/assets/js/store/actions.js
vendored
49
resources/assets/js/store/actions.js
vendored
@ -1135,6 +1135,7 @@ export default {
|
||||
reject({msg: 'Parameter error'});
|
||||
return;
|
||||
}
|
||||
dispatch("taskLoadAdd", task_id)
|
||||
dispatch("call", {
|
||||
url: 'project/task/remove',
|
||||
data: {
|
||||
@ -1142,10 +1143,12 @@ export default {
|
||||
},
|
||||
}).then(result => {
|
||||
dispatch("forgetTask", task_id)
|
||||
dispatch("taskLoadSub", task_id)
|
||||
resolve(result)
|
||||
}).catch(e => {
|
||||
console.error(e);
|
||||
dispatch("getTaskOne", task_id);
|
||||
dispatch("taskLoadSub", task_id)
|
||||
reject(e)
|
||||
});
|
||||
});
|
||||
@ -1164,6 +1167,7 @@ export default {
|
||||
reject({msg: 'Parameter error'});
|
||||
return;
|
||||
}
|
||||
dispatch("taskLoadAdd", task_id)
|
||||
dispatch("call", {
|
||||
url: 'project/task/archived',
|
||||
data: {
|
||||
@ -1171,10 +1175,12 @@ export default {
|
||||
},
|
||||
}).then(result => {
|
||||
dispatch("forgetTask", task_id)
|
||||
dispatch("taskLoadSub", task_id)
|
||||
resolve(result)
|
||||
}).catch(e => {
|
||||
console.error(e);
|
||||
dispatch("getTaskOne", task_id);
|
||||
dispatch("getTaskOne", task_id)
|
||||
dispatch("taskLoadSub", task_id)
|
||||
reject(e)
|
||||
});
|
||||
});
|
||||
@ -1365,28 +1371,67 @@ export default {
|
||||
* 更新任务
|
||||
* @param state
|
||||
* @param dispatch
|
||||
* @param data
|
||||
* @param data {task_id, ?}
|
||||
* @returns {Promise<unknown>}
|
||||
*/
|
||||
taskUpdate({state, dispatch}, data) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
const post = $A.cloneJSON($A.date2string(data));
|
||||
//
|
||||
dispatch("taskLoadAdd", post.task_id)
|
||||
dispatch("call", {
|
||||
url: 'project/task/update',
|
||||
data: post,
|
||||
method: 'post',
|
||||
}).then(result => {
|
||||
dispatch("taskLoadSub", post.task_id)
|
||||
dispatch("saveTask", result.data)
|
||||
resolve(result)
|
||||
}).catch(e => {
|
||||
console.error(e);
|
||||
dispatch("taskLoadSub", post.task_id)
|
||||
dispatch("getTaskOne", post.task_id);
|
||||
reject(e)
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 任务增加等待
|
||||
* @param state
|
||||
* @param task_id
|
||||
*/
|
||||
taskLoadAdd({state}, task_id) {
|
||||
setTimeout(() => {
|
||||
const load = state.taskLoading.find(({id}) => id == task_id)
|
||||
if (!load) {
|
||||
state.taskLoading.push({
|
||||
id: task_id,
|
||||
num: 1
|
||||
})
|
||||
} else {
|
||||
load.num++;
|
||||
}
|
||||
}, 300)
|
||||
},
|
||||
|
||||
/**
|
||||
* 任务减少等待
|
||||
* @param state
|
||||
* @param task_id
|
||||
*/
|
||||
taskLoadSub({state}, task_id) {
|
||||
const load = state.taskLoading.find(({id}) => id == task_id)
|
||||
if (!load) {
|
||||
state.taskLoading.push({
|
||||
id: task_id,
|
||||
num: -1
|
||||
})
|
||||
} else {
|
||||
load.num--;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取任务优先级预设数据
|
||||
* @param state
|
||||
|
1
resources/assets/js/store/state.js
vendored
1
resources/assets/js/store/state.js
vendored
@ -67,6 +67,7 @@ state.taskId = 0;
|
||||
state.taskContents = [];
|
||||
state.taskFiles = [];
|
||||
state.taskLogs = [];
|
||||
state.taskLoading = [];
|
||||
|
||||
// 任务优先级
|
||||
state.taskPriority = [];
|
||||
|
@ -10,5 +10,6 @@
|
||||
@import "task-add-simple";
|
||||
@import "task-archived";
|
||||
@import "task-detail";
|
||||
@import "task-menu";
|
||||
@import "task-priority";
|
||||
@import "team-management";
|
||||
|
@ -380,13 +380,14 @@
|
||||
}
|
||||
.ivu-icon {
|
||||
font-size: 22px;
|
||||
&.uncomplete {
|
||||
color: #777777;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: #555555;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&.has-desc {
|
||||
.task-title {
|
||||
font-weight: 600;
|
||||
@ -651,31 +652,12 @@
|
||||
align-items: flex-start;
|
||||
padding: 12px 12px 12px 34px;
|
||||
line-height: 24px;
|
||||
.drop-icon {
|
||||
position: relative;
|
||||
}
|
||||
.loading {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.common-loading {
|
||||
margin: 0;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
height: 24px;
|
||||
}
|
||||
.ivu-icon {
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
color: #cccccc;
|
||||
&.completed {
|
||||
color: $primary-color;
|
||||
}
|
||||
&.sub-icon {
|
||||
font-size: 16px;
|
||||
width: 16px;
|
||||
@ -689,6 +671,9 @@
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
&.uncomplete {
|
||||
color: #cccccc;
|
||||
}
|
||||
}
|
||||
.item-title {
|
||||
flex: 1;
|
||||
|
@ -26,11 +26,23 @@
|
||||
background-color: #f4f5f5;
|
||||
}
|
||||
.icon {
|
||||
width: 18px;
|
||||
.task-menu-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.ivu-icon {
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
&.completed {
|
||||
color: $primary-color;
|
||||
}
|
||||
.loading {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
.common-loading {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
.uncomplete {
|
||||
color: #888888;
|
||||
}
|
||||
}
|
||||
}
|
||||
.nav {
|
||||
@ -78,8 +90,12 @@
|
||||
}
|
||||
.menu {
|
||||
margin-left: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.ivu-icon {
|
||||
font-size: 22px;
|
||||
cursor: pointer;
|
||||
color: #606266;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -243,37 +259,22 @@
|
||||
&:last-child {
|
||||
margin-bottom: -6px;
|
||||
}
|
||||
&:hover {
|
||||
.subtask-time {
|
||||
.clock {
|
||||
transform: translateX(0);
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
.subtask-icon {
|
||||
width: 16px;
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
margin-right: 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
.loading {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin: 0;
|
||||
padding: 2px;
|
||||
}
|
||||
.ivu-icon {
|
||||
font-size: 16px;
|
||||
color: #cccccc;
|
||||
&.completed {
|
||||
color: $primary-color;
|
||||
}
|
||||
}
|
||||
&.sub-icon {
|
||||
font-size: 16px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-left: -20px;
|
||||
margin-right: 4px;
|
||||
color: #cfcfcf;
|
||||
transition: transform 0.2s;
|
||||
&.active {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
.subtask-name {
|
||||
flex: 1;
|
||||
@ -309,6 +310,13 @@
|
||||
color: #ff9900;
|
||||
}
|
||||
}
|
||||
.clock {
|
||||
margin: 3px 2px;
|
||||
font-size: 20px;
|
||||
transition: all 0.2s;
|
||||
transform: translateX(50%);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
.subtask-avatar {
|
||||
height: 20px;
|
||||
|
50
resources/assets/sass/pages/components/task-menu.scss
vendored
Normal file
50
resources/assets/sass/pages/components/task-menu.scss
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
.task-menu-icon {
|
||||
position: relative;
|
||||
|
||||
.loading {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.common-loading {
|
||||
margin: 0;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.ivu-icon {
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
color: #cccccc;
|
||||
|
||||
&.completed {
|
||||
color: $primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.task-menu-more-dropdown {
|
||||
> li {
|
||||
.item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> i {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
font-size: 18px;
|
||||
margin-right: 8px;
|
||||
padding: 0;
|
||||
color: #bbbbbb;
|
||||
|
||||
&.ivu-icon {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user