forked from ccsens_fe/tall-mui-3
7 changed files with 766 additions and 102 deletions
@ -0,0 +1,466 @@ |
|||
<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) { |
|||
this.$t.ui.showToast('请输入名称'); |
|||
return; |
|||
} |
|||
if ((!roleIdList || !roleIdList.length) && !hasRole) { |
|||
this.$t.ui.showToast('请选择负责人'); |
|||
return; |
|||
} |
|||
if (!checkerIdList || !checkerIdList.length) { |
|||
this.$t.ui.showToast('请选择检查人'); |
|||
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> |
Loading…
Reference in new issue