forked from TALL/tall3-pc-keti
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.
389 lines
12 KiB
389 lines
12 KiB
<template>
|
|
<div class="task-form bg-white border-radius-10">
|
|
<a-form ref="formRef" :model="topicMeetFormData">
|
|
<a-form-item>
|
|
<label class="color-3">课题名称</label>
|
|
<a-input v-model:value="topicMeetFormData.name" placeholder="课题名称" />
|
|
</a-form-item>
|
|
|
|
<a-form-item>
|
|
<label class="color-3">起止时间</label>
|
|
<a-space direction="vertical" :size="12">
|
|
<a-range-picker v-model:value="topicMeetFormData.date" />
|
|
</a-space>
|
|
</a-form-item>
|
|
|
|
<a-form-item>
|
|
<label class="color-3">负责人</label>
|
|
<a-select
|
|
v-model:value="topicMeetFormData.memberId"
|
|
show-search
|
|
optionFilterProp="label"
|
|
placeholder="负责人"
|
|
:options="options"
|
|
:filter-option="filterOption"
|
|
@search="handleSearch"
|
|
:getPopupContainer="
|
|
triggerNode => {
|
|
return triggerNode.parentNode || document.body;
|
|
}
|
|
"
|
|
></a-select>
|
|
</a-form-item>
|
|
|
|
<a-form-item class="form-item-dad">
|
|
<div class="flex items-center" style="margin-bottom: 5px">
|
|
<label class="color-3" style="margin-bottom: 0; margin-right: 8px">项目分阶段具体实施目标</label>
|
|
<PlusCircleOutlined style="color: #1890ff; font-size: 16px" @click="addMilestones" />
|
|
</div>
|
|
|
|
<div class="form-item-son" style="padding-left: 16px">
|
|
<div v-for="(item, index) in planTaskStageList" :key="index">
|
|
<a-form-item>
|
|
<label class="color-3">第{{ index + 1 }}阶段</label>
|
|
<a-space direction="vertical" :size="12">
|
|
<a-range-picker v-model:value="item.date" />
|
|
</a-space>
|
|
</a-form-item>
|
|
|
|
<a-form-item>
|
|
<label class="color-3">实施内容与目标</label>
|
|
<a-textarea v-model:value="item.remark" placeholder="实施内容与目标" />
|
|
</a-form-item>
|
|
</div>
|
|
</div>
|
|
</a-form-item>
|
|
|
|
<a-form-item>
|
|
<label class="color-3">主要技术指标</label>
|
|
<a-textarea v-model:value="topicMeetFormData.technicalIndicator" placeholder="主要技术指标" />
|
|
</a-form-item>
|
|
|
|
<a-form-item>
|
|
<label class="color-3">经济指标</label>
|
|
<a-textarea v-model:value="topicMeetFormData.economicIndicators" placeholder="经济指标" />
|
|
</a-form-item>
|
|
|
|
<a-form-item>
|
|
<label class="color-3">社会效益</label>
|
|
<a-textarea v-model:value="topicMeetFormData.socialBenefit" placeholder="社会效益" />
|
|
</a-form-item>
|
|
|
|
<a-form-item>
|
|
<label class="color-3">验收内容</label>
|
|
<a-checkbox-group v-model:value="topicMeetFormData.checkContentList">
|
|
<a-row>
|
|
<a-col :span="5">
|
|
<a-checkbox value="1"><span class="color-6">1、工作报告</span></a-checkbox>
|
|
</a-col>
|
|
<a-col :span="6">
|
|
<a-checkbox value="2"><span class="color-6">2、技术报告</span></a-checkbox>
|
|
</a-col>
|
|
<a-col :span="6">
|
|
<a-checkbox value="3"><span class="color-6">3、计算机软件</span></a-checkbox>
|
|
</a-col>
|
|
<a-col :span="7">
|
|
<a-checkbox value="4"><span class="color-6">4、生物品种</span></a-checkbox>
|
|
</a-col>
|
|
<a-col :span="5">
|
|
<a-checkbox value="5"><span class="color-6">5、样品或样机</span></a-checkbox>
|
|
</a-col>
|
|
<a-col :span="6">
|
|
<a-checkbox value="6"><span class="color-6">6、成套技术设备</span></a-checkbox>
|
|
</a-col>
|
|
<a-col :span="6">
|
|
<a-checkbox value="7"><span class="color-6">7、科技论文或著作</span></a-checkbox>
|
|
</a-col>
|
|
<a-col :span="7">
|
|
<a-checkbox value="8"><span class="color-6">8、科技报告收录证书(必选)</span></a-checkbox>
|
|
</a-col>
|
|
</a-row>
|
|
</a-checkbox-group>
|
|
</a-form-item>
|
|
|
|
<!-- 自定义 -->
|
|
<div class="flex items-center cursor-pointer" style="margin-bottom: 20px" @click="addDefined">
|
|
<PlusCircleOutlined style="color: #1890ff; font-size: 16px" /><span class="color-3" style="margin-left: 8px">自定义</span>
|
|
</div>
|
|
|
|
<div class="form-item-son" style="padding-left: 16px">
|
|
<div v-for="(item, index) in planTaskDefinedList" :key="index">
|
|
<a-form-item>
|
|
<label class="color-3">自定义名称</label>
|
|
<a-input v-model:value="item.key" placeholder="自定义名称" />
|
|
</a-form-item>
|
|
|
|
<a-form-item>
|
|
<label class="color-3">自定义内容</label>
|
|
<a-textarea v-model:value="item.value" placeholder="自定义内容" />
|
|
</a-form-item>
|
|
</div>
|
|
</div>
|
|
|
|
<a-form-item>
|
|
<label class="color-3">计划任务书</label>
|
|
<a-upload-dragger
|
|
v-model:fileList="fileList"
|
|
name="param"
|
|
:multiple="true"
|
|
:action="action"
|
|
:headers="headers"
|
|
:accept="'.pdf'"
|
|
@change="handleChange"
|
|
>
|
|
<p class="ant-upload-drag-icon">
|
|
<inbox-outlined></inbox-outlined>
|
|
</p>
|
|
<p class="ant-upload-text color-3 font-14">点击或拖拽文件到区域内上传交付物</p>
|
|
<p class="ant-upload-hint color-c">格式:pdf</p>
|
|
</a-upload-dragger>
|
|
</a-form-item>
|
|
|
|
<a-form-item class="text-right">
|
|
<a-button type="primary" html-type="submit" @click="onSubmit">上传计划任务书</a-button>
|
|
</a-form-item>
|
|
</a-form>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, computed } from 'vue';
|
|
import { useStore } from 'vuex';
|
|
import { InboxOutlined, PlusCircleOutlined } from '@ant-design/icons-vue';
|
|
import { uploadImg, memberQuery, savePlanTask, getPlanTask } from 'apis';
|
|
import dayjs from 'dayjs';
|
|
import { message } from 'ant-design-vue';
|
|
|
|
const store = useStore();
|
|
const formRef = ref(null);
|
|
const projectInfo = computed(() => store.state.projects.project); // 当前选择项目信息
|
|
|
|
const projectId = computed(() => store.getters['projects/projectId']);
|
|
const token = computed(() => store.getters['user/token']);
|
|
const headers = { Authorization: `Bearer ${token.value}` };
|
|
const action = uploadImg;
|
|
const fileList = ref([]);
|
|
|
|
const topicMeetFormData = ref({
|
|
projectId: projectInfo.value.id,
|
|
name: '',
|
|
date: [],
|
|
startTime: '',
|
|
endTime: '',
|
|
memberId: '',
|
|
technicalIndicator: '',
|
|
economicIndicators: '',
|
|
socialBenefit: '',
|
|
checkContentList: [],
|
|
fileList: [],
|
|
planTaskStageList: [],
|
|
planTaskDefinedList: [],
|
|
});
|
|
|
|
const options = ref([]);
|
|
|
|
const planTaskStageList = ref([{ date: [], stageStartTime: '', stageEndTime: '', remark: '' }]);
|
|
const planTaskDefinedList = ref([]);
|
|
|
|
checkPlanTask(); // 查看任务计划书
|
|
|
|
getList(); // 获取成员列表
|
|
|
|
const handleSearch = async value => {
|
|
await getList(value); // 获取成员列表
|
|
};
|
|
|
|
const filterOption = (input, option) => {
|
|
return option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
|
};
|
|
|
|
const handleChange = info => {
|
|
const resFileList = [...info.fileList];
|
|
|
|
// 数组去重
|
|
const arr = ref([]);
|
|
resFileList.forEach(file => {
|
|
let num = -1;
|
|
|
|
arr.value.forEach((item, index) => {
|
|
if (file.name === item.name) {
|
|
num = index;
|
|
}
|
|
});
|
|
if (num > -1) {
|
|
arr.value.splice(num, 1);
|
|
}
|
|
|
|
arr.value.push(file);
|
|
});
|
|
|
|
// 更改上传文件路径
|
|
arr.value = arr.value.map(file => {
|
|
if (file.response) {
|
|
file.url = file.response.data.filePath;
|
|
file.id = file.response.data.fileId;
|
|
}
|
|
|
|
return file;
|
|
});
|
|
|
|
fileList.value = arr.value;
|
|
};
|
|
|
|
// 查看任务计划书
|
|
async function checkPlanTask() {
|
|
try {
|
|
const params = { param: { projectId: projectId.value } };
|
|
const data = await getPlanTask(params);
|
|
if (data.checkContent) data.checkContentList = data.checkContent.split(',');
|
|
|
|
store.commit('layout/setFirPlanTime', { startTime: data.startTime, endTime: data.endTime });
|
|
|
|
data.date = [];
|
|
if (data.startTime) {
|
|
const start = dayjs(Number(data.startTime));
|
|
const end = dayjs(Number(data.endTime));
|
|
data.date = [start, end];
|
|
}
|
|
|
|
data.projectId = data.id;
|
|
topicMeetFormData.value = data;
|
|
|
|
planTaskDefinedList.value = data.planTaskDefinedList;
|
|
|
|
data.planTaskStageList.forEach(item => {
|
|
item.date = [];
|
|
if (item.stageStartTime) {
|
|
const planStart = dayjs(Number(item.stageStartTime));
|
|
const planEnd = dayjs(Number(item.stageEndTime));
|
|
item.date = [planStart, planEnd];
|
|
}
|
|
});
|
|
planTaskStageList.value = data.planTaskStageList;
|
|
|
|
const fileArr = [];
|
|
data.fileList.forEach(item => {
|
|
const fileInfo = {
|
|
id: item.fileId,
|
|
name: item.fileName,
|
|
url: item.filePath,
|
|
status: 'done',
|
|
};
|
|
|
|
fileArr.push(fileInfo);
|
|
});
|
|
fileList.value = fileArr;
|
|
} catch (error) {
|
|
message.info(error);
|
|
throw new Error(error);
|
|
}
|
|
}
|
|
|
|
// 获取成员列表
|
|
async function getList(name) {
|
|
try {
|
|
const params = { param: { projectId: projectId.value, name } };
|
|
const data = await memberQuery(params);
|
|
store.commit('task/setMembers', data);
|
|
options.value = [];
|
|
|
|
data.forEach(item => {
|
|
const obj = {
|
|
label: item.memberName,
|
|
value: item.memberId,
|
|
};
|
|
|
|
options.value.push(obj);
|
|
});
|
|
} catch (error) {
|
|
message.info(error);
|
|
throw new Error(error);
|
|
}
|
|
}
|
|
|
|
// 添加实施内容与目标
|
|
function addMilestones() {
|
|
planTaskStageList.value.push({ date: [], stageStartTime: '', stageEndTime: '', remark: '' });
|
|
}
|
|
|
|
// 添加自定义内容
|
|
function addDefined() {
|
|
planTaskDefinedList.value.push({ key: '', value: '' });
|
|
}
|
|
|
|
const onSubmit = async () => {
|
|
fileList.value.forEach(item => {
|
|
const obj = {
|
|
fileId: item.id,
|
|
fileName: item.name,
|
|
filePath: item.url,
|
|
};
|
|
|
|
topicMeetFormData.value.fileList.push(obj);
|
|
});
|
|
|
|
if (topicMeetFormData.value.date) {
|
|
topicMeetFormData.value.date.forEach((item, index) => {
|
|
if (index === 0) {
|
|
topicMeetFormData.value.startTime = dayjs(item).format('x');
|
|
} else {
|
|
topicMeetFormData.value.endTime = dayjs(item).format('x');
|
|
}
|
|
});
|
|
}
|
|
|
|
topicMeetFormData.value.planTaskStageList = [];
|
|
planTaskStageList.value.forEach(item => {
|
|
const obj = {
|
|
stageStartTime: '',
|
|
stageEndTime: '',
|
|
remark: item.remark,
|
|
};
|
|
|
|
if (item.date.length > 0) {
|
|
item.date.forEach((val, key) => {
|
|
if (key === 0) {
|
|
obj.stageStartTime = dayjs(val).format('x');
|
|
} else {
|
|
obj.stageEndTime = dayjs(val).format('x');
|
|
}
|
|
});
|
|
|
|
if (obj.stageStartTime < topicMeetFormData.value.startTime) {
|
|
message.info('阶段任务开始时间不能小于项目起始时间');
|
|
return false;
|
|
}
|
|
if (obj.stageEndTime > topicMeetFormData.value.endTime) {
|
|
message.info('阶段任务结束时间不能小于项目终止时间');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
topicMeetFormData.value.planTaskStageList.push(obj);
|
|
});
|
|
|
|
topicMeetFormData.value.planTaskDefinedList = planTaskDefinedList.value;
|
|
|
|
const params = { param: topicMeetFormData.value };
|
|
|
|
await savePlanTask(params);
|
|
projectInfo.value.name = topicMeetFormData.value.name;
|
|
store.commit('projects/setProject', projectInfo.value);
|
|
store.commit('layout/setRefreshProjects');
|
|
checkPlanTask();
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
.task-detail {
|
|
background-color: #fff;
|
|
}
|
|
|
|
.ant-col {
|
|
margin-top: 10px;
|
|
}
|
|
|
|
.ant-col:nth-child(-n + 4) {
|
|
margin-top: 2px;
|
|
}
|
|
</style>
|
|
|