|
|
|
@ -49,6 +49,7 @@
|
|
|
|
<el-button type="warning" @click="BatchDisable()" style="margin-left: 10px;">批量禁用</el-button>
|
|
|
|
<el-button type="warning" @click="BatchDisable()" style="margin-left: 10px;">批量禁用</el-button>
|
|
|
|
<el-button type="success" @click="BatchEnable()" style="margin-left: 10px;">批量启用</el-button>
|
|
|
|
<el-button type="success" @click="BatchEnable()" style="margin-left: 10px;">批量启用</el-button>
|
|
|
|
<el-button type="primary" @click="openBatchModify()" style="margin-left: 10px;">批量修改</el-button>
|
|
|
|
<el-button type="primary" @click="openBatchModify()" style="margin-left: 10px;">批量修改</el-button>
|
|
|
|
|
|
|
|
<el-button type="warning" @click="openBatchOccupy()" style="margin-left: 10px;">批量占位</el-button>
|
|
|
|
</el-row>
|
|
|
|
</el-row>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div style="display: flex;" class="planInfo">
|
|
|
|
<div style="display: flex;" class="planInfo">
|
|
|
|
@ -305,25 +306,19 @@
|
|
|
|
<div style="margin-bottom: 16px; color: #666;">已选 {{ selectedPlanArr.length }} 条号源明细</div>
|
|
|
|
<div style="margin-bottom: 16px; color: #666;">已选 {{ selectedPlanArr.length }} 条号源明细</div>
|
|
|
|
<el-form label-width="100px">
|
|
|
|
<el-form label-width="100px">
|
|
|
|
<el-row :gutter="10" style="margin-bottom: 6px; font-weight: 600; color: #333; font-size: 13px;">
|
|
|
|
<el-row :gutter="10" style="margin-bottom: 6px; font-weight: 600; color: #333; font-size: 13px;">
|
|
|
|
<el-col :span="4">渠道名称</el-col>
|
|
|
|
<el-col :span="6">渠道名称</el-col>
|
|
|
|
<el-col :span="8">数量</el-col>
|
|
|
|
<el-col :span="8">数量</el-col>
|
|
|
|
<el-col :span="8">占用</el-col>
|
|
|
|
|
|
|
|
</el-row>
|
|
|
|
</el-row>
|
|
|
|
<el-row v-for="(ch, ci) in batchChannels" :key="ci" :gutter="10" style="margin-bottom: 10px;">
|
|
|
|
<el-row v-for="(ch, ci) in batchChannels" :key="ci" :gutter="10" style="margin-bottom: 10px;">
|
|
|
|
<el-col :span="4" style="line-height: 32px;">{{ ch.name }}</el-col>
|
|
|
|
<el-col :span="6" style="line-height: 32px;">{{ ch.name }}</el-col>
|
|
|
|
<el-col :span="8">
|
|
|
|
<el-col :span="8">
|
|
|
|
<el-input v-model.number="batchForm[ci].count" placeholder="数量" size="default"
|
|
|
|
<el-input v-model.number="batchForm[ci].count" placeholder="数量" size="default"
|
|
|
|
oninput="value=value.replace(/[^0-9]/g,'')" />
|
|
|
|
oninput="value=value.replace(/[^0-9]/g,'')" />
|
|
|
|
</el-col>
|
|
|
|
</el-col>
|
|
|
|
<el-col :span="8">
|
|
|
|
|
|
|
|
<el-input v-model.number="batchForm[ci].locked_count" placeholder="占用数量" size="default"
|
|
|
|
|
|
|
|
oninput="value=value.replace(/[^0-9]/g,'')" />
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
</el-row>
|
|
|
|
</el-row>
|
|
|
|
<el-row :gutter="10" style="border-top: 1px solid #eee; padding-top: 10px;">
|
|
|
|
<el-row :gutter="10" style="border-top: 1px solid #eee; padding-top: 10px;">
|
|
|
|
<el-col :span="4" style="line-height: 32px; font-weight: 600;">合计</el-col>
|
|
|
|
<el-col :span="6" style="line-height: 32px; font-weight: 600;">合计</el-col>
|
|
|
|
<el-col :span="8" style="line-height: 32px; font-weight: 600;">数量: {{ batchTotalCount }}</el-col>
|
|
|
|
<el-col :span="8" style="line-height: 32px; font-weight: 600;">数量: {{ batchTotalCount }}</el-col>
|
|
|
|
<el-col :span="8" style="line-height: 32px; font-weight: 600;">占用: {{ batchTotalLocked }}</el-col>
|
|
|
|
|
|
|
|
</el-row>
|
|
|
|
</el-row>
|
|
|
|
</el-form>
|
|
|
|
</el-form>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
@ -332,6 +327,43 @@
|
|
|
|
<el-button type="primary" @click="execBatchModify()" :disabled="batchModifyRunning">确定修改</el-button>
|
|
|
|
<el-button type="primary" @click="execBatchModify()" :disabled="batchModifyRunning">确定修改</el-button>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-dialog>
|
|
|
|
</el-dialog>
|
|
|
|
|
|
|
|
<!-- 批量占位弹窗 -->
|
|
|
|
|
|
|
|
<el-dialog v-model="BatchOccupyDialogVisible" title="批量占位" width="45%" :close-on-click-modal="false">
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
|
|
|
<div style="margin-bottom: 16px; color: #666;">已选 {{ selectedPlanArr.length }} 条号源明细</div>
|
|
|
|
|
|
|
|
<el-form label-width="100px">
|
|
|
|
|
|
|
|
<el-row :gutter="10" style="margin-bottom: 6px; font-weight: 600; color: #333; font-size: 13px;">
|
|
|
|
|
|
|
|
<el-col :span="6">渠道名称</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8">占用数量</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8">提示</el-col>
|
|
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
<el-row v-for="(ch, ci) in batchChannels" :key="ci" :gutter="10" style="margin-bottom: 10px;">
|
|
|
|
|
|
|
|
<el-col :span="6" style="line-height: 32px;">{{ ch.name }}</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8">
|
|
|
|
|
|
|
|
<el-input v-model.number="batchOccupyForm[ci].locked_count" placeholder="占用数量" size="default"
|
|
|
|
|
|
|
|
oninput="value=value.replace(/[^0-9]/g,'')"
|
|
|
|
|
|
|
|
@input="onOccupyInput(ci, $event)" />
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8" style="line-height: 32px; font-size: 12px; color: #999;">
|
|
|
|
|
|
|
|
<template v-if="batchOccupyLimits[ch.id]?.limited">
|
|
|
|
|
|
|
|
最大可占: {{ batchOccupyLimits[ch.id].maxValue }}
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<template v-else>
|
|
|
|
|
|
|
|
剩余数量不一致
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
<el-row :gutter="10" style="border-top: 1px solid #eee; padding-top: 10px;">
|
|
|
|
|
|
|
|
<el-col :span="6" style="line-height: 32px; font-weight: 600;">合计</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8" style="line-height: 32px; font-weight: 600;">占用: {{ batchOccupyTotalLocked }}</el-col>
|
|
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<template #footer>
|
|
|
|
|
|
|
|
<el-button @click="BatchOccupyDialogVisible = false" :disabled="batchOccupyRunning">取消</el-button>
|
|
|
|
|
|
|
|
<el-button type="warning" @click="execBatchOccupy()" :disabled="batchOccupyRunning">确定占位</el-button>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-dialog>
|
|
|
|
<!-- 错误汇总弹窗 -->
|
|
|
|
<!-- 错误汇总弹窗 -->
|
|
|
|
<el-dialog v-model="BatchErrorDialogVisible" title="修改结果" width="40%">
|
|
|
|
<el-dialog v-model="BatchErrorDialogVisible" title="修改结果" width="40%">
|
|
|
|
<div>
|
|
|
|
<div>
|
|
|
|
@ -372,6 +404,8 @@
|
|
|
|
PlanListBatchEnableAdmin,
|
|
|
|
PlanListBatchEnableAdmin,
|
|
|
|
PlanDetailBatchUpdateAdmin,
|
|
|
|
PlanDetailBatchUpdateAdmin,
|
|
|
|
PlanListBatchChangeInfoAdmin,
|
|
|
|
PlanListBatchChangeInfoAdmin,
|
|
|
|
|
|
|
|
PlanListBatchChangeCount,
|
|
|
|
|
|
|
|
PlanListBatchChangeLocked,
|
|
|
|
GetPlanUsedList,
|
|
|
|
GetPlanUsedList,
|
|
|
|
SaveLockedCount
|
|
|
|
SaveLockedCount
|
|
|
|
} from '@/api/api.js'
|
|
|
|
} from '@/api/api.js'
|
|
|
|
@ -879,28 +913,24 @@
|
|
|
|
const initBatchForm = () => {
|
|
|
|
const initBatchForm = () => {
|
|
|
|
batchForm.value = batchChannels.map(ch => ({
|
|
|
|
batchForm.value = batchChannels.map(ch => ({
|
|
|
|
appointment_type_id: ch.id,
|
|
|
|
appointment_type_id: ch.id,
|
|
|
|
count: '',
|
|
|
|
count: ''
|
|
|
|
locked_count: ''
|
|
|
|
|
|
|
|
}))
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
initBatchForm()
|
|
|
|
initBatchForm()
|
|
|
|
const batchTotalCount = computed(() => {
|
|
|
|
const batchTotalCount = computed(() => {
|
|
|
|
return batchForm.value.reduce((s, item) => s + (Number(item.count) || 0), 0)
|
|
|
|
return batchForm.value.reduce((s, item) => s + (Number(item.count) || 0), 0)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
const batchTotalLocked = computed(() => {
|
|
|
|
|
|
|
|
return batchForm.value.reduce((s, item) => s + (Number(item.locked_count) || 0), 0)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
const openBatchModify = () => {
|
|
|
|
const openBatchModify = () => {
|
|
|
|
if (selectedPlanArr.value.length == 0) {
|
|
|
|
if (selectedPlanArr.value.length == 0) {
|
|
|
|
ElMessage.error('请至少勾选1条记录')
|
|
|
|
ElMessage.error('请至少勾选1条记录')
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
initBatchForm()
|
|
|
|
initBatchForm()
|
|
|
|
// 从 planTableData 中提取已选号源的各渠道值
|
|
|
|
// 从 planTableData 中提取已选号源的各渠道 count 值
|
|
|
|
const selectedIds = new Set(selectedPlanArr.value)
|
|
|
|
const selectedIds = new Set(selectedPlanArr.value)
|
|
|
|
const channelValues = {} // { appointment_type_id: { count: [], locked_count: [] } }
|
|
|
|
const channelValues = {}
|
|
|
|
batchChannels.forEach(ch => {
|
|
|
|
batchChannels.forEach(ch => {
|
|
|
|
channelValues[ch.id] = { count: [], locked_count: [] }
|
|
|
|
channelValues[ch.id] = { count: [] }
|
|
|
|
})
|
|
|
|
})
|
|
|
|
planTableData.value.forEach(row => {
|
|
|
|
planTableData.value.forEach(row => {
|
|
|
|
for (const key in row) {
|
|
|
|
for (const key in row) {
|
|
|
|
@ -910,7 +940,6 @@
|
|
|
|
cell.countsInfo.forEach(ci => {
|
|
|
|
cell.countsInfo.forEach(ci => {
|
|
|
|
if (channelValues[ci.appointment_type_id]) {
|
|
|
|
if (channelValues[ci.appointment_type_id]) {
|
|
|
|
channelValues[ci.appointment_type_id].count.push(ci.count)
|
|
|
|
channelValues[ci.appointment_type_id].count.push(ci.count)
|
|
|
|
channelValues[ci.appointment_type_id].locked_count.push(ci.locked_count)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -922,8 +951,7 @@
|
|
|
|
const allSame = arr => arr.length > 0 && arr.every(v => v === arr[0])
|
|
|
|
const allSame = arr => arr.length > 0 && arr.every(v => v === arr[0])
|
|
|
|
return {
|
|
|
|
return {
|
|
|
|
appointment_type_id: ch.id,
|
|
|
|
appointment_type_id: ch.id,
|
|
|
|
count: vals.count.length > 0 && allSame(vals.count) ? vals.count[0] : '',
|
|
|
|
count: vals.count.length > 0 && allSame(vals.count) ? vals.count[0] : ''
|
|
|
|
locked_count: vals.locked_count.length > 0 && allSame(vals.locked_count) ? vals.locked_count[0] : ''
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
batchProgress.value = 0
|
|
|
|
batchProgress.value = 0
|
|
|
|
@ -937,17 +965,10 @@
|
|
|
|
const execBatchModify = async () => {
|
|
|
|
const execBatchModify = async () => {
|
|
|
|
// 校验
|
|
|
|
// 校验
|
|
|
|
for (const item of batchForm.value) {
|
|
|
|
for (const item of batchForm.value) {
|
|
|
|
const count = Number(item.count)
|
|
|
|
if (Number(item.count) < 0) {
|
|
|
|
const locked = Number(item.locked_count)
|
|
|
|
|
|
|
|
if (count < 0 || locked < 0) {
|
|
|
|
|
|
|
|
ElMessage.error('数量不能为负数')
|
|
|
|
ElMessage.error('数量不能为负数')
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (locked > count) {
|
|
|
|
|
|
|
|
const chName = batchChannels.find(c => c.id === item.appointment_type_id)?.name || ''
|
|
|
|
|
|
|
|
ElMessage.error(`${chName} 的占用数量不能大于数量`)
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// 全部为 0 或空时二次确认
|
|
|
|
// 全部为 0 或空时二次确认
|
|
|
|
const allZero = batchForm.value.every(item => Number(item.count) === 0)
|
|
|
|
const allZero = batchForm.value.every(item => Number(item.count) === 0)
|
|
|
|
@ -972,12 +993,10 @@
|
|
|
|
const ids = [...selectedPlanArr.value]
|
|
|
|
const ids = [...selectedPlanArr.value]
|
|
|
|
const coutsInfo = batchForm.value.map(item => ({
|
|
|
|
const coutsInfo = batchForm.value.map(item => ({
|
|
|
|
appointment_type_id: item.appointment_type_id,
|
|
|
|
appointment_type_id: item.appointment_type_id,
|
|
|
|
count: Number(item.count) || 0,
|
|
|
|
count: Number(item.count) || 0
|
|
|
|
locked_count: Number(item.locked_count) || 0
|
|
|
|
|
|
|
|
}))
|
|
|
|
}))
|
|
|
|
batchModifyRunning.value = true
|
|
|
|
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
const res = await PlanListBatchChangeInfoAdmin({
|
|
|
|
const res = await PlanListBatchChangeCount({
|
|
|
|
ids: ids,
|
|
|
|
ids: ids,
|
|
|
|
max_total: maxTotal,
|
|
|
|
max_total: maxTotal,
|
|
|
|
coutsInfo: coutsInfo,
|
|
|
|
coutsInfo: coutsInfo,
|
|
|
|
@ -997,6 +1016,105 @@
|
|
|
|
ElMessage.error('请求异常')
|
|
|
|
ElMessage.error('请求异常')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 批量占位
|
|
|
|
|
|
|
|
let BatchOccupyDialogVisible = ref(false)
|
|
|
|
|
|
|
|
let batchOccupyRunning = ref(false)
|
|
|
|
|
|
|
|
let batchOccupyForm = ref([])
|
|
|
|
|
|
|
|
let batchOccupyLimits = ref({}) // { [appointment_type_id]: { limited: bool, maxValue: number } }
|
|
|
|
|
|
|
|
const initBatchOccupyForm = () => {
|
|
|
|
|
|
|
|
batchOccupyForm.value = batchChannels.map(ch => ({
|
|
|
|
|
|
|
|
appointment_type_id: ch.id,
|
|
|
|
|
|
|
|
locked_count: ''
|
|
|
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
initBatchOccupyForm()
|
|
|
|
|
|
|
|
const batchOccupyTotalLocked = computed(() => {
|
|
|
|
|
|
|
|
return batchOccupyForm.value.reduce((s, item) => s + (Number(item.locked_count) || 0), 0)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
const onOccupyInput = (ci, val) => {
|
|
|
|
|
|
|
|
const ch = batchChannels[ci]
|
|
|
|
|
|
|
|
const limit = batchOccupyLimits.value[ch.id]
|
|
|
|
|
|
|
|
if (limit?.limited && Number(val) > limit.maxValue) {
|
|
|
|
|
|
|
|
batchOccupyForm.value[ci].locked_count = limit.maxValue
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const openBatchOccupy = () => {
|
|
|
|
|
|
|
|
if (selectedPlanArr.value.length == 0) {
|
|
|
|
|
|
|
|
ElMessage.error('请至少勾选1条记录')
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
initBatchOccupyForm()
|
|
|
|
|
|
|
|
// 从 planTableData 中提取已选号源的各渠道 count(总数量),判断是否一致
|
|
|
|
|
|
|
|
const selectedIds = new Set(selectedPlanArr.value)
|
|
|
|
|
|
|
|
const channelCounts = {} // { [appointment_type_id]: number[] }
|
|
|
|
|
|
|
|
batchChannels.forEach(ch => {
|
|
|
|
|
|
|
|
channelCounts[ch.id] = []
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
planTableData.value.forEach(row => {
|
|
|
|
|
|
|
|
for (const key in row) {
|
|
|
|
|
|
|
|
if (key === 'time_range') continue
|
|
|
|
|
|
|
|
const cell = row[key]
|
|
|
|
|
|
|
|
if (cell && cell.id && selectedIds.has(cell.id) && cell.countsInfo) {
|
|
|
|
|
|
|
|
cell.countsInfo.forEach(ci => {
|
|
|
|
|
|
|
|
if (channelCounts[ci.appointment_type_id]) {
|
|
|
|
|
|
|
|
channelCounts[ci.appointment_type_id].push(ci.count)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
// 判断每个渠道的 count 是否全部一致,设限制
|
|
|
|
|
|
|
|
const limits = {}
|
|
|
|
|
|
|
|
batchChannels.forEach(ch => {
|
|
|
|
|
|
|
|
const vals = channelCounts[ch.id]
|
|
|
|
|
|
|
|
if (vals.length > 0) {
|
|
|
|
|
|
|
|
const allSame = vals.every(v => v === vals[0])
|
|
|
|
|
|
|
|
limits[ch.id] = {
|
|
|
|
|
|
|
|
limited: allSame,
|
|
|
|
|
|
|
|
maxValue: allSame ? vals[0] : null
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
limits[ch.id] = { limited: false, maxValue: null }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
batchOccupyLimits.value = limits
|
|
|
|
|
|
|
|
batchOccupyRunning.value = false
|
|
|
|
|
|
|
|
BatchOccupyDialogVisible.value = true
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const execBatchOccupy = async () => {
|
|
|
|
|
|
|
|
// 校验
|
|
|
|
|
|
|
|
for (const item of batchOccupyForm.value) {
|
|
|
|
|
|
|
|
if (Number(item.locked_count) < 0) {
|
|
|
|
|
|
|
|
ElMessage.error('占用数量不能为负数')
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
batchOccupyRunning.value = true
|
|
|
|
|
|
|
|
const ids = [...selectedPlanArr.value]
|
|
|
|
|
|
|
|
const coutsInfo = batchOccupyForm.value.map(item => ({
|
|
|
|
|
|
|
|
appointment_type_id: item.appointment_type_id,
|
|
|
|
|
|
|
|
locked_count: Number(item.locked_count) || 0
|
|
|
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
const res = await PlanListBatchChangeLocked({
|
|
|
|
|
|
|
|
ids: ids,
|
|
|
|
|
|
|
|
coutsInfo: coutsInfo,
|
|
|
|
|
|
|
|
department_id: searchInfo.value.department_id
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
batchOccupyRunning.value = false
|
|
|
|
|
|
|
|
if (res && res.status) {
|
|
|
|
|
|
|
|
BatchOccupyDialogVisible.value = false
|
|
|
|
|
|
|
|
ElMessage.success('批量占位完成')
|
|
|
|
|
|
|
|
GetList()
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
ElMessage.error(res?.msg || '批量占位失败')
|
|
|
|
|
|
|
|
batchOccupyRunning.value = false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
|
|
batchOccupyRunning.value = false
|
|
|
|
|
|
|
|
ElMessage.error('请求异常')
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
let MingXiDialogVisible = ref(false);
|
|
|
|
let MingXiDialogVisible = ref(false);
|
|
|
|
let MingXiLoading = ref(false)
|
|
|
|
let MingXiLoading = ref(false)
|
|
|
|
let MingXiList = ref(null);
|
|
|
|
let MingXiList = ref(null);
|
|
|
|
|