mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-10 18:02:55 +00:00
perf: 工作流支持关联任务列表自动移动
This commit is contained in:
parent
fcecccc9b8
commit
7e5bbb4bb7
@ -390,6 +390,7 @@ class Project extends AbstractModel
|
||||
$userids = Base::arrayRetainInt($item['userids'] ?: [], true);
|
||||
$usertype = trim($item['usertype']);
|
||||
$userlimit = intval($item['userlimit']);
|
||||
$columnid = intval($item['columnid']);
|
||||
if ($usertype == 'replace' && empty($userids)) {
|
||||
throw new ApiException("状态[{$item['name']}]设置错误,设置流转模式时必须填写状态负责人");
|
||||
}
|
||||
@ -411,6 +412,7 @@ class Project extends AbstractModel
|
||||
'userids' => $userids,
|
||||
'usertype' => trim($item['usertype']),
|
||||
'userlimit' => $userlimit,
|
||||
'columnid' => $columnid,
|
||||
], [], $isInsert);
|
||||
if ($flow) {
|
||||
$ids[] = $flow->id;
|
||||
@ -545,7 +547,7 @@ class Project extends AbstractModel
|
||||
$project->save();
|
||||
//
|
||||
if ($flow == 'open') {
|
||||
$project->addFlow(Base::json2array('[{"id":-10,"name":"待处理","status":"start","turns":[-10,-11,-12,-13,-14],"userids":[],"usertype":"add","userlimit":0},{"id":-11,"name":"进行中","status":"progress","turns":[-10,-11,-12,-13,-14],"userids":[],"usertype":"add","userlimit":0},{"id":-12,"name":"待测试","status":"test","turns":[-10,-11,-12,-13,-14],"userids":[],"usertype":"add","userlimit":0},{"id":-13,"name":"已完成","status":"end","turns":[-10,-11,-12,-13,-14],"userids":[],"usertype":"add","userlimit":0},{"id":-14,"name":"已取消","status":"end","turns":[-10,-11,-12,-13,-14],"userids":[],"usertype":"add","userlimit":0}]'));
|
||||
$project->addFlow(Base::json2array('[{"id":-10,"name":"待处理","status":"start","turns":[-10,-11,-12,-13,-14],"userids":[],"usertype":"add","userlimit":0,"columnid":0},{"id":-11,"name":"进行中","status":"progress","turns":[-10,-11,-12,-13,-14],"userids":[],"usertype":"add","userlimit":0,"columnid":0},{"id":-12,"name":"待测试","status":"test","turns":[-10,-11,-12,-13,-14],"userids":[],"usertype":"add","userlimit":0,"columnid":0},{"id":-13,"name":"已完成","status":"end","turns":[-10,-11,-12,-13,-14],"userids":[],"usertype":"add","userlimit":0,"columnid":0},{"id":-14,"name":"已取消","status":"end","turns":[-10,-11,-12,-13,-14],"userids":[],"usertype":"add","userlimit":0,"columnid":0}]'));
|
||||
}
|
||||
});
|
||||
//
|
||||
|
||||
@ -16,6 +16,7 @@ use App\Module\Base;
|
||||
* @property array $userids 状态负责人ID
|
||||
* @property string|null $usertype 流转模式
|
||||
* @property int|null $userlimit 限制负责人
|
||||
* @property int|null $columnid 对应的项目列表
|
||||
* @property int|null $sort 排序
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
@ -23,6 +24,7 @@ use App\Module\Base;
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectFlowItem newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectFlowItem newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectFlowItem query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectFlowItem whereColumnid($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectFlowItem whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectFlowItem whereFlowId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ProjectFlowItem whereId($value)
|
||||
|
||||
@ -618,6 +618,9 @@ class ProjectTask extends AbstractModel
|
||||
$data['assist'] = array_values(array_unique(array_diff($data['assist'], $data['owner'])));
|
||||
}
|
||||
}
|
||||
if ($newFlowItem->columnid && ProjectColumn::whereProjectId($this->project_id)->whereId($newFlowItem->columnid)->exists()) {
|
||||
$data['column_id'] = $newFlowItem->columnid;
|
||||
}
|
||||
$this->flow_item_id = $newFlowItem->id;
|
||||
$this->flow_item_name = $newFlowItem->status . "|" . $newFlowItem->name;
|
||||
$this->addLog("修改{任务}状态", [
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class ProjectFlowItemsAddColumnid extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('project_flow_items', function (Blueprint $table) {
|
||||
if (!Schema::hasColumn('project_flow_items', 'columnid')) {
|
||||
$table->bigInteger('columnid')->nullable()->default(0)->after('userlimit')->comment('对应的项目列表');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('project_flow_items', function (Blueprint $table) {
|
||||
$table->dropColumn("columnid");
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -80,12 +80,12 @@
|
||||
<EDropdown
|
||||
trigger="click"
|
||||
class="more"
|
||||
:class="{opacity: item.userids.length > 0}"
|
||||
:class="{opacity: item.userids.length > 0 || item.columnid > 0}"
|
||||
@command="onMore($event, item)">
|
||||
<div class="more-icon">
|
||||
<EAvatar v-if="item.userids.length > 1" :size="20">{{item.userids.length}}</EAvatar>
|
||||
<UserAvatar v-else-if="item.userids.length > 0" :userid="item.userids[0]" :size="20" tooltipDisabled/>
|
||||
<Icon v-else type="ios-more" />
|
||||
<Badge :dot="item.userids.length > 0 || item.columnid > 0">
|
||||
<Icon type="ios-more" />
|
||||
</Badge>
|
||||
</div>
|
||||
<EDropdownMenu slot="dropdown" class="taskflow-config-more-dropdown-menu">
|
||||
<EDropdownItem v-if="item.userids.length > 0" command="user">
|
||||
@ -95,8 +95,10 @@
|
||||
</EDropdownItem>
|
||||
<EDropdownItem command="user">
|
||||
<div class="item">
|
||||
<Icon type="md-person" />
|
||||
{{$L('状态负责人')}}
|
||||
<Icon type="md-settings" />
|
||||
<Badge :dot="item.userids.length > 0 || item.columnid > 0">
|
||||
{{$L('状态设置')}}
|
||||
</Badge>
|
||||
</div>
|
||||
</EDropdownItem>
|
||||
<EDropdownItem command="name">
|
||||
@ -144,30 +146,53 @@
|
||||
<Button type="primary" @click="onCreate">{{$L('创建工作流')}}</Button>
|
||||
</div>
|
||||
|
||||
<!--状态负责人-->
|
||||
<!--状态设置-->
|
||||
<Modal
|
||||
v-model="userShow"
|
||||
:title="`${$L('状态负责人')} (${userData.name})`"
|
||||
:styles="{
|
||||
width: '90%',
|
||||
maxWidth: '640px'
|
||||
}"
|
||||
:title="`${$L('状态设置')} (${settingData.name})`"
|
||||
:mask-closable="false">
|
||||
<Form :model="userData" label-width="auto" @submit.native.prevent>
|
||||
<FormItem prop="userids" :label="$L('状态负责人')">
|
||||
<UserSelect v-model="userData.userids" :project-id="projectId" :multiple-max="5" :title="$L('选择状态负责人')"/>
|
||||
</FormItem>
|
||||
<FormItem prop="usertype" :label="$L('流转模式')">
|
||||
<RadioGroup v-model="userData.usertype">
|
||||
<Radio label="add">{{$L('添加模式')}}</Radio>
|
||||
<Radio label="replace">{{$L('流转模式')}}</Radio>
|
||||
<Radio label="merge">{{$L('剔除模式')}}</Radio>
|
||||
</RadioGroup>
|
||||
<div v-if="userData.usertype=='replace'" class="form-tip">{{$L(`流转到【${userData.name}】时改变任务负责人为状态负责人,原本的任务负责人移至协助人员。`)}}</div>
|
||||
<div v-else-if="userData.usertype=='merge'" class="form-tip">{{$L(`流转到【${userData.name}】时改变任务负责人为状态负责人(并保留操作状态的人员),原本的任务负责人移至协助人员。`)}}</div>
|
||||
<div v-else class="form-tip">{{$L(`流转到【${userData.name}】时添加状态负责人至任务负责人。`)}}</div>
|
||||
</FormItem>
|
||||
<FormItem prop="userlimit" :label="$L('限制负责人')">
|
||||
<iSwitch v-model="userData.userlimit" :true-value="1" :false-value="0"/>
|
||||
<div v-if="userData.userlimit===1" class="form-tip">{{$L(`流转到【${userData.name}】时,[任务负责人] 和 [项目管理员] 可以修改状态。`)}}</div>
|
||||
<div v-else class="form-tip">{{$L(`流转到【${userData.name}】时,[任务负责人] 和 [项目管理员] 可以修改状态。`)}}</div>
|
||||
</FormItem>
|
||||
<Form :model="settingData" label-width="auto" @submit.native.prevent>
|
||||
<div class="workflow-setting-box">
|
||||
<h3>{{ $L('状态负责人') }}</h3>
|
||||
<div class="form-box">
|
||||
<FormItem prop="userids" :label="$L('状态负责人')">
|
||||
<UserSelect v-model="settingData.userids" :project-id="projectId" :multiple-max="5" :title="$L('选择状态负责人')"/>
|
||||
</FormItem>
|
||||
<FormItem prop="usertype" :label="$L('流转模式')">
|
||||
<RadioGroup v-model="settingData.usertype">
|
||||
<Radio label="add">{{$L('添加模式')}}</Radio>
|
||||
<Radio label="replace">{{$L('流转模式')}}</Radio>
|
||||
<Radio label="merge">{{$L('剔除模式')}}</Radio>
|
||||
</RadioGroup>
|
||||
<div v-if="settingData.usertype=='replace'" class="form-tip">{{$L(`流转到【${settingData.name}】时改变任务负责人为状态负责人,原本的任务负责人移至协助人员。`)}}</div>
|
||||
<div v-else-if="settingData.usertype=='merge'" class="form-tip">{{$L(`流转到【${settingData.name}】时改变任务负责人为状态负责人(并保留操作状态的人员),原本的任务负责人移至协助人员。`)}}</div>
|
||||
<div v-else class="form-tip">{{$L(`流转到【${settingData.name}】时添加状态负责人至任务负责人。`)}}</div>
|
||||
</FormItem>
|
||||
<FormItem prop="userlimit" :label="$L('限制负责人')">
|
||||
<iSwitch v-model="settingData.userlimit" :true-value="1" :false-value="0"/>
|
||||
<div v-if="settingData.userlimit===1" class="form-tip">{{$L(`流转到【${settingData.name}】时,[任务负责人] 和 [项目管理员] 可以修改状态。`)}}</div>
|
||||
<div v-else class="form-tip">{{$L(`流转到【${settingData.name}】时,[任务负责人] 和 [项目管理员] 可以修改状态。`)}}</div>
|
||||
</FormItem>
|
||||
</div>
|
||||
</div>
|
||||
<div class="workflow-setting-box">
|
||||
<h3>{{ $L('关联列表') }}</h3>
|
||||
<div class="form-box">
|
||||
<FormItem prop="usertype" :label="$L('关联列表')">
|
||||
<Select v-model="settingData.columnid" :placeholder="$L('选择关联列表')" transfer>
|
||||
<Option v-for="(item, index) in columnList" :value="item.id" :key="index">{{ item.name }}</Option>
|
||||
</Select>
|
||||
<div class="form-tip">
|
||||
{{$L(`流转到【${settingData.name}】时自动将任务移动至关联列表。`)}}
|
||||
<a v-if="settingData.columnid" href="javascript:void(0)" @click="settingData.columnid=0">{{$L('取消关联')}}</a>
|
||||
</div>
|
||||
</FormItem>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
<div slot="footer" class="adaption">
|
||||
<Button type="default" @click="userShow=false">{{$L('取消')}}</Button>
|
||||
@ -180,6 +205,7 @@
|
||||
<script>
|
||||
import Draggable from "vuedraggable";
|
||||
import UserSelect from "../../../components/UserSelect.vue";
|
||||
import {mapState} from "vuex";
|
||||
|
||||
export default {
|
||||
name: "ProjectWorkflow",
|
||||
@ -198,7 +224,7 @@ export default {
|
||||
openIndex: "",
|
||||
|
||||
userShow: false,
|
||||
userData: {},
|
||||
settingData: {},
|
||||
}
|
||||
},
|
||||
|
||||
@ -206,6 +232,26 @@ export default {
|
||||
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState(['cacheColumns']),
|
||||
|
||||
columnList({projectId, cacheColumns}) {
|
||||
return cacheColumns.filter(({project_id}) => {
|
||||
return project_id == projectId
|
||||
}).sort((a, b) => {
|
||||
if (a.sort != b.sort) {
|
||||
return a.sort - b.sort;
|
||||
}
|
||||
return a.id - b.id;
|
||||
}).map(item => {
|
||||
return {
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
projectId: {
|
||||
handler(val) {
|
||||
@ -285,6 +331,7 @@ export default {
|
||||
"userids": [],
|
||||
"usertype": 'add',
|
||||
"userlimit": 0,
|
||||
"columnid": 0,
|
||||
},
|
||||
{
|
||||
"id": -11,
|
||||
@ -294,6 +341,7 @@ export default {
|
||||
"userids": [],
|
||||
"usertype": 'add',
|
||||
"userlimit": 0,
|
||||
"columnid": 0,
|
||||
},
|
||||
{
|
||||
"id": -12,
|
||||
@ -303,6 +351,7 @@ export default {
|
||||
"userids": [],
|
||||
"usertype": 'add',
|
||||
"userlimit": 0,
|
||||
"columnid": 0,
|
||||
},
|
||||
{
|
||||
"id": -13,
|
||||
@ -312,6 +361,7 @@ export default {
|
||||
"userids": [],
|
||||
"usertype": 'add',
|
||||
"userlimit": 0,
|
||||
"columnid": 0,
|
||||
},
|
||||
{
|
||||
"id": -14,
|
||||
@ -321,6 +371,7 @@ export default {
|
||||
"userids": [],
|
||||
"usertype": 'add',
|
||||
"userlimit": 0,
|
||||
"columnid": 0,
|
||||
}
|
||||
]
|
||||
})
|
||||
@ -367,11 +418,12 @@ export default {
|
||||
onMore(name, item) {
|
||||
switch (name) {
|
||||
case "user":
|
||||
this.$set(this.userData, 'id', item.id);
|
||||
this.$set(this.userData, 'name', item.name);
|
||||
this.$set(this.userData, 'userids', item.userids);
|
||||
this.$set(this.userData, 'usertype', item.usertype);
|
||||
this.$set(this.userData, 'userlimit', item.userlimit);
|
||||
this.$set(this.settingData, 'id', item.id);
|
||||
this.$set(this.settingData, 'name', item.name);
|
||||
this.$set(this.settingData, 'userids', item.userids);
|
||||
this.$set(this.settingData, 'usertype', item.usertype);
|
||||
this.$set(this.settingData, 'userlimit', item.userlimit);
|
||||
this.$set(this.settingData, 'columnid', item.columnid);
|
||||
this.userShow = true;
|
||||
break;
|
||||
|
||||
@ -388,11 +440,12 @@ export default {
|
||||
onUser() {
|
||||
this.userShow = false;
|
||||
this.list.some(data => {
|
||||
let item = data.project_flow_item.find(item => item.id == this.userData.id)
|
||||
let item = data.project_flow_item.find(item => item.id == this.settingData.id)
|
||||
if (item) {
|
||||
this.$set(item, 'userids', this.userData.userids)
|
||||
this.$set(item, 'usertype', this.userData.usertype)
|
||||
this.$set(item, 'userlimit', this.userData.userlimit)
|
||||
this.$set(item, 'userids', this.settingData.userids)
|
||||
this.$set(item, 'usertype', this.settingData.usertype)
|
||||
this.$set(item, 'userlimit', this.settingData.userlimit)
|
||||
this.$set(item, 'columnid', this.settingData.columnid)
|
||||
}
|
||||
})
|
||||
},
|
||||
@ -442,6 +495,7 @@ export default {
|
||||
userids: [],
|
||||
usertype: 'add',
|
||||
userlimit: 0,
|
||||
columnid: 0,
|
||||
})
|
||||
data.project_flow_item.some(item => {
|
||||
item.turns.push(id)
|
||||
|
||||
@ -468,13 +468,22 @@
|
||||
font-size: 18px;
|
||||
font-weight: normal !important;
|
||||
opacity: 0.2;
|
||||
transition: opacity 0.3s;
|
||||
transition: opacity,transform 0.3s;
|
||||
&.opacity {
|
||||
opacity: 1;
|
||||
}
|
||||
&:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
.more-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.ivu-badge-dot {
|
||||
top: 4px;
|
||||
right: -6px;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -482,6 +491,47 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.workflow-setting-box {
|
||||
position: relative;
|
||||
padding: 44px 24px 4px;
|
||||
margin: 24px 0 12px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #eeeeee;
|
||||
transition: box-shadow 0.3s;
|
||||
&:hover {
|
||||
box-shadow: 0 0 10px #e6ecfa;
|
||||
}
|
||||
h3 {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 24px;
|
||||
padding: 4px 10px;
|
||||
border-radius: 4px;
|
||||
display: inline-block;
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #eeeeee;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.form-box {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.ivu-form-item {
|
||||
.ivu-form {
|
||||
padding: 12px 0 0 0;
|
||||
.ivu-form-item {
|
||||
margin-bottom: 8px;
|
||||
.ivu-form-item-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.taskflow-config-more-dropdown-menu {
|
||||
.users {
|
||||
display: flex;
|
||||
@ -496,6 +546,9 @@
|
||||
.item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.ivu-badge-dot {
|
||||
top: 4px;
|
||||
}
|
||||
}
|
||||
.delete {
|
||||
color: #f00;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user