Browse Source
feat(inspection): 新增待办列表并优化排程界面
feat(inspection): 新增待办列表并优化排程界面
- 新增 myTodoList.vue 页面实现 QC 人员待办功能 - 在 inspectionScheduleView.vue 中添加无数据提示状态 - 重构排程表单的 QC 人员选择逻辑,区分显示名称和提交用户名 - 添加路由参数监听功能,支持从待办页面跳转到申请单列表 - 优化多个检验模块的搜索表单项布局和样式 - 在申请单列表中实现 Excel 导出功能 - 移除主表格的红色背景样式标记 - 添加定时刷新机制确保待办数据实时更新master
6 changed files with 516 additions and 96 deletions
-
76src/views/modules/inspection/com_inspectionScheduleView.vue
-
106src/views/modules/inspection/inspectionPendingList.vue
-
4src/views/modules/inspection/inspectionRequestAudit.vue
-
46src/views/modules/inspection/inspectionRequestList.vue
-
4src/views/modules/inspection/inspectionScheduleList.vue
-
336src/views/modules/inspection/myTodoList.vue
@ -0,0 +1,336 @@ |
|||||
|
<template> |
||||
|
<div class="my-todo-container"> |
||||
|
<!-- 页面标题 --> |
||||
|
<div class="page-header"> |
||||
|
<h2 class="page-title">我的代办(QC人员)</h2> |
||||
|
<p class="page-desc">对于QC人员查看到自己的待验货的申请单</p> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 日期卡片网格 --> |
||||
|
<div class="schedule-grid" v-loading="loading"> |
||||
|
<div |
||||
|
v-for="day in scheduleDays" |
||||
|
:key="day.date" |
||||
|
class="schedule-card"> |
||||
|
<div class="card-header"> |
||||
|
<span class="date-label">{{ day.dateLabel }}</span> |
||||
|
<span class="date-weekday">{{ day.weekday }}</span> |
||||
|
</div> |
||||
|
<div class="card-body"> |
||||
|
<div |
||||
|
v-for="task in day.tasks" |
||||
|
:key="task.requestNo" |
||||
|
class="task-item" |
||||
|
@click="handleTaskClick(task, day.date)"> |
||||
|
<div class="task-no">单号:{{ task.requestNo }}</div> |
||||
|
<div class="task-supplier" :title="task.supplierName">{{ task.supplierName }}</div> |
||||
|
<div v-if="task.inspectAddress" class="task-address" :title="task.inspectAddress"> |
||||
|
<i class="el-icon-location"></i> {{ task.inspectAddress }} |
||||
|
</div> |
||||
|
</div> |
||||
|
<div v-if="day.tasks.length === 0" class="empty-slot"> |
||||
|
<span class="empty-text">暂无排程</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { getScheduleView } from '@/api/inspection/inspectionRequestHeader.js' |
||||
|
|
||||
|
export default { |
||||
|
name: 'MyTodoList', |
||||
|
|
||||
|
data () { |
||||
|
return { |
||||
|
scheduleDays: [], // 排程日期数组(未来10天) |
||||
|
loading: false, // 加载状态 |
||||
|
refreshTimer: null // 定时器 |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
mounted () { |
||||
|
this.loadScheduleData() |
||||
|
// 每分钟刷新一次 |
||||
|
this.refreshTimer = setInterval(() => { |
||||
|
this.loadScheduleData() |
||||
|
}, 60000) |
||||
|
}, |
||||
|
|
||||
|
beforeDestroy () { |
||||
|
// 清除定时器 |
||||
|
if (this.refreshTimer) { |
||||
|
clearInterval(this.refreshTimer) |
||||
|
this.refreshTimer = null |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
// 加载排程数据 |
||||
|
loadScheduleData () { |
||||
|
this.loading = true |
||||
|
|
||||
|
// 使用当前登录用户的用户名作为QC人员查询 |
||||
|
const qcOperator = this.$store.state.user.name |
||||
|
|
||||
|
getScheduleView(qcOperator).then(({ data }) => { |
||||
|
if (data.code === 0 && data.list) { |
||||
|
// 生成未来10天的日期结构 |
||||
|
const days = this.generateNextDays(10) |
||||
|
|
||||
|
// 将后端返回的数据按日期分组 |
||||
|
const tasksByDate = {} |
||||
|
data.list.forEach(task => { |
||||
|
const dateStr = this.formatDate(new Date(task.planStartDate)) |
||||
|
if (!tasksByDate[dateStr]) { |
||||
|
tasksByDate[dateStr] = [] |
||||
|
} |
||||
|
tasksByDate[dateStr].push({ |
||||
|
requestNo: task.requestNo, |
||||
|
supplierName: task.supplierName, |
||||
|
inspectAddress: task.inspectAddress, |
||||
|
planStartDate: task.planStartDate, |
||||
|
planEndDate: task.planEndDate |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
|
// 将任务分配到对应的日期卡片中 |
||||
|
this.scheduleDays = days.map(day => ({ |
||||
|
...day, |
||||
|
tasks: tasksByDate[day.date] || [] |
||||
|
})) |
||||
|
|
||||
|
console.log('加载排程数据成功:', this.scheduleDays) |
||||
|
} else { |
||||
|
// 即使失败也显示空白的日期卡片 |
||||
|
this.scheduleDays = this.generateNextDays(10) |
||||
|
} |
||||
|
}).catch((error) => { |
||||
|
console.error('加载排程数据错误:', error) |
||||
|
// 即使失败也显示空白的日期卡片 |
||||
|
this.scheduleDays = this.generateNextDays(10) |
||||
|
}).finally(() => { |
||||
|
this.loading = false |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
// 生成未来N天的日期数组 |
||||
|
generateNextDays (days) { |
||||
|
const result = [] |
||||
|
const today = new Date() |
||||
|
const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'] |
||||
|
|
||||
|
for (let i = 0; i < days; i++) { |
||||
|
const date = new Date(today) |
||||
|
date.setDate(today.getDate() + i) |
||||
|
|
||||
|
const dateStr = this.formatDate(date) |
||||
|
const dateLabel = `${date.getMonth() + 1}/${date.getDate()}` |
||||
|
const weekday = weekdays[date.getDay()] |
||||
|
|
||||
|
result.push({ |
||||
|
date: dateStr, |
||||
|
dateLabel: dateLabel, |
||||
|
weekday: weekday, |
||||
|
tasks: [] |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
return result |
||||
|
}, |
||||
|
|
||||
|
// 格式化日期为 yyyy-MM-dd |
||||
|
formatDate (date) { |
||||
|
const year = date.getFullYear() |
||||
|
const month = String(date.getMonth() + 1).padStart(2, '0') |
||||
|
const day = String(date.getDate()).padStart(2, '0') |
||||
|
return `${year}-${month}-${day}` |
||||
|
}, |
||||
|
|
||||
|
// 点击任务卡片 |
||||
|
handleTaskClick (task, date) { |
||||
|
console.log('点击任务:', task, '日期:', date) |
||||
|
|
||||
|
// 跳转到待验货申请单页面,并传递任务信息 |
||||
|
const query = { |
||||
|
planStartDate: date, |
||||
|
planEndDate: date |
||||
|
} |
||||
|
|
||||
|
// 如果有申请单号,传递过去 |
||||
|
if (task.requestNo) { |
||||
|
query.requestNo = task.requestNo |
||||
|
} |
||||
|
|
||||
|
// 如果有供应商名称,传递过去 |
||||
|
if (task.supplierName) { |
||||
|
query.supplierName = task.supplierName |
||||
|
} |
||||
|
|
||||
|
this.$router.push({ |
||||
|
path: '/inspection-inspectionPendingList', |
||||
|
query: query |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style scoped lang="scss"> |
||||
|
.my-todo-container { |
||||
|
padding: 20px; |
||||
|
background: #fff; |
||||
|
min-height: 100%; |
||||
|
} |
||||
|
|
||||
|
// 页面标题 |
||||
|
.page-header { |
||||
|
margin-bottom: 20px; |
||||
|
|
||||
|
.page-title { |
||||
|
font-size: 20px; |
||||
|
font-weight: bold; |
||||
|
color: #303133; |
||||
|
margin: 0 0 8px 0; |
||||
|
} |
||||
|
|
||||
|
.page-desc { |
||||
|
font-size: 14px; |
||||
|
color: #909399; |
||||
|
margin: 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 排程网格 |
||||
|
.schedule-grid { |
||||
|
display: grid; |
||||
|
grid-template-columns: repeat(5, 1fr); |
||||
|
grid-template-rows: repeat(2, 1fr); |
||||
|
gap: 15px; |
||||
|
min-height: 600px; |
||||
|
} |
||||
|
|
||||
|
// 排程卡片 |
||||
|
.schedule-card { |
||||
|
border: 2px solid #dcdfe6; |
||||
|
border-radius: 4px; |
||||
|
background: #fff; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
min-height: 180px; |
||||
|
transition: all 0.3s; |
||||
|
|
||||
|
&:hover { |
||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); |
||||
|
} |
||||
|
|
||||
|
.card-header { |
||||
|
padding: 10px 12px; |
||||
|
background: #f5f7fa; |
||||
|
border-bottom: 2px solid #dcdfe6; |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
|
||||
|
.date-label { |
||||
|
font-size: 18px; |
||||
|
font-weight: bold; |
||||
|
color: #303133; |
||||
|
} |
||||
|
|
||||
|
.date-weekday { |
||||
|
font-size: 13px; |
||||
|
color: #909399; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.card-body { |
||||
|
flex: 1; |
||||
|
padding: 10px; |
||||
|
overflow-y: auto; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
gap: 8px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 任务项 |
||||
|
.task-item { |
||||
|
padding: 10px; |
||||
|
background: #f5f7fa; |
||||
|
border: 1px solid #dcdfe6; |
||||
|
border-radius: 3px; |
||||
|
cursor: pointer; |
||||
|
transition: all 0.3s; |
||||
|
|
||||
|
&:hover { |
||||
|
background: #ecf5ff; |
||||
|
border-color: #409eff; |
||||
|
box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2); |
||||
|
transform: translateY(-2px); |
||||
|
} |
||||
|
|
||||
|
.task-no { |
||||
|
font-size: 13px; |
||||
|
font-weight: bold; |
||||
|
color: #409eff; |
||||
|
margin-bottom: 5px; |
||||
|
} |
||||
|
|
||||
|
.task-supplier { |
||||
|
font-size: 12px; |
||||
|
color: #606266; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
white-space: nowrap; |
||||
|
margin-bottom: 4px; |
||||
|
} |
||||
|
|
||||
|
.task-address { |
||||
|
font-size: 11px; |
||||
|
color: #909399; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
white-space: nowrap; |
||||
|
|
||||
|
i { |
||||
|
margin-right: 3px; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 空白占位 |
||||
|
.empty-slot { |
||||
|
flex: 1; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
min-height: 80px; |
||||
|
|
||||
|
.empty-text { |
||||
|
color: #c0c4cc; |
||||
|
font-size: 13px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 滚动条样式 |
||||
|
::-webkit-scrollbar { |
||||
|
width: 6px; |
||||
|
height: 6px; |
||||
|
} |
||||
|
|
||||
|
::-webkit-scrollbar-thumb { |
||||
|
background: #c0c4cc; |
||||
|
border-radius: 3px; |
||||
|
|
||||
|
&:hover { |
||||
|
background: #909399; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
::-webkit-scrollbar-track { |
||||
|
background: #f5f7fa; |
||||
|
} |
||||
|
</style> |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue