perf: 完善部门群组功能

This commit is contained in:
kuaifan 2022-11-17 20:49:47 +08:00
parent c817e5815f
commit 865ac80b99
13 changed files with 343 additions and 30 deletions

View File

@ -502,6 +502,7 @@ class UsersController extends AbstractController
* - yes: 已认证
* - no: 未认证
* - 其他值: 全部(默认)
* - keys.department 部门ID0表示默认部门不赋值获取所有部门
*
* @apiParam {Number} [page] 当前页,默认:1
* @apiParam {Number} [pagesize] 每页显示数量,默认:20,最大:50
@ -560,6 +561,15 @@ class UsersController extends AbstractController
} elseif ($keys['email_verity'] === 'no') {
$builder->whereEmailVerity(0);
}
if (isset($keys['department'])) {
if ($keys['department'] == '0') {
$builder->where(function($query) {
$query->where("department", "")->orWhere("department", ",,");
});
} else {
$builder->where("department", "like", "%,{$keys['department']},%");
}
}
} else {
$builder->whereNull('disable_at');
}
@ -580,6 +590,7 @@ class UsersController extends AbstractController
* @apiParam {String} [type] 操作
* - setadmin 设为管理员
* - clearadmin 取消管理员
* - department 修改部门(需要参数 department
* - setdisable 设为离职(需要参数 disable_time、transfer_userid
* - cleardisable 取消离职
* - delete 删除会员(需要参数 delete_reason
@ -588,6 +599,7 @@ class UsersController extends AbstractController
* @apiParam {String} [password] 新的密码
* @apiParam {String} [nickname] 昵称
* @apiParam {String} [profession] 职位
* @apiParam {String} [department] 部门
* @apiParam {String} [disable_time] 离职时间
* @apiParam {String} [transfer_userid] 离职交接人
* @apiParam {String} [delete_reason] 删除原因
@ -622,6 +634,18 @@ class UsersController extends AbstractController
$upArray['identity'] = array_diff($userInfo->identity, ['admin']);
break;
case 'department':
if (!is_array($data['department'])) {
$data['department'] = [];
}
foreach ($data['department'] as $id) {
if (!UserDepartment::whereId($id)->exists()) {
return Base::retError('修改部门不存在');
}
}
$upArray['department'] = $data['department'];
break;
case 'setdisable':
if ($userInfo->userid === $user->userid) {
return Base::retError('不能操作自己离职');
@ -660,6 +684,9 @@ class UsersController extends AbstractController
if (isset($upArray['identity'])) {
$upArray['identity'] = "," . implode(",", $upArray['identity']) . ",";
}
if (isset($upArray['department'])) {
$upArray['department'] = "," . implode(",", $upArray['department']) . ",";
}
// 邮箱
if (Arr::exists($data, 'email')) {
$email = trim($data['email']);
@ -710,9 +737,29 @@ class UsersController extends AbstractController
}
if ($upArray) {
AbstractModel::transaction(function() use ($user, $type, $upArray, $userInfo, $transferUser) {
$exitIds = array_diff($userInfo->department, Base::explodeInt($upArray['department']));
$joinIds = array_diff(Base::explodeInt($upArray['department']), $userInfo->department);
$userInfo->updateInstance($upArray);
$userInfo->save();
if ($type === 'setdisable') {
if ($type === 'department') {
$userids = [$userInfo->userid];
// 退出群组
$exitDepartments = UserDepartment::whereIn('id', $exitIds)->get();
foreach ($exitDepartments as $exitDepartment) {
if ($exitDepartment->dialog_id > 0 && $exitDialog = WebSocketDialog::find($exitDepartment->dialog_id)) {
$exitDialog->exitGroup($userids, 'remove', false);
$exitDialog->pushMsg("groupExit", null, $userids);
}
}
// 加入群组
$joinDepartments = UserDepartment::whereIn('id', $joinIds)->get();
foreach ($joinDepartments as $joinDepartment) {
if ($joinDepartment->dialog_id > 0 && $joinDialog = WebSocketDialog::find($joinDepartment->dialog_id)) {
$joinDialog->joinGroup($userids, 0, true);
$joinDialog->pushMsg("groupJoin", null, $userids);
}
}
} elseif ($type === 'setdisable') {
$userTransfer = UserTransfer::createInstance([
'original_userid' => $userInfo->userid,
'new_userid' => $transferUser->userid,
@ -1193,12 +1240,11 @@ class UsersController extends AbstractController
return Base::retError('请选择正确的部门负责人');
}
//
$userDepartment->updateInstance([
$userDepartment->saveDepartment([
'name' => $name,
'parent_id' => $parent_id,
'owner_userid' => $owner_userid,
]);
$userDepartment->saveDepartment();
//
return Base::retSuccess($parent_id > 0 ? '保存成功' : '新建成功');
}

View File

@ -13,6 +13,7 @@ use Carbon\Carbon;
*
* @property int $userid
* @property array $identity 身份
* @property array $department 所属部门
* @property string|null $az A-Z
* @property string|null $pinyin 拼音(主要用于搜索)
* @property string|null $email 邮箱
@ -42,6 +43,7 @@ use Carbon\Carbon;
* @method static \Illuminate\Database\Eloquent\Builder|User whereChangepass($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereCreatedIp($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereDepartment($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereDisableAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereEmail($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereEmailVerity($value)
@ -133,6 +135,19 @@ class User extends AbstractModel
return array_filter(is_array($value) ? $value : explode(",", trim($value, ",")));
}
/**
* 部门
* @param $value
* @return array
*/
public function getDepartmentAttribute($value)
{
if (empty($value)) {
return [];
}
return array_filter(is_array($value) ? $value : explode(",", trim($value, ",")));
}
/**
* 是否在线
* @return bool

View File

@ -2,6 +2,8 @@
namespace App\Models;
use App\Exceptions\ApiException;
/**
* App\Models\UserDepartment
*
@ -26,14 +28,48 @@ namespace App\Models;
*/
class UserDepartment extends AbstractModel
{
/**
* 保存部门
* @return bool
* @param $data
*/
public function saveDepartment() {
// todo 聊天室相关
return $this->save();
public function saveDepartment($data = []) {
AbstractModel::transaction(function () use ($data) {
$oldUser = null;
$newUser = null;
if ($data['owner_userid'] !== $this->owner_userid) {
$oldUser = User::find($this->owner_userid);
$newUser = User::find($data['owner_userid']);
}
$this->updateInstance($data);
//
if ($this->dialog_id > 0) {
$dialog = WebSocketDialog::find($this->dialog_id);
if ($dialog) {
$dialog->name = $this->name;
$dialog->owner_id = $this->owner_userid;
$dialog->save();
}
} else {
$dialog = WebSocketDialog::createGroup($this->name, [$this->owner_userid], 'department', $this->owner_userid);
if (empty($dialog)) {
throw new ApiException("创建群组失败");
}
$this->dialog_id = $dialog->id;
}
$this->save();
//
if ($oldUser) {
$oldUser->department = array_diff($oldUser->department, [$this->id]);
$oldUser->department = "," . implode(",", $oldUser->department) . ",";
$oldUser->save();
}
if ($newUser) {
$newUser->department = array_diff($newUser->department, [$this->id]);
$newUser->department = array_merge($newUser->department, [$this->id]);
$newUser->department = "," . implode(",", $newUser->department) . ",";
$newUser->save();
}
});
}
/**
@ -41,11 +77,27 @@ class UserDepartment extends AbstractModel
* @return void
*/
public function deleteDepartment() {
// 删除子部门
$list = self::whereParentId($this->id)->get();
foreach ($list as $item) {
$item->deleteDepartment();
}
// todo 移动成员
// 移出成员
User::where("department", "like", "%,{$this->id},%")->chunk(100, function($items) {
/** @var User $user */
foreach ($items as $user) {
$user->department = array_diff($user->department, [$this->id]);
$user->department = "," . implode(",", $user->department) . ",";
$user->save();
}
});
// 解散群组
$dialog = WebSocketDialog::find($this->dialog_id);
if ($dialog) {
$dialog->deleteDialog();
$dialog->pushMsg("groupDelete");
}
//
$this->delete();
}
}

View File

@ -144,11 +144,12 @@ class WebSocketDialog extends AbstractModel
* 加入聊天室
* @param int|array $userid 加入的会员ID或会员ID组
* @param int $inviter 邀请人
* @param bool $important 重要人员
* @return bool
*/
public function joinGroup($userid, $inviter)
public function joinGroup($userid, $inviter, $important = false)
{
AbstractModel::transaction(function () use ($inviter, $userid) {
AbstractModel::transaction(function () use ($important, $inviter, $userid) {
foreach (is_array($userid) ? $userid : [$userid] as $value) {
if ($value > 0) {
WebSocketDialogUser::updateInsert([
@ -156,6 +157,7 @@ class WebSocketDialog extends AbstractModel
'userid' => $value,
], [
'inviter' => $inviter,
'important' => $important ? 1 : 0,
]);
WebSocketDialogMsg::sendMsg(null, $this->id, 'notice', [
'notice' => User::userid2nickname($value) . " 已加入群组"
@ -198,7 +200,7 @@ class WebSocketDialog extends AbstractModel
throw new ApiException('群主不可' . $typeDesc);
}
if ($item->important) {
throw new ApiException('项目人员或任务人员不可' . $typeDesc);
throw new ApiException('部门成员、项目人员或任务人员不可' . $typeDesc);
}
}
//
@ -396,7 +398,7 @@ class WebSocketDialog extends AbstractModel
'name' => $name ?: '',
'group_type' => $group_type,
'owner_id' => $owner_id,
'last_at' => in_array($group_type, ['user', 'all']) ? Carbon::now() : null,
'last_at' => in_array($group_type, ['user', 'department', 'all']) ? Carbon::now() : null,
]);
$dialog->save();
foreach (is_array($userid) ? $userid : [$userid] as $value) {

View File

@ -11,7 +11,7 @@ namespace App\Models;
* @property string|null $top_at 置顶时间
* @property int|null $mark_unread 是否标记为未读0否1是
* @property int|null $inviter 邀请人
* @property int|null $important 是否不可移出(项目、任务人员)
* @property int|null $important 是否不可移出(项目、任务、部门人员)
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser newModelQuery()

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddUsersDepartment extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
if (!Schema::hasColumn('users', 'department')) {
$table->string('department', 255)->nullable()->default('')->after('identity')->comment('所属部门');
}
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn("department");
});
}
}

View File

@ -34,7 +34,9 @@
<div v-if="dialogData.group_type !== 'all'" class="group-info-button">
<Button v-if="dialogData.owner_id == userId || dialogData.owner_id == 0" @click="openAdd" type="primary">{{ $L("添加成员") }}</Button>
<Button v-if="dialogData.owner_id == userId" @click="onDisband" type="error" ghost>{{ $L("解散群组") }}</Button>
<template v-if="dialogData.owner_id == userId">
<Button v-if="dialogData.group_type !== 'department'" @click="onDisband" type="error" ghost>{{ $L("解散群组") }}</Button>
</template>
<Button v-else @click="onExit" type="error" ghost>{{ $L("退出群组") }}</Button>
</div>
@ -45,7 +47,10 @@
:mask-closable="false">
<Form :model="addData" label-width="auto" @submit.native.prevent>
<FormItem prop="userids" :label="$L('新增成员')">
<UserInput v-model="addData.userids" :disabledChoice="addData.disabledChoice" :multiple-max="100" :placeholder="$L('选择项目成员')"/>
<UserInput v-model="addData.userids" :disabledChoice="addData.disabledChoice" :multiple-max="100" :placeholder="$L('选择成员')"/>
<div v-if="dialogData.group_type === 'department'" class="form-tip">{{$L('此操作仅加入群成员并不会加入部门')}}</div>
<div v-else-if="dialogData.group_type === 'project'" class="form-tip">{{$L('此操作仅加入群成员并不会加入项目')}}</div>
<div v-else-if="dialogData.group_type === 'task'" class="form-tip">{{$L('此操作仅加入群成员并不会加入任务负责人')}}</div>
</FormItem>
</Form>
<div slot="footer" class="adaption">
@ -95,6 +100,7 @@ export default {
groupType() {
const {group_type} = this.dialogData
if (group_type === 'department') return '部门群组'
if (group_type === 'project') return '项目群组'
if (group_type === 'task') return '任务群组'
if (group_type === 'user') return '个人群组'

View File

@ -20,7 +20,8 @@
<div class="dialog-block">
<div class="dialog-avatar">
<template v-if="dialogData.type=='group'">
<i v-if="dialogData.group_type=='project'" class="taskfont icon-avatar project">&#xe6f9;</i>
<i v-if="dialogData.group_type=='department'" class="taskfont icon-avatar department">&#xe75c;</i>
<i v-else-if="dialogData.group_type=='project'" class="taskfont icon-avatar project">&#xe6f9;</i>
<i v-else-if="dialogData.group_type=='task'" class="taskfont icon-avatar task">&#xe6f4;</i>
<Icon v-else class="icon-avatar" type="ios-people" />
</template>
@ -40,6 +41,8 @@
</template>
<h2>{{dialogData.name}}</h2>
<em v-if="peopleNum > 0">({{peopleNum}})</em>
<Tag v-if="dialogData.group_type=='all'" class="after" :fade="false">{{$L('全员')}}</Tag>
<Tag v-else-if="dialogData.group_type=='department'" class="after" :fade="false">{{$L('部门')}}</Tag>
</div>
<ul class="title-desc">
<li v-if="dialogData.type === 'user'" :class="[dialogData.online_state === true ? 'online' : 'offline']">
@ -295,7 +298,8 @@
<div class="forward-option">
<div class="forward-avatar">
<template v-if="dialog.type=='group'">
<i v-if="dialog.group_type=='project'" class="taskfont icon-avatar project">&#xe6f9;</i>
<i v-if="dialog.group_type=='department'" class="taskfont icon-avatar department">&#xe75c;</i>
<i v-else-if="dialog.group_type=='project'" class="taskfont icon-avatar project">&#xe6f9;</i>
<i v-else-if="dialog.group_type=='task'" class="taskfont icon-avatar task">&#xe6f4;</i>
<Icon v-else class="icon-avatar" type="ios-people" />
</template>

View File

@ -9,14 +9,14 @@
<div class="management-box">
<div class="management-department">
<ul>
<li class="level-1">
<li :class="[`level-1`, departmentSelect === 0 ? 'active' : '']" @click="onSelectDepartment(0)">
<i class="taskfont department-icon">&#xe766;</i>
<div class="department-title">{{$L('默认部门')}}</div>
<EDropdown
size="medium"
trigger="click"
@command="onOpDepartment">
<i class="taskfont department-menu">&#xe6e9;</i>
<i @click.stop="" class="taskfont department-menu">&#xe6e9;</i>
<EDropdownMenu slot="dropdown">
<EDropdownItem command="add_0">
<div>{{$L('添加子部门')}}</div>
@ -24,7 +24,11 @@
</EDropdownMenu>
</EDropdown>
</li>
<li v-for="item in departmentList" :key="item.id" :class="`level-${item.level}`">
<li
v-for="item in departmentList"
:key="item.id"
:class="[`level-${item.level}`, departmentSelect === item.id ? 'active' : '']"
@click="onSelectDepartment(item.id)">
<UserAvatar :userid="item.owner_userid" :size="20" class="department-icon">
<p><strong>{{$L('部门负责人')}}</strong></p>
</UserAvatar>
@ -33,7 +37,7 @@
size="medium"
trigger="click"
@command="onOpDepartment">
<i class="taskfont department-menu">&#xe6e9;</i>
<i @click.stop="" class="taskfont department-menu">&#xe6e9;</i>
<EDropdownMenu slot="dropdown">
<EDropdownItem v-if="item.level <= 2" :command="`add_${item.id}`">
<div>{{$L('添加子部门')}}</div>
@ -163,10 +167,30 @@
</div>
</Modal>
<!--修改部门-->
<Modal
v-model="departmentEditShow"
:title="$L('修改部门')">
<Form :model="departmentEditData" label-width="auto" @submit.native.prevent>
<Alert type="error" style="margin-bottom:18px">{{$L(`正在进行帐号【ID:${departmentEditData.userid}${departmentEditData.nickname}】部门修改。`)}}</Alert>
<FormItem :label="$L('原部门')">
<div>{{departmentEditData.old || '-'}}</div>
</FormItem>
<FormItem :label="$L('修改部门')">
<Select v-model="departmentEditData.department" multiple :placeholder="$L('留空为默认部门')">
<Option v-for="(item, index) in departmentList" :value="item.id" :key="index">{{ item.name }}</Option>
</Select>
</FormItem>
</Form>
<div slot="footer" class="adaption">
<Button type="default" @click="departmentEditShow=false">{{$L('取消')}}</Button>
<Button type="primary" :loading="departmentEditLoading > 0" @click="operationUser(departmentEditData, true)">{{$L('确定修改')}}</Button>
</div>
</Modal>
<!--操作离职-->
<Modal
v-model="disableShow"
class="operate-left"
:title="$L('操作离职')">
<Form :model="disableData" label-width="auto" @submit.native.prevent>
<Alert type="error" style="margin-bottom:18px">{{$L(`正在进行帐号【ID:${disableData.userid}${disableData.nickname}】离职操作。`)}}</Alert>
@ -223,12 +247,17 @@ export default {
total: 0,
noText: '',
departmentEditShow: false,
departmentEditLoading: 0,
departmentEditData: {},
disableShow: false,
disableLoading: 0,
disableData: {},
departmentShow: false,
departmentLoading: 0,
departmentSelect: -1,
departmentData: {
id: 0,
name: '',
@ -248,6 +277,9 @@ export default {
this.keys = {}
this.setPage(1)
}
},
departmentSelect() {
this.setPage(1)
}
},
computed: {
@ -378,6 +410,43 @@ export default {
]);
},
},
{
title: this.$L('部门'),
key: 'department',
minWidth: 80,
render: (h, {row}) => {
let departments = []
row.department.some(did => {
const data = this.departmentList.find(d => d.id == did)
if (data) {
departments.push(data.name)
}
})
if (departments.length === 0) {
return h('div', this.$L('默认部门'));
} else {
const tmp = []
tmp.push(h('span', departments[0]))
if (departments.length > 1) {
departments = departments.splice(1)
tmp.push(h('ETooltip', [
h('div', {
slot: 'content',
domProps: {
innerHTML: departments.join("<br/>")
}
}),
h('div', {
class: 'department-tag-num'
}, ` +${departments.length}`)
]))
}
return h('div', {
class: 'team-table-department-warp'
}, tmp);
}
},
},
{
title: this.$L('最后在线'),
key: 'line_at',
@ -416,6 +485,12 @@ export default {
},
}, [h('div', this.$L('修改密码'))]))
dropdownItems.push(h('EDropdownItem', {
props: {
command: 'department',
},
}, [h('div', this.$L('修改部门'))]))
if (identity.includes('disable')) {
dropdownItems.push(h('EDropdownItem', {
props: {
@ -487,10 +562,16 @@ export default {
getLists() {
this.loadIng++;
this.keyIs = $A.objImplode(this.keys) != "";
let keys = $A.cloneJSON(this.keys)
if (this.departmentSelect > -1) {
keys = Object.assign(keys, {
department: this.departmentSelect
})
}
this.$store.dispatch("call", {
url: 'users/lists',
data: {
keys: this.keys,
keys,
page: Math.max(this.page, 1),
pagesize: Math.max($A.runNum(this.pageSize), 10),
},
@ -498,7 +579,7 @@ export default {
this.page = data.current_page;
this.total = data.total;
this.list = data.data;
this.noText = '没有相关的数据';
this.noText = '没有相关的成员';
}).catch(() => {
this.noText = '数据加载失败';
}).finally(_ => {
@ -551,6 +632,24 @@ export default {
});
break;
case 'department':
let departments = []
row.department.some(did => {
const data = this.departmentList.find(d => d.id == did)
if (data) {
departments.push(data.name)
}
})
this.departmentEditData = {
type: 'department',
userid: row.userid,
nickname: row.nickname,
department: row.department.map(id => parseInt(id)),
old: departments.join(", ")
};
this.departmentEditShow = true;
break;
case 'setdisable':
this.disableData = {
type: 'setdisable',
@ -602,7 +701,9 @@ export default {
operationUser(data, tipErr) {
return new Promise((resolve, reject) => {
if (data.type == 'setdisable') {
if (data.type == 'department') {
this.departmentEditLoading++;
} else if (data.type == 'setdisable') {
this.disableLoading++;
} else {
this.loadIng++;
@ -614,7 +715,9 @@ export default {
$A.messageSuccess(msg);
this.getLists();
resolve()
if (data.type == 'setdisable') {
if (data.type == 'department') {
this.departmentEditShow = false;
} else if (data.type == 'setdisable') {
this.disableShow = false;
}
}).catch(({msg}) => {
@ -624,7 +727,9 @@ export default {
this.getLists();
reject(msg)
}).finally(_ => {
if (data.type == 'setdisable') {
if (data.type == 'department') {
this.departmentEditLoading--;
} else if (data.type == 'setdisable') {
this.disableLoading--;
} else {
this.loadIng--;
@ -676,6 +781,7 @@ export default {
}).then(({msg}) => {
$A.messageSuccess(msg)
this.getDepartmentLists()
this.getLists()
this.departmentShow = false
}).catch(({msg}) => {
$A.modalError(msg);
@ -684,6 +790,14 @@ export default {
})
},
onSelectDepartment(id) {
if (this.departmentSelect === id) {
this.departmentSelect = -1
return
}
this.departmentSelect = id
},
onOpDepartment(val) {
if ($A.leftExists(val, 'add_')) {
this.onShowDepartment({
@ -699,7 +813,7 @@ export default {
if (delItem) {
$A.modalConfirm({
title: this.$L('删除部门'),
content: `<div>${this.$L(`你确定要删除【${delItem.name}】部门吗?`)}</div><div style="color:#f00;font-weight:600">${this.$L(`注意:此操作不可恢复,部门下的成员将向上移动`)}</div>`,
content: `<div>${this.$L(`你确定要删除【${delItem.name}】部门吗?`)}</div><div style="color:#f00;font-weight:600">${this.$L(`注意:此操作不可恢复,部门下的成员将移至默认部门`)}</div>`,
language: false,
loading: true,
onOk: () => {
@ -710,6 +824,9 @@ export default {
id: delItem.id
},
}).then(({msg}) => {
if (delItem.id === this.departmentSelect) {
this.departmentSelect = -1
}
resolve(msg);
this.getDepartmentLists();
}).catch(({msg}) => {

View File

@ -55,7 +55,8 @@
})"
v-longpress="handleLongpress">
<template v-if="dialog.type=='group'">
<i v-if="dialog.group_type=='project'" class="taskfont icon-avatar project">&#xe6f9;</i>
<i v-if="dialog.group_type=='department'" class="taskfont icon-avatar department">&#xe75c;</i>
<i v-else-if="dialog.group_type=='project'" class="taskfont icon-avatar project">&#xe6f9;</i>
<i v-else-if="dialog.group_type=='task'" class="taskfont icon-avatar task">&#xe6f4;</i>
<Icon v-else class="icon-avatar" type="ios-people" />
</template>

View File

@ -128,6 +128,10 @@
background-color: #61B2F9;
color: #ffffff;
&.department {
background-color: #5BC7B0;
}
&.project {
background-color: #6E99EB;
}
@ -160,6 +164,10 @@
&.ivu-tag-success {
padding: 0 6px;
}
&.after {
margin: 0 0 0 6px;
}
}
.ivu-icon {
@ -1420,6 +1428,9 @@
font-size: 18px;
background-color: #61B2F9;
color: #ffffff;
&.department {
background-color: #5BC7B0;
}
&.project {
background-color: #6E99EB;
}

View File

@ -130,3 +130,25 @@
height: 0;
}
}
.team-table-department-warp {
display: flex;
align-items: center;
.department-tag-num {
background-color: #515a6e;
border-radius: 9px;
color: #fff;
cursor: pointer;
flex-shrink: 0;
font-size: 12px;
height: 18px;
line-height: 18px;
margin-left: 4px;
min-width: 18px;
padding: 0 5px;
text-align: center;
transform: scale(0.9);
transform-origin: right center;
}
}

View File

@ -126,6 +126,9 @@
font-size: 26px;
background-color: #61B2F9;
color: #ffffff;
&.department {
background-color: #5BC7B0;
}
&.project {
background-color: #6E99EB;
}