You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
466 lines
14 KiB
466 lines
14 KiB
<template>
|
|
<div class="new-projects-box">
|
|
<div class="form">
|
|
<!-- 项目名称 -->
|
|
<view class="mb-3 font-bold text-base flex justify-center text-black">新建任务</view>
|
|
<div class="flex items-center mb-2">
|
|
<div>名称<span class="text-red-500">*</span>:</div>
|
|
<u-input max-length="5" v-model="name" :type="type" :border="border" />
|
|
</div>
|
|
<!-- 起止时间 -->
|
|
<div class="mb-2">
|
|
<div>起止时间:</div>
|
|
<u-input placeholder="请选择起止时间" v-model="timeValue" :type="type" :border="border" @click="$emit('showTime')" />
|
|
</div>
|
|
<!-- 多选框 -->
|
|
<div class="flex justify-between items-center">
|
|
<div>负责人<span class="text-red-500">*</span>:</div>
|
|
<div class="flex-1" v-if="hasRole">{{ roleName }}</div>
|
|
<div label="负责人" class="flex-1" v-else>
|
|
<u-dropdown disabled ref="uDropdown" placeholder="请选择负责人">
|
|
<u-dropdown-item :title="roleList">
|
|
<view class="slot-content bg-white">
|
|
<div
|
|
class="flex flex-row justify-between mb-1 drop-item"
|
|
v-for="(role, roleIndex) in roleOptions"
|
|
:key="roleIndex"
|
|
@click="change(roleIndex)"
|
|
>
|
|
<view v-model="role.id">{{ role.name }}</view>
|
|
<u-icon v-if="role.dropdownShow" name="checkbox-mark" color="#2979ff" size="28"></u-icon>
|
|
</div>
|
|
</view>
|
|
</u-dropdown-item>
|
|
</u-dropdown>
|
|
</div>
|
|
</div>
|
|
<!-- 下拉图标 -->
|
|
<div class="flex justify-center my-6">
|
|
<u-icon v-if="arrow" name="arrow-down" size="28" @click="openDropdown"></u-icon>
|
|
<u-icon v-else name="arrow-up" size="28" @click="closeSecondDropdown"></u-icon>
|
|
</div>
|
|
<!-- 下拉框的内容 -->
|
|
<div v-if="show" class="mb-6">
|
|
<!-- 描述 -->
|
|
<div class="flex items-center mb-2">
|
|
<div>描述:</div>
|
|
<u-input v-model="description" max-length="48" type="textarea" height="36" auto-height :border="border" />
|
|
</div>
|
|
<!-- 所属项目 -->
|
|
<div class="w flex items-center mb-2">
|
|
<div>所属项目<span class="text-red-500">*</span>:</div>
|
|
<div>{{ project.name }}</div>
|
|
</div>
|
|
<!-- 所属任务 -->
|
|
<div class="w flex items-center mb-2" v-if="task && task.id">
|
|
<div>所属任务:</div>
|
|
<div>{{ task.name }}</div>
|
|
</div>
|
|
<!-- 上道工序 -->
|
|
<div class="flex items-center mb-2">
|
|
<div>上道工序:</div>
|
|
<InputSearch
|
|
@searchPrevTask="searchPrevTask"
|
|
:dataSource="allTasks"
|
|
@select="handleChange"
|
|
@clearAllTasks="clearAllTasks"
|
|
placeholder="请输入上道工序"
|
|
/>
|
|
</div>
|
|
<!-- 检查人多选框 -->
|
|
<div class="flex justify-between items-center">
|
|
<div>检查人<span class="text-red-500">*</span>:</div>
|
|
<div label="检查人" class="flex-1">
|
|
<u-dropdown ref="dropdown">
|
|
<u-dropdown-item :title="checkerList">
|
|
<view class="slot-content bg-white">
|
|
<div
|
|
class="flex flex-row justify-between mb-1 drop-item"
|
|
v-for="(checkoutOption, Index) in checkoutOptions"
|
|
:key="Index"
|
|
@click="choose(Index)"
|
|
>
|
|
<view v-model="checkoutOption.value">{{ checkoutOption.name }}</view>
|
|
<u-icon v-if="checkoutOption.dropdownShow" name="checkbox-mark" color="#2979ff" size="28"></u-icon>
|
|
</div>
|
|
</view>
|
|
</u-dropdown-item>
|
|
</u-dropdown>
|
|
</div>
|
|
</div>
|
|
<!-- 是否是日常任务 -->
|
|
<div class="flex justify-between items-center mt-6">
|
|
是否是日常任务:
|
|
<u-switch v-model="isGlobal" size="28"></u-switch>
|
|
</div>
|
|
<div class="mt-6">
|
|
<div>交付物:</div>
|
|
<div v-for="(sort, sortIndex) in deliverSort" :key="sortIndex">
|
|
<u-input
|
|
@blur="addDeliverInput"
|
|
v-model="sort.name"
|
|
:placeholder="`交付物名称${sortIndex + 1}`"
|
|
:type="type"
|
|
:border="border"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="flex items-center mb-6">
|
|
<u-button type="primary" size="medium" @click="setParameters">提交</u-button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex';
|
|
|
|
export default {
|
|
props: {
|
|
startTime: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
endTime: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
task: {
|
|
type: Object,
|
|
default: null,
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
arrow: true,
|
|
show: false,
|
|
isGlobal: false, //是否日常任务
|
|
name: '', //名称
|
|
showChooseTime: false,
|
|
timeValue: '', //起止时间
|
|
description: '', //描述
|
|
projectShow: false, //所属项目模糊搜索展示
|
|
processTaskId: '', //上道工序
|
|
type: 'text',
|
|
border: true,
|
|
roleList: undefined, //负责人默认多选
|
|
checkerList: undefined, //检查人默认多选
|
|
roleOptions: [], // 负责人下拉多选列表
|
|
checkoutOptions: [], // 检查人下拉多选列表
|
|
roleIdList: [], // 选中的负责人id
|
|
checkerIdList: [], // 选中的检查人id
|
|
deliverables: [], // 交付物
|
|
deliverSort: [{ name: '' }], // 交付物排序
|
|
allTasks: [],
|
|
roleName: '', // 负责人名字
|
|
hasRole: false, // 有没有负责人
|
|
};
|
|
},
|
|
|
|
computed: {
|
|
...mapState('role', ['visibleRoles', 'roleId']),
|
|
...mapState('project', ['project']),
|
|
...mapState('task', ['tasks']),
|
|
...mapGetters('project', ['projectId']),
|
|
},
|
|
|
|
watch: {
|
|
endTime(val) {
|
|
if (val) {
|
|
this.timeValue = this.startTime + ' 至 ' + val;
|
|
}
|
|
},
|
|
},
|
|
|
|
mounted() {
|
|
// 获取负责人和检查人列表
|
|
if (this.visibleRoles.length) {
|
|
this.visibleRoles.forEach(role => {
|
|
role.dropdownShow = false;
|
|
role.status = false;
|
|
});
|
|
}
|
|
this.roleOptions = this.$u.deepClone(this.visibleRoles);
|
|
this.checkoutOptions = this.$u.deepClone(this.visibleRoles);
|
|
|
|
// 判断有没有负责人 是不是添加子任务
|
|
if (this.roleId) {
|
|
const item = this.visibleRoles.find(r => r.id === this.roleId);
|
|
if (item) {
|
|
this.roleName = item.name;
|
|
this.hasRole = true;
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
...mapMutations('task', ['updateTasks']),
|
|
...mapActions('task', ['getPermanent']),
|
|
|
|
// 负责人下拉多选选中
|
|
change(index) {
|
|
let arr = [...this.roleOptions];
|
|
// 选择多选项图标的展示
|
|
arr[index].dropdownShow = !arr[index].dropdownShow;
|
|
// 多选展示的改变
|
|
this.roleList = arr[index].name;
|
|
let shows = '';
|
|
// 遍历arr,如果选中,添加到多选展示框上
|
|
arr.map(val => {
|
|
if (val.dropdownShow === true) {
|
|
shows += val.name + ',';
|
|
this.roleIdList.push(val.id);
|
|
}
|
|
});
|
|
this.roleOptions = [...arr];
|
|
// 删除最后的','
|
|
this.roleList = shows.slice(0, shows.length - 1);
|
|
},
|
|
|
|
// 检查人下拉多选选中
|
|
choose(index) {
|
|
let arr = [...this.checkoutOptions];
|
|
// 选择多选项图标的展示
|
|
arr[index].dropdownShow = !arr[index].dropdownShow;
|
|
// 多选展示的改变
|
|
this.checkerList = arr[index].name;
|
|
let shows = '';
|
|
// 遍历arr,如果选中,添加到多选展示框上
|
|
arr.map(val => {
|
|
if (val.dropdownShow === true) {
|
|
shows += val.name + ',';
|
|
this.checkerIdList.push(val.id);
|
|
}
|
|
});
|
|
this.checkoutOptions = [...arr];
|
|
// 删除最后的','
|
|
this.checkerList = shows.slice(0, shows.length - 1);
|
|
// this.roleList = arr[value - 1].name;
|
|
},
|
|
|
|
// 打开下拉框
|
|
openDropdown() {
|
|
this.arrow = !this.arrow;
|
|
this.show = true;
|
|
},
|
|
|
|
// 关闭下拉框
|
|
closeSecondDropdown() {
|
|
this.arrow = !this.arrow;
|
|
this.show = false;
|
|
},
|
|
|
|
/**
|
|
* 模糊查询 查找项目下的任务
|
|
* @param name 任务名
|
|
* @param projectId 项目id
|
|
*/
|
|
async searchPrevTask(val) {
|
|
try {
|
|
const params = { name: val, projectId: this.projectId };
|
|
const data = await this.$u.api.queryTaskOfProject(params);
|
|
this.allTasks = data;
|
|
return data;
|
|
} catch (error) {
|
|
console.error('error: ', error);
|
|
}
|
|
},
|
|
|
|
//用户点击获取的数据
|
|
handleChange(data) {
|
|
console.log('data', data);
|
|
this.processTaskId = data.detailId;
|
|
},
|
|
// 清空模糊查询信息
|
|
clearAllTasks() {
|
|
this.allTasks = [];
|
|
},
|
|
|
|
// 数组最后一项有值 添加一条交付物输入框
|
|
addDeliverInput() {
|
|
if (this.deliverSort[this.deliverSort.length - 1].name) {
|
|
this.deliverSort.push({ name: '' });
|
|
}
|
|
},
|
|
|
|
// 设置提交参数
|
|
async setParameters() {
|
|
const {
|
|
projectId,
|
|
task,
|
|
name,
|
|
startTime,
|
|
endTime,
|
|
hasRole,
|
|
roleIdList,
|
|
roleId,
|
|
description,
|
|
processTaskId,
|
|
checkerIdList,
|
|
isGlobal,
|
|
} = this;
|
|
if (!name) {
|
|
uni.$uiowToast('请输入名称');
|
|
return;
|
|
}
|
|
if ((!roleIdList || !roleIdList.length) && !hasRole) {
|
|
uni.$uiowToast('请选择负责人');
|
|
return;
|
|
}
|
|
if (!checkerIdList || !checkerIdList.length) {
|
|
uni.$uiowToast('请选择检查人');
|
|
return;
|
|
}
|
|
const deliverList = [];
|
|
this.deliverSort.forEach(item => {
|
|
if (item.name) {
|
|
deliverList.push(item.name);
|
|
}
|
|
});
|
|
const params = {
|
|
name,
|
|
startTime: startTime ? this.$moment(startTime).format('x') - 0 : '',
|
|
endTime: endTime ? this.$moment(endTime).format('x') - 0 : '',
|
|
roleIdList: hasRole ? [roleId] : roleIdList,
|
|
description,
|
|
projectId,
|
|
parentTaskId: task && task.id ? task.id : '', // 父任务
|
|
processTaskId, // 上道工序 TODO
|
|
checkerIdList,
|
|
global: isGlobal ? 1 : 0,
|
|
deliverList,
|
|
};
|
|
await this.handleSubmit(params);
|
|
},
|
|
|
|
/**
|
|
* 新建任务
|
|
* @param name 任务名
|
|
* @param startTime 开始时间
|
|
* @param endTime 结束时间
|
|
* @param roleIdList 负责人id(数组)
|
|
* @param description 描述
|
|
* @param projectId 所属项目id
|
|
* @param parentTaskId 所属任务id
|
|
* @param processTaskId 上道工序(任务id)
|
|
* @param checkerIdList 检查人id(数组)
|
|
* @param global 是否日常任务 0否 1是
|
|
* @param deliverList 交付物名字(数组)
|
|
*/
|
|
async handleSubmit(params) {
|
|
try {
|
|
const data = await this.$u.api.saveTask(params);
|
|
// TODO 任务新建成功 继续 or 取消
|
|
this.$emit('closeMask');
|
|
const newTasks = {
|
|
data: data[0],
|
|
processTaskId: params.processTaskId,
|
|
};
|
|
// 将新加的任务加到store
|
|
// 判断不是子任务
|
|
if (!this.task || !this.task.id) {
|
|
this.addNewTasks(newTasks);
|
|
}
|
|
} catch (error) {
|
|
this.$emit('closeMask');
|
|
console.error('error: ', error);
|
|
}
|
|
},
|
|
|
|
// 添加任务后更新tasks
|
|
addNewTasks(data) {
|
|
const oldTasks = this.$u.deepClone(this.tasks);
|
|
let res = data.data;
|
|
console.log('添加任务后更新tasks', data);
|
|
// 判断有没有选择上道工序
|
|
if (data.processTaskId) {
|
|
const index = oldTasks.find(item => item.detailId === data.processTaskId);
|
|
if (index) {
|
|
oldTasks.splice(index + 1, 0, res);
|
|
}
|
|
} else {
|
|
this.setAddPosition(res, oldTasks);
|
|
}
|
|
},
|
|
|
|
// 设置添加位置
|
|
setAddPosition(res, oldTasks) {
|
|
console.log('设置添加位置', res, oldTasks);
|
|
|
|
if (res.planStart - 0 < oldTasks[0].planStart - 0) {
|
|
// 开始时间小于列表的第一个 插入最前面
|
|
oldTasks.splice(0, 0, res);
|
|
} else if (res.planStart - 0 === oldTasks[0].planStart - 0) {
|
|
// 开始时间等于列表的第一个 插入第二
|
|
oldTasks.splice(1, 0, res);
|
|
} else if (res.planStart - 0 >= oldTasks[oldTasks.length - 1].planStart - 0) {
|
|
// 开始时间大等于列表的最后一个 插入最后
|
|
oldTasks.splice(-1, 0, res);
|
|
} else {
|
|
// 判断开始时间在列表中间的哪个位置
|
|
for (let i = 0; i < oldTasks.length; i++) {
|
|
const item = oldTasks[i];
|
|
if (res.planStart - 0 > item.planStart - 0) {
|
|
if (res.planStart - 0 <= oldTasks[i + 1].planStart - 0) {
|
|
oldTasks.splice(i + 1, 0, res);
|
|
// console.log('res: ', res);
|
|
// return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// TODO: 不能全更新
|
|
console.log('oldTasks: ', oldTasks);
|
|
this.updateTasks([...oldTasks]);
|
|
const params = { roleId: this.roleId, projectId: this.projectId };
|
|
this.getPermanent(params);
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.form {
|
|
display: flex;
|
|
flex-direction: column;
|
|
width: 100%;
|
|
max-height: 400px;
|
|
overflow-y: scroll;
|
|
}
|
|
|
|
.drop-item {
|
|
border-bottom: 1px solid #f1f1f1;
|
|
padding: 16rpx;
|
|
}
|
|
|
|
::v-deep.u-input--border {
|
|
border: none;
|
|
border-radius: 0;
|
|
}
|
|
::v-deep.u-dropdown__menu__item > uni-view {
|
|
border: none !important;
|
|
padding: 5px;
|
|
}
|
|
.u-input {
|
|
border-bottom: 1px solid #dcdfe6;
|
|
}
|
|
|
|
.new-projects-box {
|
|
margin-top: 20px;
|
|
padding: 15px;
|
|
width: 100%;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.w {
|
|
width: 300px;
|
|
height: 39px;
|
|
}
|
|
|
|
::v-deep .u-dropdown__menu__item .u-flex {
|
|
border: 0 !important;
|
|
border-bottom: 1px solid #dcdfe6 !important;
|
|
padding: 0 20rpx;
|
|
}
|
|
</style>
|
|
|