| | |
| | | v-model="currentDate" |
| | | :type="datePickerType" |
| | | placeholder="选择日期" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 180px; margin-left: 10px" |
| | | @change="handleDateChange" |
| | | /> |
| | |
| | | <div class="right-actions"> |
| | | <el-button type="primary" @click="handleAddPlan">新增计划</el-button> |
| | | <el-button @click="handleExport">导出计划</el-button> |
| | | <el-button @click="handleShare">共享计划</el-button> |
| | | <!-- <el-button @click="handleShare">共享计划@</el-button> --> |
| | | </div> |
| | | </div> |
| | | |
| | |
| | | <span>{{ getCurrentLevelText() }} - {{ getCurrentPeriodText() }}</span> |
| | | <div> |
| | | <el-button size="small" @click="handleRefresh">刷新</el-button> |
| | | <el-button size="small" @click="handleFilter">筛选</el-button> |
| | | <!-- <el-button size="small" @click="handleFilter">筛选@</el-button> --> |
| | | </div> |
| | | </div> |
| | | </template> |
| | |
| | | <div class="plan-actions"> |
| | | <el-button size="small" @click="handleEditPlan(plan)">编辑</el-button> |
| | | <el-button size="small" @click="handleViewDetail(plan)">详情</el-button> |
| | | <el-dropdown @command="handleMoreAction"> |
| | | <el-dropdown @command="(command) => handleMoreAction(plan, command)"> |
| | | <el-button size="small"> |
| | | 更多<el-icon class="el-icon--right"><ArrowDown /></el-icon> |
| | | </el-button> |
| | | <template #dropdown> |
| | | <el-dropdown-menu> |
| | | <el-dropdown-item command="share">共享</el-dropdown-item> |
| | | <!-- <el-dropdown-item command="share">共享@</el-dropdown-item> --> |
| | | <el-dropdown-item command="copy">复制</el-dropdown-item> |
| | | <el-dropdown-item command="delete" divided>删除</el-dropdown-item> |
| | | </el-dropdown-menu> |
| | |
| | | <!-- 新增/编辑计划对话框 --> |
| | | <el-dialog |
| | | v-model="planDialogVisible" |
| | | :title="dialogTitle" |
| | | :title="operationType === 'add' ? '发布计划' : '编辑计划'" |
| | | width="600px" |
| | | @close="handleDialogClose" |
| | | > |
| | |
| | | <el-date-picker |
| | | v-model="planForm.startDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | placeholder="选择开始时间" |
| | | style="width: 100%" |
| | | /> |
| | |
| | | <el-date-picker |
| | | v-model="planForm.endDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | placeholder="选择结束时间" |
| | | style="width: 100%" |
| | | /> |
| | |
| | | <el-option label="低" value="low" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="标签"> |
| | | <!-- <el-form-item label="标签"> |
| | | <el-input v-model="planForm.tags" placeholder="请输入标签,用逗号分隔" /> |
| | | </el-form-item> --> |
| | | <el-form-item label="标签" prop="tags"> |
| | | <!-- <el-checkbox-group v-model="planForm.tags"> |
| | | <el-checkbox label="all"></el-checkbox> |
| | | <el-checkbox label="manager">管理层</el-checkbox> |
| | | <el-checkbox label="hr">人事部门</el-checkbox> |
| | | <el-checkbox label="finance">财务部门</el-checkbox> |
| | | <el-checkbox label="tech">技术部门</el-checkbox> |
| | | </el-checkbox-group> --> |
| | | <el-select |
| | | v-model="planForm.tags" |
| | | multiple |
| | | placeholder="请选择标签" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="dept in departments" |
| | | :key="dept" |
| | | :label="dept" |
| | | :value="dept" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="状态" prop="status"> |
| | | <el-select v-model="planForm.status" placeholder="选择状态" style="width: 100%"> |
| | | <el-option label="未开始" value="not_started" /> |
| | | <el-option label="进行中" value="in_progress" /> |
| | | <el-option label="已完成" value="completed" /> |
| | | <el-option label="已暂停" value="paused" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="进度" prop="progress"> |
| | | <el-input-number |
| | | v-model="planForm.progress" |
| | | min="0" |
| | | max="100" |
| | | step="1" |
| | | placeholder="请输入进度" |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | <!-- 计划详情对话框 --> |
| | | <el-dialog v-model="showPlanDetailDialog" title="计划详情" width="700px"> |
| | | <div v-if="currentPlanDetail" class="mb10"> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions-item label="计划标题">{{ currentPlanDetail.title }}</el-descriptions-item> |
| | | <el-descriptions-item label="计划描述">{{ currentPlanDetail.description }}</el-descriptions-item> |
| | | <el-descriptions-item label="计划级别">{{ getCurrentLevelText(currentPlanDetail.level) }}</el-descriptions-item> |
| | | <el-descriptions-item label="时间周期">{{ getCurrentPeriodText(currentPlanDetail.period) }}</el-descriptions-item> |
| | | <el-descriptions-item label="开始时间">{{ currentPlanDetail.startDate }}</el-descriptions-item> |
| | | <el-descriptions-item label="结束时间">{{ currentPlanDetail.endDate }}</el-descriptions-item> |
| | | <el-descriptions-item label="负责人">{{ currentPlanDetail.assignee }}</el-descriptions-item> |
| | | <el-descriptions-item label="优先级">{{ getPriorityText(currentPlanDetail.priority) }}</el-descriptions-item> |
| | | <el-descriptions-item label="标签">{{ currentPlanDetail.tags.join(', ') }}</el-descriptions-item> |
| | | <el-descriptions-item label="状态">{{ getStatusText(currentPlanDetail.status) }}</el-descriptions-item> |
| | | <el-descriptions-item label="进度">{{ currentPlanDetail.progress }}%</el-descriptions-item> |
| | | </el-descriptions> |
| | | </div> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, computed, onMounted } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | const { proxy } = getCurrentInstance(); |
| | | import { |
| | | User, |
| | | UserFilled, |
| | |
| | | Flag, |
| | | ArrowDown |
| | | } from '@element-plus/icons-vue' |
| | | import { listDutyPlan, addDutyPlan, updateDutyPlan, delDutyPlan,NumDutyPlan,exportDutyPlan } from '@/api/collaborativeApproval/planTemplate.js' |
| | | |
| | | // 响应式数据 |
| | | const operationType = ref('add') |
| | | const currentLevel = ref('personal') |
| | | const currentPeriod = ref('week') |
| | | const currentDate = ref(new Date()) |
| | | const planDialogVisible = ref(false) |
| | | const dialogTitle = ref('新增计划') |
| | | const planFormRef = ref() |
| | | const showPlanDetailDialog = ref(false) |
| | | const currentPlanDetail = ref(null) |
| | | |
| | | // 表单数据 |
| | | const planForm = reactive({ |
| | | id: '', |
| | | title: '', |
| | | description: '', |
| | | level: 'personal', |
| | |
| | | endDate: '', |
| | | assignee: '', |
| | | priority: 'medium', |
| | | tags: '' |
| | | tags: [], |
| | | status: '', |
| | | progress: 0 |
| | | }) |
| | | |
| | | // 表单验证规则 |
| | |
| | | assignee: [{ required: true, message: '请输入负责人', trigger: 'blur' }], |
| | | priority: [{ required: true, message: '请选择优先级', trigger: 'change' }] |
| | | } |
| | | |
| | | const departments = ["产品", "分析", "调研",'技术', '架构', '设计','市场', '推广', '营销']; |
| | | // 概览数据 |
| | | const overviewData = reactive({ |
| | | personal: { total: 12, completion: 75 }, |
| | | group: { total: 8, completion: 60 }, |
| | | department: { total: 15, completion: 45 }, |
| | | company: { total: 6, completion: 30 } |
| | | personal: { total: 0, completion: 0 }, |
| | | group: { total: 0, completion: 0 }, |
| | | department: { total: 0, completion: 0 }, |
| | | company: { total: 0, completion: 0 } |
| | | }) |
| | | |
| | | // 计划列表数据 |
| | | const planList = ref([ |
| | | { |
| | | id: 1, |
| | | title: '产品需求分析', |
| | | description: '对新产品进行详细的需求分析和市场调研,制定产品规划方案', |
| | | level: 'personal', |
| | | period: 'week', |
| | | startDate: '2025-01-15', |
| | | endDate: '2025-01-21', |
| | | assignee: '陈志强', |
| | | priority: 'high', |
| | | status: 'in_progress', |
| | | progress: 80, |
| | | tags: ['产品', '分析', '调研'] |
| | | }, |
| | | { |
| | | id: 2, |
| | | title: '技术架构设计', |
| | | description: '设计系统技术架构,包括数据库设计、接口设计等', |
| | | level: 'group', |
| | | period: 'month', |
| | | startDate: '2025-01-01', |
| | | endDate: '2025-01-31', |
| | | assignee: '刘雅婷', |
| | | priority: 'high', |
| | | status: 'completed', |
| | | progress: 100, |
| | | tags: ['技术', '架构', '设计'] |
| | | }, |
| | | { |
| | | id: 3, |
| | | title: '市场推广计划', |
| | | description: '制定年度市场推广策略和营销计划', |
| | | level: 'department', |
| | | period: 'year', |
| | | startDate: '2025-01-01', |
| | | endDate: '2025-12-31', |
| | | assignee: '王建国', |
| | | priority: 'medium', |
| | | status: 'not_started', |
| | | progress: 0, |
| | | tags: ['市场', '推广', '营销'] |
| | | }, |
| | | { |
| | | id: 4, |
| | | title: '团队建设活动', |
| | | description: '组织团队建设活动,提升团队凝聚力和协作效率', |
| | | level: 'company', |
| | | period: 'month', |
| | | startDate: '2025-01-15', |
| | | endDate: '2025-02-15', |
| | | assignee: '赵丽华', |
| | | priority: 'low', |
| | | status: 'in_progress', |
| | | progress: 30, |
| | | tags: ['团队', '建设', '活动'] |
| | | } |
| | | ]) |
| | | const planList = ref([]) |
| | | |
| | | // 计算属性 |
| | | const datePickerType = computed(() => { |
| | |
| | | // 方法 |
| | | const handleLevelChange = (value) => { |
| | | console.log('计划级别变更:', value) |
| | | getPlanList() |
| | | // 这里可以根据级别筛选数据 |
| | | } |
| | | |
| | | const handlePeriodChange = (value) => { |
| | | console.log('时间周期变更:', value) |
| | | getPlanList() |
| | | // 这里可以根据周期筛选数据 |
| | | } |
| | | |
| | | const handleDateChange = (value) => { |
| | | console.log('日期变更:', value) |
| | | getPlanList() |
| | | // 这里可以根据日期筛选数据 |
| | | } |
| | | |
| | | const handleAddPlan = () => { |
| | | operationType.value = 'add' |
| | | dialogTitle.value = '新增计划' |
| | | planDialogVisible.value = true |
| | | // 重置表单 |
| | |
| | | planForm.level = 'personal' |
| | | planForm.period = 'week' |
| | | planForm.priority = 'medium' |
| | | planForm.status = 'not_started' |
| | | planForm.progress = 0 |
| | | } |
| | | |
| | | const handleEditPlan = (plan) => { |
| | | operationType.value = 'edit' |
| | | dialogTitle.value = '编辑计划' |
| | | planDialogVisible.value = true |
| | | // 填充表单数据 |
| | | Object.keys(planForm).forEach(key => { |
| | | if (key === 'tags') { |
| | | planForm[key] = plan[key].join(', ') |
| | | } else { |
| | | planForm[key] = plan[key] |
| | | } |
| | | }) |
| | | Object.assign(planForm, plan) |
| | | // // 填充表单数据 |
| | | // Object.keys(planForm).forEach(key => { |
| | | // if (key === 'tags') { |
| | | // planForm[key] = plan[key].join(', ') |
| | | // } else { |
| | | // planForm[key] = plan[key] |
| | | // } |
| | | // }) |
| | | } |
| | | |
| | | const handleViewDetail = (plan) => { |
| | | ElMessage.info(`查看计划详情: ${plan.title}`) |
| | | currentPlanDetail.value = plan |
| | | showPlanDetailDialog.value = true |
| | | // ElMessage.info(`查看计划详情: ${plan.title}`) |
| | | } |
| | | |
| | | const handleMoreAction = (command) => { |
| | | const handleMoreAction = async(plan,command) => { |
| | | let ids = []; |
| | | ids.push(plan.id); |
| | | console.log("ids",ids) |
| | | switch (command) { |
| | | case 'share': |
| | | ElMessage.success('计划已共享') |
| | | break |
| | | case 'copy': |
| | | ElMessage.success('计划已复制') |
| | | const knowledgeText = ` |
| | | 计划标题:${plan.title} |
| | | 计划描述:${plan.description} |
| | | 计划级别:${getCurrentLevelText(plan.level)} |
| | | 时间周期:${getCurrentPeriodText(plan.period)} |
| | | 开始时间:${plan.startDate} |
| | | 结束时间:${plan.endDate} |
| | | 负责人:${plan.assignee} |
| | | 优先级:${getPriorityText(plan.priority)} |
| | | 标签:${plan.tags.join(', ')} |
| | | 状态:${getStatusText(plan.status)} |
| | | 进度:${plan.progress}% |
| | | `.trim(); |
| | | |
| | | // 复制到剪贴板 |
| | | navigator.clipboard.writeText(knowledgeText).then(() => { |
| | | ElMessage.success("知识内容已复制到剪贴板"); |
| | | }).catch(() => { |
| | | ElMessage.error("复制失败,请手动复制"); |
| | | }); |
| | | // ElMessage.success('计划已复制') |
| | | break |
| | | case 'delete': |
| | | ElMessageBox.confirm('确定要删除这个计划吗?', '提示', { |
| | |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | ElMessage.success('计划已删除') |
| | | |
| | | delDutyPlan(ids).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success('计划已删除') |
| | | ids.value = []; |
| | | getPlanList() |
| | | } |
| | | }) |
| | | }) |
| | | break |
| | | } |
| | | } |
| | | |
| | | // |
| | | const handleSavePlan = async () => { |
| | | try { |
| | | await planFormRef.value.validate() |
| | | ElMessage.success('计划保存成功') |
| | | planDialogVisible.value = false |
| | | if (operationType.value === 'add') { |
| | | addDutyPlan(planForm).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success('计划保存成功') |
| | | planDialogVisible.value = false |
| | | } |
| | | getPlanList() |
| | | }) |
| | | } else { |
| | | |
| | | updateDutyPlan(planForm).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success('计划保存成功') |
| | | planDialogVisible.value = false |
| | | } |
| | | getPlanList() |
| | | }) |
| | | } |
| | | } catch (error) { |
| | | console.log('表单验证失败:', error) |
| | | } |
| | |
| | | } |
| | | |
| | | const handleRefresh = () => { |
| | | ElMessage.success('数据已刷新') |
| | | getPlanList() |
| | | // ElMessage.success('数据已刷新') |
| | | } |
| | | |
| | | const handleFilter = () => { |
| | |
| | | } |
| | | |
| | | const handleExport = () => { |
| | | ElMessage.success('计划已导出') |
| | | } |
| | | |
| | | ElMessageBox.confirm("是否确认导出?", "导出", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | // exportDutyPlan().then(res => { |
| | | |
| | | // }) |
| | | proxy.download("/dutyPlan/export", {}, "计划管理.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已取消"); |
| | | }); |
| | | }; |
| | | const handleShare = () => { |
| | | ElMessage.success('计划已共享') |
| | | } |
| | |
| | | if (progress >= 50) return '#E6A23C' |
| | | return '#F56C6C' |
| | | } |
| | | //获取数据列表 |
| | | const getPlanList = async () => { |
| | | const params = { |
| | | level: currentLevel.value, |
| | | period: currentPeriod.value, |
| | | queryDate:currentDate.value |
| | | } |
| | | listDutyPlan(params).then(res => { |
| | | if (res.code === 200) { |
| | | planList.value = res.data.records |
| | | } |
| | | }).catch(err => { |
| | | console.log(err) |
| | | }) |
| | | } |
| | | //获取数据 |
| | | const getPlanNum = async () => { |
| | | NumDutyPlan().then(res => { |
| | | if (res.code === 200) { |
| | | // console.log(res.data) |
| | | //讲结果里面的数据根据level 赋值给overviewData |
| | | res.data.forEach(item => { |
| | | overviewData[item.level].total = item.num |
| | | overviewData[item.level].completion = item.completion |
| | | }) |
| | | |
| | | } |
| | | }).catch(err => { |
| | | console.log(err) |
| | | }) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getPlanList() |
| | | getPlanNum() |
| | | console.log('多级计划模板页面已加载') |
| | | }) |
| | | </script> |