|
@@ -1,54 +1,159 @@
|
|
|
<template>
|
|
|
- <div style="margin-top: 14%;">
|
|
|
- <el-divider content-position="right">
|
|
|
- <el-tooltip class="item" effect="dark" content="温馨提示:点击添加可以新建里程碑" placement="bottom-end">
|
|
|
- <el-button style="z-index: 999999;" size="mini" type="primary" icon="el-icon-plus" circle @click="details_projectMilepost" />
|
|
|
- </el-tooltip>
|
|
|
- </el-divider>
|
|
|
- <ul class="time-line">
|
|
|
- <li v-for="(item, index) in valuesList" :key="index">
|
|
|
- <i>
|
|
|
+ <div>
|
|
|
+ <div style="margin-top: 14%;">
|
|
|
+ <el-divider content-position="right">
|
|
|
+ <el-tooltip class="item" effect="dark" content="温馨提示:点击添加可以新建里程碑" placement="bottom-end">
|
|
|
+ <el-button style="z-index: 999999;" size="mini" type="primary" icon="el-icon-plus" circle @click="details_projectMilepost" />
|
|
|
+ </el-tooltip>
|
|
|
+ </el-divider>
|
|
|
+ <ul class="time-line">
|
|
|
+ <li v-for="(item, index) in valuesList" :key="index">
|
|
|
+ <i>
|
|
|
+ <div>
|
|
|
+ <el-popover class="popover" placement="top" width="200" trigger="click" style="border-radius: 10px;">
|
|
|
+ <p style="text-align: center">
|
|
|
+ <el-button size="mini" @click="dalete_Milepost = true">删除</el-button>
|
|
|
+ <el-button size="mini" type="primary" @click="query_date">编辑</el-button>
|
|
|
+ </p>
|
|
|
+ <b slot="reference" @click="get_Milepost(item)">一 </b>
|
|
|
+ </el-popover>
|
|
|
+ </div>
|
|
|
+ </i>
|
|
|
<div>
|
|
|
- <el-popover class="popover" placement="top" width="200" trigger="click" style="border-radius: 10px;">
|
|
|
- <p style="text-align: center">
|
|
|
- <el-button size="mini" @click="dalete_Milepost = true">删除</el-button>
|
|
|
- <el-button size="mini" type="primary" @click="query_date">编辑</el-button>
|
|
|
- </p>
|
|
|
- <b slot="reference" @click="get_Milepost(item)">一 </b>
|
|
|
- </el-popover>
|
|
|
+ <p style="white-space:pre-line;"><pre class="description">{{ item.description }}</pre></p>
|
|
|
+ <span style="font-size: 16px; color: #333B4A; font-weight: 500;">{{ item.title | ellipsis(20) }}</span><br>
|
|
|
+ <span style="font-size: 12px; color: #9B9B9B;">{{ item.date | dateStr }}</span>
|
|
|
</div>
|
|
|
- </i>
|
|
|
- <div>
|
|
|
- <p style="white-space:pre-line;"><pre class="description">{{ item.description }}</pre></p>
|
|
|
- <span style="font-size: 16px; color: #333B4A; font-weight: 500;">{{ item.title | ellipsis(20) }}</span><br>
|
|
|
- <span style="font-size: 12px; color: #9B9B9B;">{{ item.date | dateStr }}</span>
|
|
|
- </div>
|
|
|
- </li>
|
|
|
- </ul>
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </div>
|
|
|
+ <el-dialog :visible.sync="dialogFormVisible" class="dialog" :close-on-click-modal="false" @close="close_dialog">
|
|
|
+ <div style="display:flex;align-items: center;margin:0 0 30px 10px;">
|
|
|
+ <div class="titIcon" />
|
|
|
+ <div style="width:150px;height:20px;font-size:18px;font-family:MicrosoftYaHei;color:rgba(51,59,74,1);margin-left:6px">{{ title_name }}</div>
|
|
|
+ </div>
|
|
|
+ <el-form
|
|
|
+ ref="form"
|
|
|
+ :model="form"
|
|
|
+ :rules="title_name === '新建里程碑'? formRules :formRules1"
|
|
|
+ :label-width="formLabelWidth1"
|
|
|
+ label-position="right"
|
|
|
+ >
|
|
|
+ <el-form-item label="标题" prop="title">
|
|
|
+ <el-input v-model="form.title" autocomplete="off" placeholder="请输入标题" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="时间" prop="mtime">
|
|
|
+ <el-date-picker
|
|
|
+ v-model="form.mtime"
|
|
|
+ type="date"
|
|
|
+ value-format="yyyy-MM-dd"
|
|
|
+ placeholder="请选择日期"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="详情">
|
|
|
+ <el-input
|
|
|
+ v-model="form.description"
|
|
|
+ class="details"
|
|
|
+ rows="3"
|
|
|
+ maxlength="200"
|
|
|
+ type="textarea"
|
|
|
+ placeholder="请输入详情内容,详情内容不可超过200字符"
|
|
|
+ show-word-limit
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
+ <el-button @click="dialogFormVisible = false">关 闭</el-button>
|
|
|
+ <el-button type="primary" @click="Milepost_Submission(form)">提 交</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ <el-dialog :visible.sync="dalete_Milepost" width="30%" center :close-on-click-modal="false">
|
|
|
+ <div align="center">确定要删除 {{ get_Milepost_data.title }} 项目吗?</div>
|
|
|
+ <span slot="footer" class="dialog-footer">
|
|
|
+ <el-button @click="dalete_Milepost = false">关 闭</el-button>
|
|
|
+ <el-button type="primary" @click="select_Milepost">确 定</el-button>
|
|
|
+ </span>
|
|
|
+ </el-dialog>
|
|
|
</div>
|
|
|
</template>
|
|
|
<script>
|
|
|
const _ = require('lodash')
|
|
|
+import {
|
|
|
+ mileStoneCreate,
|
|
|
+ mileStoneUpdate,
|
|
|
+ mileStoneDelete
|
|
|
+} from '@/api/projectIndex'
|
|
|
export default {
|
|
|
+ filters: {
|
|
|
+ dateStr(value) {
|
|
|
+ if (!value) return ''
|
|
|
+ const date = value.split('T')
|
|
|
+ return date[0]
|
|
|
+ },
|
|
|
+ ellipsis(value, num) {
|
|
|
+ if (!value) return ''
|
|
|
+ if (value.length > num) {
|
|
|
+ return value.slice(0, num) + '...'
|
|
|
+ }
|
|
|
+ return value
|
|
|
+ }
|
|
|
+ },
|
|
|
props: {
|
|
|
valuesList: {
|
|
|
- type: String,
|
|
|
- default: '',
|
|
|
- required: false
|
|
|
- },
|
|
|
- size: {
|
|
|
- type: String,
|
|
|
- default: 'small',
|
|
|
+ type: Array,
|
|
|
+ default: () => [],
|
|
|
required: false
|
|
|
}
|
|
|
},
|
|
|
data() {
|
|
|
+ const validatePass = (rule, value, callback) => {
|
|
|
+ if (value === undefined || value === '') {
|
|
|
+ callback(new Error('标题不能为空'))
|
|
|
+ } else {
|
|
|
+ if (this.form.title !== '') {
|
|
|
+ this.project_Milepost.map(item => {
|
|
|
+ if (item.title === this.form.title) {
|
|
|
+ callback(new Error('该里程碑标题已存在,请重新设置'))
|
|
|
+ } else {
|
|
|
+ this.$refs.form.validateField('checkPass')
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ callback()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const validate = (rule, value, callback) => {
|
|
|
+ if (value === undefined || value === '') {
|
|
|
+ callback(new Error('时间不能为空'))
|
|
|
+ } else {
|
|
|
+ if (this.form.mtime !== '') {
|
|
|
+ this.project_Milepost.map(item => {
|
|
|
+ if (item.mtime === this.form.mtime) {
|
|
|
+ callback(new Error('该日期已设置其他里程碑'))
|
|
|
+ } else {
|
|
|
+ this.$refs.form.validateField('checkPass')
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ callback()
|
|
|
+ }
|
|
|
+ }
|
|
|
return {
|
|
|
inputValue: '',
|
|
|
dalete_Milepost: false, // 删除里程碑
|
|
|
title_name: '', // 里程碑title
|
|
|
dialogFormVisible: false,
|
|
|
- get_Milepost_data: {} // 点击原点数据
|
|
|
+ get_Milepost_data: {}, // 点击原点数据
|
|
|
+ formLabelWidth1: '60px',
|
|
|
+ formRules1: {
|
|
|
+ title: [{ required: true, message: '标题不能为空', trigger: 'blur' }],
|
|
|
+ mtime: [{ required: true, message: '时间不能为空', trigger: 'blur' }]
|
|
|
+ },
|
|
|
+ formRules: {
|
|
|
+ title: [{ required: true, validator: validatePass, trigger: 'blur' }],
|
|
|
+ mtime: [{ required: true, validator: validate, trigger: 'blur' }]
|
|
|
+ },
|
|
|
+ form: {}
|
|
|
}
|
|
|
},
|
|
|
computed: {
|
|
@@ -69,12 +174,72 @@ export default {
|
|
|
// 点击原点
|
|
|
this.get_Milepost_data = _.cloneDeep(e)
|
|
|
},
|
|
|
+ details_projectMilepost() {
|
|
|
+ // 创建里程碑
|
|
|
+ this.title_name = '创建里程碑'
|
|
|
+ this.form = {}
|
|
|
+ this.dialogFormVisible = true
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.$refs['form'].clearValidate()
|
|
|
+ })
|
|
|
+ },
|
|
|
query_date() {
|
|
|
// 编辑里程碑
|
|
|
this.title_name = '编辑里程碑'
|
|
|
this.dialogFormVisible = true
|
|
|
this.form = this.get_Milepost_data
|
|
|
},
|
|
|
+ close_dialog() {
|
|
|
+ this.$emit('close_dialog')
|
|
|
+ },
|
|
|
+ Milepost_Submission(e) {
|
|
|
+ // 里程碑(提交)
|
|
|
+ this.$refs['form'].validate(valid => {
|
|
|
+ if (valid) {
|
|
|
+ const milestone = {
|
|
|
+ projectId: this.$route.query.id,
|
|
|
+ id: e.id,
|
|
|
+ title: e.title,
|
|
|
+ mtime: e.mtime,
|
|
|
+ description: e.description
|
|
|
+ }
|
|
|
+ const user = {
|
|
|
+ name: localStorage.getItem('realname'),
|
|
|
+ ename: localStorage.getItem('username'),
|
|
|
+ id: ''
|
|
|
+ }
|
|
|
+ if (this.title_name === '创建里程碑') {
|
|
|
+ this.mileStoneCreate(milestone, user)
|
|
|
+ } else if (this.title_name === '编辑里程碑') {
|
|
|
+ this.mileStoneUpdate(milestone, user)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ async mileStoneCreate(milestone, user) {
|
|
|
+ const res = await mileStoneCreate({ milestone, user })
|
|
|
+ if (res.code === 200) {
|
|
|
+ this.$message({ message: res.msg, type: 'success', duration: 1000, offset: 150 })
|
|
|
+ }
|
|
|
+ this.dialogFormVisible = false
|
|
|
+ this.change()
|
|
|
+ },
|
|
|
+ async mileStoneUpdate(milestone, user) {
|
|
|
+ const res = await mileStoneUpdate({ milestone, user })
|
|
|
+ if (res.code === 200) {
|
|
|
+ this.$message({ message: res.msg, type: 'success', duration: 1000, offset: 150 })
|
|
|
+ }
|
|
|
+ this.dialogFormVisible = false
|
|
|
+ this.change()
|
|
|
+ },
|
|
|
+ async select_Milepost() {
|
|
|
+ const res = await mileStoneDelete(this.get_Milepost_data.id, {})
|
|
|
+ if (res.code === 200) {
|
|
|
+ this.$message({ message: res.msg, type: 'success', duration: 1000, offset: 150 })
|
|
|
+ }
|
|
|
+ this.dalete_Milepost = false
|
|
|
+ this.change()
|
|
|
+ },
|
|
|
change() {
|
|
|
this.$emit('update:valuesList', this.inputValue)
|
|
|
this.$emit('change', this.inputValue)
|
|
@@ -83,6 +248,9 @@ export default {
|
|
|
}
|
|
|
</script>
|
|
|
<style scoped lang="scss">
|
|
|
+/deep/.el-divider--horizontal {
|
|
|
+ margin: 0;
|
|
|
+}
|
|
|
.time-line {
|
|
|
list-style-type: none;
|
|
|
padding: 0px;
|
|
@@ -96,7 +264,7 @@ export default {
|
|
|
position: relative;
|
|
|
text-align: center;
|
|
|
width: 24%;
|
|
|
- padding-top: 5%;
|
|
|
+ padding-top: 4%;
|
|
|
margin: 0 1%;
|
|
|
i div {
|
|
|
position: absolute;
|