<template>
|
<div class="container">
|
<div class="title" v-if="!editId">
|
任务分配{{ editId }}
|
<span class="back" @click="back"> <i class="iconfont icon-fanhui"></i> 返回 </span>
|
</div>
|
<div class="title" v-else>
|
<span>任务分配</span> <span class="back" @click="back"> <i class="iconfont icon-fanhui"></i> 返回 </span>
|
</div>
|
|
<div class="wrap" style="min-width: 2000px !important;">
|
<el-row>
|
<el-col :lg="16" :md="20" :sm="24" :xs="24">
|
<el-form :model="project" status-icon ref="form" label-width="auto" @submit.prevent :rules="rules">
|
<el-form-item label="所属项目" prop="project_id">
|
<el-select v-model="project.project_id" placeholder="所属项目" clearable filterable
|
@change="handleProjectChange" :disabled="assignFlag">
|
<el-option v-for="item in projectInfoArr" :key="item.id" :label="item.project_name" :value="item.id" />
|
</el-select>
|
</el-form-item>
|
|
<el-form-item label="项目模块" prop="module_id">
|
<el-cascader v-model="project.module_id" :options="projectModuleTreeArr" width="100%" clearable filterable
|
:props="moduleCascaderProps" :show-all-levels="false" @change="handleModuleChange"
|
:disabled="assignFlag" />
|
</el-form-item>
|
|
<el-form-item label="任务名称" prop="name">
|
<el-input v-model="project.name" placeholder="请输入任务名称" clearable :disabled="assignFlag" />
|
</el-form-item>
|
|
<el-form-item label="任务描述" prop="description">
|
<el-input type="textarea" :autosize="{ minRows: 4, maxRows: 8 }" placeholder="请输入备注"
|
v-model="project.description" :disabled="assignFlag">
|
</el-input>
|
</el-form-item>
|
|
<el-form-item label="任务类型" prop="type">
|
<el-select v-model="project.type" placeholder="任务类型" clearable filterable :disabled="assignFlag">
|
<el-option v-for="item in projectTaskTypeArr" :key="item.value" :label="item.label"
|
:value="item.value" />
|
</el-select>
|
</el-form-item>
|
|
<el-form-item label="优先级" prop="priority">
|
<el-select v-model="project.priority" placeholder="优先级" clearable filterable :disabled="assignFlag">
|
<el-option v-for="item in projectTaskPriorityArr" :key="item.value" :label="item.label"
|
:value="item.value" />
|
</el-select>
|
</el-form-item>
|
|
<el-form-item label="任务状态" prop="status">
|
<el-select v-model="project.status" placeholder="任务状态" clearable filterable :disabled="assignFlag">
|
<el-option v-for="item in projectTaskStatusArr" :key="item.value" :label="item.label"
|
:value="item.value" />
|
</el-select>
|
</el-form-item>
|
|
<el-form-item label="排配状态" prop="assign_status">
|
<el-select v-model="project.assign_status" placeholder="排配状态" clearable filterable :disabled="assignFlag">
|
<el-option v-for="item in projectTaskAssignStatus" :key="item.value" :label="item.label"
|
:value="item.value" />
|
</el-select>
|
</el-form-item>
|
|
<el-form-item label="评估人" prop="evaluator_users" class="selectClass">
|
<el-select v-model="project.evaluator_users" placeholder="请选择评估人" clearable filterable :multiple="true"
|
:disabled="assignFlag">
|
<el-option v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id" />
|
</el-select>
|
</el-form-item>
|
|
<el-form-item label="计划工时" prop="plan_hour">
|
<el-input-number v-model="project.plan_hour" :min="1" label="计划工时"
|
:disabled="assignFlag"></el-input-number>
|
</el-form-item>
|
|
<el-form-item label="计划时间" prop="plan_date">
|
<el-date-picker v-model="project.plan_date" type="daterange" range-separator="-"
|
start-placeholder="计划开始时间" end-placeholder="计划结束时间" size="large" format="YYYY-MM-DD"
|
value-format="YYYY-MM-DD HH:mm:ss" :disabled="assignFlag" />
|
</el-form-item>
|
|
<el-form-item label="备注" prop="remark">
|
<el-input type="textarea" :autosize="{ minRows: 4, maxRows: 8 }" placeholder="请输入备注"
|
v-model="project.remark" :disabled="assignFlag">
|
</el-input>
|
</el-form-item>
|
|
<el-form-item label="开发者" prop="developer_users" class="selectClass">
|
<el-select v-model="project.developer_users" placeholder="请选择开发者" clearable filterable :multiple="true"
|
@change="handleDeveloperChange">
|
<el-option v-for="item in developerUserList" :key="item.id" :label="item.nickname" :value="item.id" />
|
</el-select>
|
</el-form-item>
|
|
<el-form-item label="排配信息" v-if="dailys" prop="dailys" class="selectClass">
|
<div class="project-batch" style="width: 3000px !important;">
|
<div v-for="(daily, index) in dailys" :key="index" class="log-item">
|
<el-form inline="true" :ref="refHandler" :key="index" :model="daily" label-position="top"
|
:label-width="labelWidth" @submit.prevent>
|
<el-form-item label-width="30" :label="index === -1 ? '序号' : ''">
|
<el-text class="log-index">{{ index + 1 }}</el-text>
|
</el-form-item>
|
|
<el-form-item :label="index === -1 ? '开发者' : ''" prop="user_id" class="selectClass">
|
<el-select v-model="daily.user_id" placeholder="请选择开发者" clearable filterable :multiple="false" size="small" style="width: 120px" :disabled="assignFlag">
|
<el-option v-for="item in developerUserList" :key="item.id" :label="item.nickname" :value="item.id" />
|
</el-select>
|
</el-form-item>
|
|
<el-form-item :label="index === -1 ? '日志日期' : ''" prop="daily_date" :rules="rules.daily_date">
|
<el-date-picker
|
v-model="daily.daily_date"
|
type="date"
|
placeholder="日志日期"
|
value-format="YYYY-MM-DD"
|
style="width: 120px"
|
size="small"
|
clearable
|
/>
|
</el-form-item>
|
|
<el-form-item :label="index === -1 ? '日志类型' : ''" prop="daily_type" :rules="rules.daily_type">
|
<el-select
|
v-model="daily.daily_type"
|
placeholder="日志类型"
|
style="width: 100px"
|
clearable
|
filterable
|
size="small"
|
>
|
<el-option v-for="item in dailyTypeArr" :key="item.value" :label="item.label" :value="item.value" />
|
</el-select>
|
</el-form-item>
|
|
<el-form-item :label="index === -1 ? '日志状态' : ''" prop="daily_status" :rules="rules.daily_status">
|
<el-select
|
v-model="daily.daily_status"
|
placeholder="日志状态"
|
style="width: 100px"
|
clearable
|
filterable
|
size="small"
|
>
|
<el-option v-for="item in dailyStatusArr" :key="item.value" :label="item.label" :value="item.value" />
|
</el-select>
|
</el-form-item>
|
|
<el-form-item :label="index === -1 ? '日志内容' : ''" prop="daily_content" :rules="rules.daily_content">
|
<el-input
|
v-model="daily.daily_content"
|
placeholder="日志内容"
|
style="width: 200px"
|
:key="index"
|
size="small"
|
clearable
|
/>
|
</el-form-item>
|
|
<el-form-item :label="index === -1 ? '计划用时' : ''" prop="estimated_hours" :rules="rules.estimated_hours">
|
<el-tooltip class="box-item" effect="dark" content="计划工时" placement="top-start">
|
<el-input-number
|
v-model="daily.estimated_hours"
|
:step="0.5"
|
label="计划用时"
|
placeholder="计划用时"
|
:key="index"
|
size="small"
|
clearable
|
/>
|
</el-tooltip>
|
</el-form-item>
|
<el-form-item>
|
<i class="iconfont icon-jian1 minus" @click="deleteRow(index)" :key="index"></i>
|
</el-form-item>
|
</el-form>
|
</div>
|
</div>
|
</el-form-item>
|
|
<el-form-item class="submit">
|
<el-button type="primary" @click="submitForm">保 存</el-button>
|
<el-button @click="resetForm">重 置</el-button>
|
</el-form-item>
|
</el-form>
|
</el-col>
|
</el-row>
|
</div>
|
</div>
|
</template>
|
|
<script>
|
import { reactive, ref, onMounted, computed } from 'vue'
|
import { ElMessageBox,ElMessage } from 'element-plus'
|
import ProjectInfo from '@/model/projectInfo'
|
import sysDictItemModel from '@/model/sysDictItem'
|
import ProjectModuleInfo from '@/model/projectModuleInfo'
|
import AdminInfo from '@/lin/model/admin'
|
import ProjectTaskInfo from '@/model/projectTaskInfo'
|
import ProjectDaily from '@/model/projectDaily'
|
|
export default {
|
props: {
|
editId: {
|
type: String,
|
default: null,
|
},
|
},
|
setup(props, context) {
|
const assignFlag = ref(true)
|
const form = ref(null)
|
const loading = ref(false)
|
|
const dailys = ref([])
|
|
const ruleForm = ref([])
|
const refHandler = el => {
|
if (el) {
|
ruleForm.value.push(el)
|
}
|
}
|
|
const deleteRow = index => {
|
// 获取列表
|
const delDaiy = dailys.value[index]
|
// 把project里面的developer_users删除
|
project.developer_users = project.developer_users.filter(item => item !== delDaiy.user_id)
|
dailys.value.splice(index, 1)
|
}
|
|
const project = reactive({
|
id: '',
|
project_id: '',
|
module_id: '',
|
name: '',
|
description: '',
|
type: '',
|
priority: '',
|
status: '',
|
assign_status: '',
|
evaluator_users: [],
|
developer_users: [],
|
plan_hour: '',
|
plan_date: [],
|
plan_begin_date: '',
|
plan_end_date: '',
|
actual_date: [],
|
actual_begin_date: '',
|
actual_end_date: '',
|
remark: '',
|
})
|
|
const projectTaskStatusArr = ref([])
|
const projectTaskAssignStatus = ref([])
|
const projectTaskTypeArr = ref([])
|
const projectTaskPriorityArr = ref([])
|
const userList = ref([])
|
const developerUserList = ref([])
|
|
const projectInfoArr = ref([])
|
const projectModuleArr = ref([])
|
const projectModuleTreeArr = ref([])
|
const moduleCascaderProps = {
|
value: 'id', // 设置 value 字段
|
label: 'name', // 设置 label 字段
|
children: 'children', // 设置子项的字段
|
checkStrictly: true, // 设置任意节点的子节点是否可以勾选
|
}
|
|
const dailyTypeArr = ref([])
|
const dailyStatusArr = ref([])
|
|
|
const listAssign = (a, b) => Object.keys(a).forEach(key => {
|
a[key] = b[key] || a[key]
|
})
|
|
const handleProjectChange = async e => {
|
// 编辑操作
|
console.log(e)
|
// projectModuleArr.value = await ProjectModuleInfo.getProjectModuleInfoList({ projectId: e })
|
projectModuleTreeArr.value = await ProjectModuleInfo.getProjectModuleTree({ projectId: e })
|
}
|
/**
|
* 表单规则验证
|
*/
|
const rules = {
|
daily_date: [{ message: '请输入日期', trigger: ['blur', 'change'], required: true }],
|
daily_type: [{ message: '请选择日志类型', trigger: ['blur', 'change'], required: true }],
|
project_id: [{ message: '请选择项目', trigger: ['blur', 'change'], required: true }],
|
daily_status: [{ message: '请选择日志状态', trigger: ['blur', 'change'], required: true }],
|
daily_content: [{ message: '请输入日志内容', trigger: ['blur', 'change'], required: true }],
|
estimated_hours: [
|
{
|
message: '请输入计划工时',
|
trigger: ['blur', 'change'],
|
required: true
|
},
|
{
|
message: '工时不能小于 0.5',
|
trigger: ['blur', 'change'],
|
validator: (rule, value, callback) => {
|
if (value < 0.5) {
|
callback(new Error('工时不能小于 0.5'));
|
} else {
|
callback(); // 验证通过
|
}
|
}
|
}
|
]
|
|
}
|
|
onMounted(() => {
|
loadDictDitems()
|
})
|
|
const loadDictDitems = async () => {
|
if (props.editId) {
|
await getProjectInfo()
|
projectModuleTreeArr.value = await ProjectModuleInfo.getProjectModuleTree({ projectId: project.project_id })
|
} else {
|
projectModuleTreeArr.value = await ProjectModuleInfo.getProjectModuleTree({})
|
}
|
projectTaskStatusArr.value = await sysDictItemModel.getSysDictItemListByType('project_task_status')
|
projectTaskAssignStatus.value = await sysDictItemModel.getSysDictItemListByType('project_task_assign_status')
|
projectTaskTypeArr.value = await sysDictItemModel.getSysDictItemListByType('project_task_type')
|
projectTaskPriorityArr.value = await sysDictItemModel.getSysDictItemListByType('project_task_priority')
|
|
projectInfoArr.value = await ProjectInfo.getProjectInfoList('')
|
projectModuleArr.value = await ProjectModuleInfo.getProjectModuleInfoList({})
|
|
// const res = await AdminInfo.getAdminUsers({ groupId: 7, count: 30 })
|
const res = await AdminInfo.getAdminUsers({count: 30 })
|
if (res && res.items) {
|
userList.value = res.items
|
developerUserList.value = res.items.filter(item => item.groups.some(group => group.id === 7))
|
}
|
|
dailyTypeArr.value = await sysDictItemModel.getSysDictItemListByType('daily_type')
|
dailyStatusArr.value = await sysDictItemModel.getSysDictItemListByType('daily_status')
|
|
}
|
|
const getProjectInfo = async () => {
|
loading.value = true
|
const res = await ProjectTaskInfo.get(props.editId)
|
listAssign(project, res)
|
project.plan_date = []
|
project.plan_date.push(`${project.plan_begin_date} 00:00:00`)
|
project.plan_date.push(`${project.plan_end_date} 00:00:00`)
|
if (project.evaluator_users) {
|
const evaluator_users = project.evaluator_users.map(item => Number(item.evaluator_id))
|
console.log('evaluator_users')
|
console.log(evaluator_users)
|
project.evaluator_users = evaluator_users
|
}
|
console.log(project)
|
project.value = res
|
loading.value = false
|
}
|
|
const handleModuleChange = value => {
|
if (value && value.length > 0) {
|
// 仅保存最后一级的 id
|
project.module_id = value[value.length - 1] // 取最后一个值
|
} else {
|
project.module_id = null // 如果没有选择,则清空
|
}
|
}
|
|
const handleDeveloperChange = value => {
|
// 遍历循环dailys,查找是否有userId是否在value中,如果不存在,则新增值
|
value.forEach(item => {
|
const index = dailys.value.findIndex(v => v.user_id === item)
|
if (index === -1) {
|
dailys.value.push({
|
user_id: item,
|
task_id: project.id,
|
project_id: project.project_id,
|
module_id: project.module_id,
|
task_name: project.name,
|
task_desc: project.description,
|
daily_type: '1',
|
daily_content: project.name,
|
daily_status: '0',
|
daily_date: '',
|
estimated_hours: '2',
|
})
|
}
|
})
|
|
// 遍历dailys 把不在value里面的元素给移除
|
dailys.value = dailys.value.filter(item => value.includes(item.user_id))
|
}
|
|
// 重置表单
|
const resetForm = () => {
|
const forms = ruleForm.value
|
forms.forEach(tmpForm => {
|
if (tmpForm) {
|
tmpForm.resetFields()
|
}
|
})
|
}
|
|
const validForm = () => {
|
const forms = ruleForm.value
|
const validateArray = forms.map(async (tmpForm, index, array) => await tmpForm.validate(valid => valid))
|
|
const result = Promise.all(validateArray)
|
return result
|
}
|
|
const submitForm = async formName => {
|
const result = validForm()
|
result.then(res => {
|
let validateFlag = true
|
res.forEach(validateRes => {
|
validateFlag &= validateRes
|
})
|
if (validateFlag) {
|
ElMessageBox.confirm('确认保存吗, 是否继续?', '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning',
|
})
|
.then(async () => {
|
loading.value = true
|
|
const tempForm = { daily_list: dailys.value }
|
const res = await ProjectDaily.createBatchWithTask(tempForm)
|
|
if (res.code < window.MAX_SUCCESS_CODE) {
|
// 重新初始化
|
resetForm()
|
ElMessage.success(`${res.message}`)
|
loading.value = false
|
} else {
|
ElMessage.error(`${res.message}`)
|
loading.value = false
|
}
|
})
|
.catch(e => {
|
// 用户点击取消按钮时执行的操作
|
// 可以选择不做任何事情,也可以显示取消消息
|
// ElMessage.error('操作已取消'); // 如果需要显示取消消息,可以取消注释
|
})
|
}
|
})
|
}
|
|
const back = () => {
|
context.emit('editClose')
|
}
|
|
return {
|
back,
|
project,
|
form,
|
rules,
|
resetForm,
|
submitForm,
|
|
projectTaskStatusArr,
|
projectTaskAssignStatus,
|
projectTaskTypeArr,
|
projectTaskPriorityArr,
|
userList,
|
|
projectInfoArr,
|
projectModuleArr,
|
projectModuleTreeArr,
|
moduleCascaderProps,
|
|
handleProjectChange,
|
handleModuleChange,
|
|
assignFlag,
|
dailys,
|
handleDeveloperChange,
|
dailyTypeArr,
|
dailyStatusArr,
|
deleteRow,
|
ruleForm,
|
refHandler,
|
developerUserList,
|
}
|
},
|
}
|
</script>
|
|
<style lang="scss" scoped>
|
.container {
|
.title {
|
height: 59px;
|
line-height: 59px;
|
color: $parent-title-color;
|
font-size: 16px;
|
font-weight: 500;
|
text-indent: 40px;
|
border-bottom: 1px solid #dae1ec;
|
|
.back {
|
float: right;
|
margin-right: 40px;
|
cursor: pointer;
|
}
|
}
|
|
.wrap {
|
padding: 20px;
|
}
|
|
.submit {
|
float: left;
|
}
|
}
|
</style>
|