部门负责人/部门管理员可通过系统配置开启,选择管理部门后只读查看 本部门及下级部门成员的全部项目和任务。前端自动根据 department_readonly 标记禁用编辑操作,后端统一注入负责人视角上下文控制数据访问边界。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
656 lines
32 KiB
Vue
656 lines
32 KiB
Vue
<template>
|
||
<div class="project-workflow">
|
||
<div class="workflow-title">
|
||
{{$L('工作流设置')}}
|
||
<div class="title-icon">
|
||
<Loading v-if="loadIng > 0"/>
|
||
<Icon v-else type="ios-refresh" @click="getData"/>
|
||
</div>
|
||
</div>
|
||
<div v-if="list.length > 0" class="workflow-content">
|
||
<Collapse v-model="openIndex" accordion>
|
||
<Panel v-for="data in list" :key="data.id" :name="'index_' + data.id">
|
||
<div class="workflow-item">
|
||
<div class="workflow-name">{{data.name}}</div>
|
||
<div class="workflow-status">
|
||
<div
|
||
v-for="item in data.project_flow_item"
|
||
:key="item.id"
|
||
:class="item.status"
|
||
:style="$A.generateColorVarStyle(item.color, [10], 'flow-item-custom-color')">
|
||
{{item.name}}
|
||
</div>
|
||
</div>
|
||
<div class="workflow-save" @click.stop="">
|
||
<template v-if="contrast(data.project_flow_item, data.project_flow_bak)">
|
||
<Button :loading="loadIng > 0" type="primary" @click="onSave(data)">{{$L('保存')}}</Button>
|
||
<Button v-if="data.id > 0" :disabled="loadIng > 0" type="primary" ghost @click="onReduction(data, $event)">{{$L('还原')}}</Button>
|
||
</template>
|
||
<Button :disabled="loadIng > 0" type="error" ghost @click="onDelete(data)">{{$L('删除')}}</Button>
|
||
</div>
|
||
</div>
|
||
<div slot="content" class="taskflow-config">
|
||
<div v-if="flowRulesMap[data.id] && flowRulesMap[data.id].length > 0" class="taskflow-config-rules">
|
||
<div class="rules-title">
|
||
<Icon type="md-list-box" />
|
||
<span>{{$L('工作流规则')}}</span>
|
||
</div>
|
||
<div class="rules-list">
|
||
<div v-for="(rule, ruleIndex) in flowRulesMap[data.id]" :key="ruleIndex" class="rules-item">
|
||
<template v-if="rule.type === 'owner'">
|
||
<span>{{$L('流转到')}}</span>
|
||
<span class="rule-status" :class="rule.status">{{rule.name}}</span>
|
||
<span v-if="rule.usertype === 'add'">{{$L('时添加')}}</span>
|
||
<span v-else>{{$L('时改变任务负责人为')}}</span>
|
||
<UserAvatar v-for="(uid, uidx) in rule.userids" :key="`${ruleIndex}_${uidx}`" :userid="uid" :size="20" :borderWidth="1" showName/>
|
||
<span v-if="rule.usertype === 'add'">{{$L('至任务负责人')}}</span>
|
||
<span v-else-if="rule.usertype === 'merge'">{{$L('(并保留操作人),原负责人移至协助人员')}}</span>
|
||
<span v-else>{{$L(',原负责人移至协助人员')}}</span>
|
||
</template>
|
||
<template v-else-if="rule.type === 'limit'">
|
||
<span class="rule-status" :class="rule.status">{{rule.name}}</span>
|
||
<span>{{$L('仅限任务负责人和项目管理员修改状态')}}</span>
|
||
</template>
|
||
<template v-else-if="rule.type === 'column'">
|
||
<span>{{$L('流转到')}}</span>
|
||
<span class="rule-status" :class="rule.status">{{rule.name}}</span>
|
||
<span>{{$L('时自动将任务移动至列表')}}</span>
|
||
<span class="rule-column">{{rule.columnName}}</span>
|
||
</template>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="taskflow-config-table">
|
||
<div class="taskflow-config-table-left-container">
|
||
<div class="taskflow-config-table-column-header left-header">{{$L('配置项')}}</div>
|
||
<div :ref="`overlay_${data.id}`" class="taskflow-config-table-column-body">
|
||
<div class="taskflow-config-table-block">
|
||
<div class="taskflow-config-table-block-title">{{$L('设置状态为')}}</div>
|
||
<div class="taskflow-config-table-block-item">
|
||
<div>
|
||
<div class="title">{{$L('开始状态')}}</div>
|
||
<div class="subtitle">{{$L('新建任务默认状态')}}</div>
|
||
</div>
|
||
</div>
|
||
<div class="taskflow-config-table-block-item">
|
||
<div>
|
||
<div class="title">{{$L('进行中')}}</div>
|
||
<div class="subtitle">{{$L('可设置多个状态为进行中')}}</div>
|
||
</div>
|
||
</div>
|
||
<div class="taskflow-config-table-block-item">
|
||
<div>
|
||
<div class="title">{{$L('验收/测试')}}</div>
|
||
<div class="subtitle">{{$L('只能设置单个状态为验收/测试')}}</div>
|
||
</div>
|
||
</div>
|
||
<div class="taskflow-config-table-block-item">
|
||
<div>
|
||
<div class="title">{{$L('结束状态')}}</div>
|
||
<div class="subtitle">{{$L('该状态下任务自动标记完成')}}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="taskflow-config-table-block hr">
|
||
<div class="taskflow-config-table-block-title">{{$L('可流转到')}}</div>
|
||
<div v-for="item in data.project_flow_item" :key="item.id" class="taskflow-config-table-block-item">
|
||
<span class="transform-status-name">{{item.name}}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="taskflow-config-table-right-container">
|
||
<Draggable
|
||
:list="data.project_flow_item"
|
||
:animation="150"
|
||
:disabled="$isEEUIApp || windowTouch"
|
||
class="taskflow-config-table-list-wrapper"
|
||
tag="div"
|
||
draggable=".column-border"
|
||
@sort="() => {}">
|
||
<div
|
||
v-for="(item, index) in data.project_flow_item"
|
||
:key="index"
|
||
:style="$A.generateColorVarStyle(item.color, [10, 20, 70], 'flow-item-custom-color')"
|
||
class="taskflow-config-table-status-column column-border"
|
||
:class="item.status">
|
||
<div
|
||
class="taskflow-config-table-status-item taskflow-config-table-column-header">
|
||
<div class="status-label-with-menu" :class="item.status">
|
||
<div class="name">{{item.name}}</div>
|
||
<EDropdown
|
||
trigger="click"
|
||
class="more"
|
||
:class="{opacity: item.userids.length > 0 || item.columnid > 0}"
|
||
@command="onMore($event, item)">
|
||
<div class="more-icon">
|
||
<Badge :dot="item.userids.length > 0 || item.columnid > 0">
|
||
<Icon type="ios-more" />
|
||
</Badge>
|
||
</div>
|
||
<EDropdownMenu slot="dropdown" class="taskflow-config-more-dropdown-menu">
|
||
<li class="taskflow-config-more-dropdown-warp">
|
||
<ul>
|
||
<EDropdownItem v-if="item.userids.length > 0" command="user">
|
||
<div class="users">
|
||
<UserAvatar v-for="(uid, ukey) in item.userids" :key="ukey" :userid="uid" :size="28" :borderWidth="1" :showName="item.userids.length === 1"/>
|
||
</div>
|
||
</EDropdownItem>
|
||
<EDropdownItem command="user">
|
||
<div class="item">
|
||
<Icon type="md-settings" />
|
||
<Badge :dot="item.userids.length > 0 || item.columnid > 0">
|
||
{{$L('状态设置')}}
|
||
</Badge>
|
||
</div>
|
||
</EDropdownItem>
|
||
<EDropdownItem command="name">
|
||
<div class="item">
|
||
<Icon type="md-create" />{{$L('修改名称')}}
|
||
</div>
|
||
</EDropdownItem>
|
||
<EDropdownItem command="remove">
|
||
<div class="item delete">
|
||
<Icon type="md-trash" />{{$L('删除')}}
|
||
</div>
|
||
</EDropdownItem>
|
||
<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||'#ddd'}" v-html="c.color == item.color ? '' : ''"></i>{{$L(c.name)}}
|
||
</div>
|
||
</EDropdownItem>
|
||
</ul>
|
||
</li>
|
||
</EDropdownMenu>
|
||
</EDropdown>
|
||
</div>
|
||
</div>
|
||
<div :ref="`overlay_${data.id}`" class="taskflow-config-table-column-body">
|
||
<div class="taskflow-config-table-block">
|
||
<div class="taskflow-config-table-block-title"></div>
|
||
<RadioGroup v-model="item.status">
|
||
<Radio label="start"><span></span></Radio>
|
||
<Radio label="progress"><span></span></Radio>
|
||
<Radio label="test"><span></span></Radio>
|
||
<Radio label="end"><span></span></Radio>
|
||
</RadioGroup>
|
||
</div>
|
||
<div class="taskflow-config-table-block">
|
||
<div class="taskflow-config-table-block-title"></div>
|
||
<CheckboxGroup v-model="item.turns" @on-change="onTurns(item)">
|
||
<Checkbox v-for="v in data.project_flow_item" :key="v.id" :label="v.id" :disabled="v.id==item.id"><span></span></Checkbox>
|
||
</CheckboxGroup>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="taskflow-config-table-status-column addnew" @click="onAdd(data)">{{$L('添加状态')}}</div>
|
||
</Draggable>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</Panel>
|
||
</Collapse>
|
||
</div>
|
||
<div v-else-if="loadIng == 0" class="workflow-no">
|
||
{{$L('当前项目还没有创建工作流')}}
|
||
<Button type="primary" icon="md-add" @click="onCreate">{{$L('创建工作流')}}</Button>
|
||
</div>
|
||
|
||
<!--状态设置-->
|
||
<Modal
|
||
v-model="userShow"
|
||
:styles="{
|
||
width: '90%',
|
||
maxWidth: '640px'
|
||
}"
|
||
:title="`${$L('状态设置')} (${settingData.name})`"
|
||
:mask-closable="false">
|
||
<Form :model="settingData" v-bind="formOptions" @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>
|
||
<Button type="primary" @click="onUser">{{$L('保存')}}</Button>
|
||
</div>
|
||
</Modal>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import Draggable from "vuedraggable";
|
||
import UserSelect from "../../../components/UserSelect.vue";
|
||
import {mapState} from "vuex";
|
||
|
||
export default {
|
||
name: "ProjectWorkflow",
|
||
components: {UserSelect, Draggable},
|
||
props: {
|
||
projectId: {
|
||
type: Number,
|
||
default: 0
|
||
},
|
||
},
|
||
data() {
|
||
return {
|
||
loadIng: 0,
|
||
|
||
list: [],
|
||
openIndex: "",
|
||
|
||
userShow: false,
|
||
settingData: {},
|
||
}
|
||
},
|
||
|
||
mounted() {
|
||
|
||
},
|
||
|
||
computed: {
|
||
...mapState(['cacheColumns', 'formOptions']),
|
||
|
||
columnList({projectId, cacheColumns}) {
|
||
return cacheColumns.filter(({project_id}) => {
|
||
return project_id == projectId
|
||
}).sort((a, b) => {
|
||
if (a.sort != b.sort) {
|
||
return $A.sortFloat(a.sort, b.sort);
|
||
}
|
||
return a.id - b.id;
|
||
}).map(item => {
|
||
return {
|
||
id: item.id,
|
||
name: item.name,
|
||
}
|
||
});
|
||
},
|
||
|
||
flowRulesMap() {
|
||
const map = {};
|
||
const columnMap = {};
|
||
this.columnList.forEach(col => {
|
||
columnMap[col.id] = col.name;
|
||
});
|
||
|
||
this.list.forEach(data => {
|
||
const rules = [];
|
||
data.project_flow_item.forEach(item => {
|
||
// 状态负责人规则
|
||
if (item.userids && item.userids.length > 0) {
|
||
rules.push({
|
||
type: 'owner',
|
||
name: item.name,
|
||
status: item.status,
|
||
userids: item.userids,
|
||
usertype: item.usertype
|
||
});
|
||
}
|
||
|
||
// 限制负责人规则(不依赖状态负责人)
|
||
if (item.userlimit === 1) {
|
||
rules.push({
|
||
type: 'limit',
|
||
name: item.name,
|
||
status: item.status
|
||
});
|
||
}
|
||
|
||
// 关联列表规则
|
||
if (item.columnid && columnMap[item.columnid]) {
|
||
rules.push({
|
||
type: 'column',
|
||
name: item.name,
|
||
status: item.status,
|
||
columnName: columnMap[item.columnid]
|
||
});
|
||
}
|
||
});
|
||
map[data.id] = rules;
|
||
});
|
||
|
||
return map;
|
||
}
|
||
},
|
||
|
||
watch: {
|
||
projectId: {
|
||
handler(val) {
|
||
if (val) {
|
||
this.getData()
|
||
}
|
||
},
|
||
immediate: true
|
||
},
|
||
},
|
||
|
||
methods: {
|
||
getData() {
|
||
this.loadIng++;
|
||
this.$store.dispatch("call", {
|
||
url: 'project/flow/list',
|
||
data: {
|
||
project_id: this.projectId
|
||
},
|
||
}).then(({data}) => {
|
||
this.list = data.map(item => {
|
||
item.project_flow_bak = JSON.stringify(item.project_flow_item)
|
||
return item;
|
||
});
|
||
this.openIndex = this.list.length === 1 ? ("index_" + this.list[0].id) : ""
|
||
this.$nextTick(this.syncScroller);
|
||
}).catch(({msg}) => {
|
||
$A.modalError(msg);
|
||
}).finally(_ => {
|
||
this.loadIng--;
|
||
});
|
||
},
|
||
|
||
syncScroller() {
|
||
this.list.some(data => {
|
||
this.$refs[`overlay_${data.id}`] && this.$refs[`overlay_${data.id}`].some(el => {
|
||
if (!Object.keys(el.attributes).includes("sync-scroller")) {
|
||
el.setAttribute("sync-scroller", true);
|
||
el.addEventListener('scroll', ({target}) => {
|
||
let top = target.scrollTop;
|
||
let left = target.scrollLeft;
|
||
this.$nextTick(() => {
|
||
this.$refs[`overlay_${data.id}`].some(node => {
|
||
if (node != el) {
|
||
node.scrollTo(left, top)
|
||
}
|
||
})
|
||
})
|
||
});
|
||
}
|
||
});
|
||
})
|
||
|
||
},
|
||
|
||
contrast(project_flow_item, project_flow_bak) {
|
||
return JSON.stringify(project_flow_item) != project_flow_bak
|
||
},
|
||
|
||
existDiff() {
|
||
return !!this.list.find(data => {
|
||
return this.contrast(data.project_flow_item, data.project_flow_bak)
|
||
});
|
||
},
|
||
|
||
onCreate() {
|
||
let id = -1 * $A.randNum(1000, 10000);
|
||
this.list.push({
|
||
"id": id,
|
||
"name": "Default",
|
||
"project_flow_item": [
|
||
{
|
||
"id": -10,
|
||
"name": this.$L("待处理"),
|
||
"status": "start",
|
||
"turns": [-10, -11, -12, -13, -14],
|
||
"userids": [],
|
||
"usertype": 'add',
|
||
"userlimit": 0,
|
||
"columnid": 0,
|
||
},
|
||
{
|
||
"id": -11,
|
||
"name": this.$L("进行中"),
|
||
"status": "progress",
|
||
"turns": [-10, -11, -12, -13, -14],
|
||
"userids": [],
|
||
"usertype": 'add',
|
||
"userlimit": 0,
|
||
"columnid": 0,
|
||
},
|
||
{
|
||
"id": -12,
|
||
"name": this.$L("待测试"),
|
||
"status": "test",
|
||
"turns": [-10, -11, -12, -13, -14],
|
||
"userids": [],
|
||
"usertype": 'add',
|
||
"userlimit": 0,
|
||
"columnid": 0,
|
||
},
|
||
{
|
||
"id": -13,
|
||
"name": this.$L("已完成"),
|
||
"status": "end",
|
||
"turns": [-10, -11, -12, -13, -14],
|
||
"userids": [],
|
||
"usertype": 'add',
|
||
"userlimit": 0,
|
||
"columnid": 0,
|
||
},
|
||
{
|
||
"id": -14,
|
||
"name": this.$L("已取消"),
|
||
"status": "end",
|
||
"color": "#999999",
|
||
"turns": [-10, -11, -12, -13, -14],
|
||
"userids": [],
|
||
"usertype": 'add',
|
||
"userlimit": 0,
|
||
"columnid": 0,
|
||
}
|
||
]
|
||
})
|
||
this.openIndex = "index_" + id;
|
||
this.$nextTick(this.syncScroller);
|
||
},
|
||
|
||
onDelete(data) {
|
||
$A.modalConfirm({
|
||
title: '删除工作流',
|
||
content: '你确定要删除工作流吗?',
|
||
loading: true,
|
||
onOk: () => {
|
||
if (data.id > 0) {
|
||
return new Promise((resolve, reject) => {
|
||
this.loadIng++;
|
||
this.$store.dispatch("call", {
|
||
url: 'project/flow/delete',
|
||
data: {
|
||
project_id: this.projectId,
|
||
},
|
||
}).then(({msg}) => {
|
||
resolve(msg);
|
||
//
|
||
let index = this.list.findIndex(({id}) => id == data.id)
|
||
if (index > -1) {
|
||
this.list.splice(index, 1)
|
||
}
|
||
}).catch(({msg}) => {
|
||
reject(msg);
|
||
}).finally(_ => {
|
||
this.loadIng--;
|
||
});
|
||
})
|
||
}
|
||
const index = this.list.findIndex(({id}) => id == data.id)
|
||
if (index > -1) {
|
||
this.list.splice(index, 1)
|
||
}
|
||
}
|
||
});
|
||
},
|
||
|
||
onMore(command, item) {
|
||
switch (command) {
|
||
case "user":
|
||
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;
|
||
|
||
case "name":
|
||
this.onName(item);
|
||
break;
|
||
|
||
case "remove":
|
||
this.onRemove(item);
|
||
break;
|
||
|
||
default:
|
||
if (command.name) {
|
||
this.$set(item, 'color', command.color);
|
||
}
|
||
}
|
||
},
|
||
|
||
onUser() {
|
||
this.userShow = false;
|
||
this.list.some(data => {
|
||
let item = data.project_flow_item.find(item => item.id == this.settingData.id)
|
||
if (item) {
|
||
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)
|
||
}
|
||
})
|
||
},
|
||
|
||
onName(item) {
|
||
$A.modalInput({
|
||
value: item.name,
|
||
title: "修改名称",
|
||
placeholder: "请输入流程名称",
|
||
onOk: (name) => {
|
||
if (!name) {
|
||
return '请输入流程名称';
|
||
}
|
||
this.$set(item, 'name', name);
|
||
}
|
||
});
|
||
},
|
||
|
||
onRemove(item) {
|
||
this.list.some(data => {
|
||
let index = data.project_flow_item.findIndex(({id}) => id == item.id)
|
||
if (index > -1) {
|
||
data.project_flow_item.splice(index, 1)
|
||
}
|
||
})
|
||
},
|
||
|
||
onTurns(item) {
|
||
this.$set(item, 'turns', item.turns.sort())
|
||
},
|
||
|
||
onAdd(data) {
|
||
$A.modalInput({
|
||
title: "添加状态",
|
||
placeholder: "请输入状态名称",
|
||
onOk: (name) => {
|
||
if (!name) {
|
||
return '请输入状态名称'
|
||
}
|
||
const id = $A.randNum(100000, 999999) * -1;
|
||
const turns = data.project_flow_item.map(({id}) => id)
|
||
data.project_flow_item.push({
|
||
id,
|
||
name,
|
||
status: 'end',
|
||
turns,
|
||
userids: [],
|
||
usertype: 'add',
|
||
userlimit: 0,
|
||
columnid: 0,
|
||
})
|
||
data.project_flow_item.some(item => {
|
||
item.turns.push(id)
|
||
})
|
||
}
|
||
});
|
||
},
|
||
|
||
onReduction(data) {
|
||
this.$set(data, 'project_flow_item', JSON.parse(data.project_flow_bak))
|
||
},
|
||
|
||
onSave(formData) {
|
||
let sort = 0;
|
||
formData.project_flow_item.some(item => {
|
||
item.sort = sort++
|
||
})
|
||
this.loadIng++;
|
||
this.$store.dispatch("call", {
|
||
url: 'project/flow/save',
|
||
data: {
|
||
project_id: this.projectId,
|
||
flows: formData.project_flow_item,
|
||
},
|
||
method: 'post',
|
||
}).then(({data, msg}) => {
|
||
$.messageSuccess(msg)
|
||
//
|
||
data.project_flow_bak = JSON.stringify(data.project_flow_item)
|
||
let index = this.list.findIndex(({id}) => id == formData.id)
|
||
if (index > -1) {
|
||
this.list.splice(index, 1, data)
|
||
} else {
|
||
this.list.push(data)
|
||
}
|
||
this.openIndex = "index_" + data.id;
|
||
this.$nextTick(this.syncScroller);
|
||
}).catch(({msg}) => {
|
||
$A.modalError(msg);
|
||
}).finally(_ => {
|
||
this.loadIng--;
|
||
});
|
||
},
|
||
|
||
saveAll() {
|
||
this.list.some(data => {
|
||
if (this.contrast(data.project_flow_item, data.project_flow_bak)) {
|
||
this.onSave(data)
|
||
}
|
||
});
|
||
},
|
||
|
||
}
|
||
}
|
||
</script>
|