|
|
@ -55,8 +55,7 @@ |
|
|
:key="task.requestNo" |
|
|
:key="task.requestNo" |
|
|
class="task-item" |
|
|
class="task-item" |
|
|
@click="handleTaskClick(task)"> |
|
|
@click="handleTaskClick(task)"> |
|
|
<div class="task-no">单号:{{ task.requestNo }}</div> |
|
|
|
|
|
<div class="task-supplier" :title="task.supplierName">{{ task.supplierName }}</div> |
|
|
|
|
|
|
|
|
<div class="task-line-text" :title="buildTaskLineText(task)">{{ buildTaskLineText(task) }}</div> |
|
|
<!-- <div v-if="task.inspectAddress" class="task-address" :title="task.inspectAddress"> |
|
|
<!-- <div v-if="task.inspectAddress" class="task-address" :title="task.inspectAddress"> |
|
|
<i class="el-icon-location"></i> {{ task.inspectAddress }} |
|
|
<i class="el-icon-location"></i> {{ task.inspectAddress }} |
|
|
</div> --> |
|
|
</div> --> |
|
|
@ -105,6 +104,19 @@ |
|
|
:close-on-click-modal="false" |
|
|
:close-on-click-modal="false" |
|
|
append-to-body |
|
|
append-to-body |
|
|
top="5vh"> |
|
|
top="5vh"> |
|
|
|
|
|
<el-form :inline="true" size="small" class="all-qc-query-form"> |
|
|
|
|
|
<el-form-item label="起始日期"> |
|
|
|
|
|
<el-date-picker |
|
|
|
|
|
v-model="allQcQuery.startDate" |
|
|
|
|
|
type="date" |
|
|
|
|
|
value-format="yyyy-MM-dd" |
|
|
|
|
|
placeholder="请选择起始日期" |
|
|
|
|
|
style="width: 150px;" /> |
|
|
|
|
|
</el-form-item> |
|
|
|
|
|
<el-form-item label=" "> |
|
|
|
|
|
<el-button type="primary" size="small" @click="queryAllQcSchedule">查询</el-button> |
|
|
|
|
|
</el-form-item> |
|
|
|
|
|
</el-form> |
|
|
<div class="all-qc-schedule-container" v-loading="allQcLoading"> |
|
|
<div class="all-qc-schedule-container" v-loading="allQcLoading"> |
|
|
<div class="schedule-days-grid"> |
|
|
<div class="schedule-days-grid"> |
|
|
<div v-for="day in allScheduleDays" :key="day.date" class="schedule-day-card"> |
|
|
<div v-for="day in allScheduleDays" :key="day.date" class="schedule-day-card"> |
|
|
@ -116,13 +128,14 @@ |
|
|
<div |
|
|
<div |
|
|
v-for="qcTask in day.qcTasks" |
|
|
v-for="qcTask in day.qcTasks" |
|
|
:key="qcTask.userName" |
|
|
:key="qcTask.userName" |
|
|
class="qc-task-item" |
|
|
|
|
|
@click="handleQcTaskClick(qcTask)"> |
|
|
|
|
|
<div class="qc-name-tag">{{ qcTask.qcName }}</div> |
|
|
|
|
|
|
|
|
class="qc-task-item"> |
|
|
<div class="task-list"> |
|
|
<div class="task-list"> |
|
|
<div v-for="task in qcTask.tasks" :key="task.requestNo" class="mini-task"> |
|
|
|
|
|
<span class="task-no-text">{{ task.requestNo }}</span> |
|
|
|
|
|
<span class="task-supplier-text" :title="task.supplierName">{{ task.supplierName }}</span> |
|
|
|
|
|
|
|
|
<div |
|
|
|
|
|
v-for="task in qcTask.tasks" |
|
|
|
|
|
:key="task.requestNo" |
|
|
|
|
|
class="mini-task" |
|
|
|
|
|
@click="handleQcTaskClick({ ...task, qcName: qcTask.qcName, userName: qcTask.userName })"> |
|
|
|
|
|
<span class="task-line-text" :title="buildTaskLineText(task, qcTask.qcName)">{{ buildTaskLineText(task, qcTask.qcName) }}</span> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
@ -162,6 +175,9 @@ export default { |
|
|
allQcLoading: false, |
|
|
allQcLoading: false, |
|
|
allQcScheduleData: {}, // 存储所有QC的排程数据 { userName: [days] } |
|
|
allQcScheduleData: {}, // 存储所有QC的排程数据 { userName: [days] } |
|
|
allScheduleDays: [], // 按日期组织的排程数据 [{ date, dateLabel, weekday, qcTasks: [...] }] |
|
|
allScheduleDays: [], // 按日期组织的排程数据 [{ date, dateLabel, weekday, qcTasks: [...] }] |
|
|
|
|
|
allQcQuery: { |
|
|
|
|
|
startDate: '' |
|
|
|
|
|
}, |
|
|
scheduleForm: { |
|
|
scheduleForm: { |
|
|
qcOperator: '', |
|
|
qcOperator: '', |
|
|
qcUserName: '', |
|
|
qcUserName: '', |
|
|
@ -224,7 +240,11 @@ export default { |
|
|
loadQcList() { |
|
|
loadQcList() { |
|
|
console.log('[排程视图] 开始加载QC列表') |
|
|
console.log('[排程视图] 开始加载QC列表') |
|
|
|
|
|
|
|
|
const params = { page: 1, limit: 100 } |
|
|
|
|
|
|
|
|
const params = { |
|
|
|
|
|
page: 1, |
|
|
|
|
|
limit: 100, |
|
|
|
|
|
site: this.$store.state.user.site |
|
|
|
|
|
} |
|
|
getQcPersonList(params) |
|
|
getQcPersonList(params) |
|
|
.then(({ data }) => { |
|
|
.then(({ data }) => { |
|
|
if (data.code === 0 && data.page && data.page.list) { |
|
|
if (data.code === 0 && data.page && data.page.list) { |
|
|
@ -356,23 +376,25 @@ export default { |
|
|
} |
|
|
} |
|
|
this.loading = true |
|
|
this.loading = true |
|
|
console.log('[排程视图] 开始加载排程数据, QC:', qc.userName) |
|
|
console.log('[排程视图] 开始加载排程数据, QC:', qc.userName) |
|
|
getScheduleView(qc.userName) |
|
|
|
|
|
|
|
|
getScheduleView(qc.userName, this.getTodayDateString(), this.$store.state.user.site) |
|
|
.then(({ data }) => { |
|
|
.then(({ data }) => { |
|
|
if (data.code === 0) { |
|
|
if (data.code === 0) { |
|
|
const days = this.generateNextDays(10) |
|
|
const days = this.generateNextDays(10) |
|
|
const tasksByDate = {} |
|
|
const tasksByDate = {} |
|
|
;(data.list || []).forEach(task => { |
|
|
;(data.list || []).forEach(task => { |
|
|
const startDate = new Date(task.planStartDate) |
|
|
|
|
|
const endDate = new Date(task.planEndDate || task.planStartDate) |
|
|
|
|
|
let currentDate = new Date(startDate) |
|
|
|
|
|
while (currentDate <= endDate) { |
|
|
|
|
|
|
|
|
const taskStartDate = new Date(task.planStartDate) |
|
|
|
|
|
const taskEndDate = new Date(task.planEndDate || task.planStartDate) |
|
|
|
|
|
let currentDate = new Date(taskStartDate) |
|
|
|
|
|
while (currentDate <= taskEndDate) { |
|
|
const dateStr = this.formatDate(currentDate) |
|
|
const dateStr = this.formatDate(currentDate) |
|
|
if (!tasksByDate[dateStr]) tasksByDate[dateStr] = [] |
|
|
if (!tasksByDate[dateStr]) tasksByDate[dateStr] = [] |
|
|
const exists = tasksByDate[dateStr].some(t => t.requestNo === task.requestNo) |
|
|
const exists = tasksByDate[dateStr].some(t => t.requestNo === task.requestNo) |
|
|
if (!exists) { |
|
|
if (!exists) { |
|
|
tasksByDate[dateStr].push({ |
|
|
tasksByDate[dateStr].push({ |
|
|
requestNo: task.requestNo, |
|
|
requestNo: task.requestNo, |
|
|
|
|
|
poNo: task.poNo, |
|
|
supplierName: task.supplierName, |
|
|
supplierName: task.supplierName, |
|
|
|
|
|
qcDisplay: qc.qcName, |
|
|
inspectAddress: task.inspectAddress, |
|
|
inspectAddress: task.inspectAddress, |
|
|
planStartDate: task.planStartDate, |
|
|
planStartDate: task.planStartDate, |
|
|
planEndDate: task.planEndDate |
|
|
planEndDate: task.planEndDate |
|
|
@ -408,13 +430,13 @@ export default { |
|
|
this.loading = false |
|
|
this.loading = false |
|
|
}) |
|
|
}) |
|
|
}, |
|
|
}, |
|
|
generateNextDays(days) { |
|
|
|
|
|
|
|
|
generateNextDays(days, startDate) { |
|
|
const result = [] |
|
|
const result = [] |
|
|
const today = new Date() |
|
|
|
|
|
|
|
|
const baseDate = this.parseDateString(startDate) || new Date() |
|
|
const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'] |
|
|
const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'] |
|
|
for (let i = 0; i < days; i++) { |
|
|
for (let i = 0; i < days; i++) { |
|
|
const date = new Date(today) |
|
|
|
|
|
date.setDate(today.getDate() + i) |
|
|
|
|
|
|
|
|
const date = new Date(baseDate) |
|
|
|
|
|
date.setDate(baseDate.getDate() + i) |
|
|
result.push({ |
|
|
result.push({ |
|
|
date: this.formatDate(date), |
|
|
date: this.formatDate(date), |
|
|
dateLabel: `${date.getMonth() + 1}/${date.getDate()}`, |
|
|
dateLabel: `${date.getMonth() + 1}/${date.getDate()}`, |
|
|
@ -424,6 +446,36 @@ export default { |
|
|
} |
|
|
} |
|
|
return result |
|
|
return result |
|
|
}, |
|
|
}, |
|
|
|
|
|
getTodayDateString() { |
|
|
|
|
|
return this.formatDate(new Date()) |
|
|
|
|
|
}, |
|
|
|
|
|
parseDateString(dateStr) { |
|
|
|
|
|
if (!dateStr) { |
|
|
|
|
|
return null |
|
|
|
|
|
} |
|
|
|
|
|
const parts = String(dateStr).split('-') |
|
|
|
|
|
if (parts.length !== 3) { |
|
|
|
|
|
return null |
|
|
|
|
|
} |
|
|
|
|
|
const year = Number(parts[0]) |
|
|
|
|
|
const month = Number(parts[1]) - 1 |
|
|
|
|
|
const day = Number(parts[2]) |
|
|
|
|
|
const parsedDate = new Date(year, month, day) |
|
|
|
|
|
if (Number.isNaN(parsedDate.getTime())) { |
|
|
|
|
|
return null |
|
|
|
|
|
} |
|
|
|
|
|
return parsedDate |
|
|
|
|
|
}, |
|
|
|
|
|
getSupplierDisplayName(supplierName) { |
|
|
|
|
|
const value = supplierName || '' |
|
|
|
|
|
return value.length > 30 ? value.substring(0, 30) : value |
|
|
|
|
|
}, |
|
|
|
|
|
buildTaskLineText(task, qcDisplayName) { |
|
|
|
|
|
const displayName = qcDisplayName || task.qcDisplay || (this.selectedQc ? this.selectedQc.qcName : '') |
|
|
|
|
|
const poNo = task.poNo || '' |
|
|
|
|
|
const supplierName = this.getSupplierDisplayName(task.supplierName) |
|
|
|
|
|
return [displayName, poNo, supplierName].filter(item => item).join(' | ') |
|
|
|
|
|
}, |
|
|
formatDate(date) { |
|
|
formatDate(date) { |
|
|
const year = date.getFullYear() |
|
|
const year = date.getFullYear() |
|
|
const month = String(date.getMonth() + 1).padStart(2, '0') |
|
|
const month = String(date.getMonth() + 1).padStart(2, '0') |
|
|
@ -437,6 +489,14 @@ export default { |
|
|
// 显示所有QC排程弹窗 |
|
|
// 显示所有QC排程弹窗 |
|
|
showAllQcSchedule() { |
|
|
showAllQcSchedule() { |
|
|
this.allQcScheduleDialogVisible = true |
|
|
this.allQcScheduleDialogVisible = true |
|
|
|
|
|
this.allQcQuery.startDate = this.getTodayDateString() |
|
|
|
|
|
this.loadAllQcSchedule() |
|
|
|
|
|
}, |
|
|
|
|
|
// 按起始日期查询所有QC排程 |
|
|
|
|
|
queryAllQcSchedule() { |
|
|
|
|
|
if (!this.allQcQuery.startDate) { |
|
|
|
|
|
this.allQcQuery.startDate = this.getTodayDateString() |
|
|
|
|
|
} |
|
|
this.loadAllQcSchedule() |
|
|
this.loadAllQcSchedule() |
|
|
}, |
|
|
}, |
|
|
// 加载所有QC的排程数据 |
|
|
// 加载所有QC的排程数据 |
|
|
@ -445,23 +505,26 @@ export default { |
|
|
this.$message.warning('暂无QC人员数据') |
|
|
this.$message.warning('暂无QC人员数据') |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
|
|
|
const startDate = this.allQcQuery.startDate || this.getTodayDateString() |
|
|
|
|
|
this.allQcQuery.startDate = startDate |
|
|
this.allQcLoading = true |
|
|
this.allQcLoading = true |
|
|
const promises = this.qcList.map(qc => { |
|
|
const promises = this.qcList.map(qc => { |
|
|
return getScheduleView(qc.userName).then(({ data }) => { |
|
|
|
|
|
|
|
|
return getScheduleView(qc.userName, startDate, this.$store.state.user.site).then(({ data }) => { |
|
|
if (data.code === 0) { |
|
|
if (data.code === 0) { |
|
|
const days = this.generateNextDays(10) |
|
|
|
|
|
|
|
|
const days = this.generateNextDays(10, startDate) |
|
|
const tasksByDate = {} |
|
|
const tasksByDate = {} |
|
|
;(data.list || []).forEach(task => { |
|
|
;(data.list || []).forEach(task => { |
|
|
const startDate = new Date(task.planStartDate) |
|
|
|
|
|
const endDate = new Date(task.planEndDate || task.planStartDate) |
|
|
|
|
|
let currentDate = new Date(startDate) |
|
|
|
|
|
while (currentDate <= endDate) { |
|
|
|
|
|
|
|
|
const taskStartDate = new Date(task.planStartDate) |
|
|
|
|
|
const taskEndDate = new Date(task.planEndDate || task.planStartDate) |
|
|
|
|
|
let currentDate = new Date(taskStartDate) |
|
|
|
|
|
while (currentDate <= taskEndDate) { |
|
|
const dateStr = this.formatDate(currentDate) |
|
|
const dateStr = this.formatDate(currentDate) |
|
|
if (!tasksByDate[dateStr]) tasksByDate[dateStr] = [] |
|
|
if (!tasksByDate[dateStr]) tasksByDate[dateStr] = [] |
|
|
const exists = tasksByDate[dateStr].some(t => t.requestNo === task.requestNo) |
|
|
const exists = tasksByDate[dateStr].some(t => t.requestNo === task.requestNo) |
|
|
if (!exists) { |
|
|
if (!exists) { |
|
|
tasksByDate[dateStr].push({ |
|
|
tasksByDate[dateStr].push({ |
|
|
requestNo: task.requestNo, |
|
|
requestNo: task.requestNo, |
|
|
|
|
|
poNo: task.poNo, |
|
|
supplierName: task.supplierName, |
|
|
supplierName: task.supplierName, |
|
|
inspectAddress: task.inspectAddress, |
|
|
inspectAddress: task.inspectAddress, |
|
|
planStartDate: task.planStartDate, |
|
|
planStartDate: task.planStartDate, |
|
|
@ -477,17 +540,17 @@ export default { |
|
|
})) |
|
|
})) |
|
|
return { userName: qc.userName, qcName: qc.qcName, scheduleDays } |
|
|
return { userName: qc.userName, qcName: qc.qcName, scheduleDays } |
|
|
} else { |
|
|
} else { |
|
|
return { userName: qc.userName, qcName: qc.qcName, scheduleDays: this.generateNextDays(10) } |
|
|
|
|
|
|
|
|
return { userName: qc.userName, qcName: qc.qcName, scheduleDays: this.generateNextDays(10, startDate) } |
|
|
} |
|
|
} |
|
|
}).catch(() => { |
|
|
}).catch(() => { |
|
|
return { userName: qc.userName, qcName: qc.qcName, scheduleDays: this.generateNextDays(10) } |
|
|
|
|
|
|
|
|
return { userName: qc.userName, qcName: qc.qcName, scheduleDays: this.generateNextDays(10, startDate) } |
|
|
}) |
|
|
}) |
|
|
}) |
|
|
}) |
|
|
|
|
|
|
|
|
Promise.all(promises).then(results => { |
|
|
Promise.all(promises).then(results => { |
|
|
// 按日期重新组织数据 |
|
|
// 按日期重新组织数据 |
|
|
const daysMap = {} |
|
|
const daysMap = {} |
|
|
const baseDays = this.generateNextDays(10) |
|
|
|
|
|
|
|
|
const baseDays = this.generateNextDays(10, startDate) |
|
|
|
|
|
|
|
|
// 初始化每一天的数据结构 |
|
|
// 初始化每一天的数据结构 |
|
|
baseDays.forEach(day => { |
|
|
baseDays.forEach(day => { |
|
|
@ -665,35 +728,14 @@ export default { |
|
|
border-color: #409eff; |
|
|
border-color: #409eff; |
|
|
box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2); |
|
|
box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.task-no { |
|
|
|
|
|
font-size: 13px; |
|
|
|
|
|
font-weight: bold; |
|
|
|
|
|
color: #409eff; |
|
|
|
|
|
margin-bottom: 5px; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.task-supplier { |
|
|
|
|
|
|
|
|
.task-line-text { |
|
|
font-size: 12px; |
|
|
font-size: 12px; |
|
|
color: #606266; |
|
|
|
|
|
word-wrap: break-word; |
|
|
|
|
|
word-break: break-all; |
|
|
|
|
|
white-space: normal; |
|
|
|
|
|
line-height: 1.5; |
|
|
|
|
|
margin-bottom: 4px; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.task-address { |
|
|
|
|
|
font-size: 10px; |
|
|
|
|
|
color: #909399; |
|
|
|
|
|
|
|
|
color: #303133; |
|
|
|
|
|
white-space: nowrap; |
|
|
overflow: hidden; |
|
|
overflow: hidden; |
|
|
text-overflow: ellipsis; |
|
|
text-overflow: ellipsis; |
|
|
white-space: nowrap; |
|
|
|
|
|
|
|
|
|
|
|
i { |
|
|
|
|
|
margin-right: 2px; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.empty-slot { |
|
|
.empty-slot { |
|
|
@ -733,6 +775,11 @@ export default { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* 所有QC排程弹窗样式 */ |
|
|
/* 所有QC排程弹窗样式 */ |
|
|
|
|
|
.all-qc-query-form { |
|
|
|
|
|
padding: 0 10px; |
|
|
|
|
|
margin-bottom: 6px; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
.all-qc-schedule-container { |
|
|
.all-qc-schedule-container { |
|
|
max-height: 75vh; |
|
|
max-height: 75vh; |
|
|
overflow-y: auto; |
|
|
overflow-y: auto; |
|
|
@ -826,15 +873,6 @@ export default { |
|
|
box-shadow: 0 2px 6px rgba(64, 158, 255, 0.12); |
|
|
box-shadow: 0 2px 6px rgba(64, 158, 255, 0.12); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.qc-name-tag { |
|
|
|
|
|
font-size: 12px; |
|
|
|
|
|
font-weight: bold; |
|
|
|
|
|
color: #409eff; |
|
|
|
|
|
margin-bottom: 4px; |
|
|
|
|
|
padding-bottom: 3px; |
|
|
|
|
|
border-bottom: 1px dashed #dcdfe6; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.task-list { |
|
|
.task-list { |
|
|
display: flex; |
|
|
display: flex; |
|
|
flex-direction: column; |
|
|
flex-direction: column; |
|
|
@ -845,25 +883,10 @@ export default { |
|
|
padding: 3px 5px; |
|
|
padding: 3px 5px; |
|
|
background: #fff; |
|
|
background: #fff; |
|
|
border-radius: 2px; |
|
|
border-radius: 2px; |
|
|
font-size: 10px; |
|
|
|
|
|
color: #606266; |
|
|
|
|
|
display: flex; |
|
|
|
|
|
justify-content: space-between; |
|
|
|
|
|
align-items: center; |
|
|
|
|
|
gap: 4px; |
|
|
|
|
|
|
|
|
|
|
|
.task-no-text { |
|
|
|
|
|
font-weight: 500; |
|
|
|
|
|
color: #303133; |
|
|
|
|
|
flex-shrink: 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
cursor: pointer; |
|
|
|
|
|
|
|
|
.task-supplier-text { |
|
|
|
|
|
color: #909399; |
|
|
|
|
|
overflow: hidden; |
|
|
|
|
|
text-overflow: ellipsis; |
|
|
|
|
|
white-space: nowrap; |
|
|
|
|
|
flex: 1; |
|
|
|
|
|
|
|
|
&:hover { |
|
|
|
|
|
background: #ecf5ff; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|