<template>
|
<n-modal
|
:show="visible"
|
@update:show="(value) => emit('update:visible', value)"
|
title="📐 统一配置校准周期"
|
preset="card"
|
size="medium"
|
:style="bodyStyle"
|
>
|
<label class="form-label">选择周期模板</label>
|
<div class="config-template-grid">
|
<div class="template-card" :class="{ selected: selectedTemplate === 7 }" @click="selectTemplate(7)">
|
<div class="t-icon">⚡</div>
|
<div class="t-name">高频</div>
|
<div class="t-desc">每 7 天校准</div>
|
</div>
|
<div class="template-card" :class="{ selected: selectedTemplate === 14 }" @click="selectTemplate(14)">
|
<div class="t-icon">🔄</div>
|
<div class="t-name">标准</div>
|
<div class="t-desc">每 14 天校准</div>
|
</div>
|
<div class="template-card" :class="{ selected: selectedTemplate === 30 }" @click="selectTemplate(30)">
|
<div class="t-icon">📅</div>
|
<div class="t-name">常规</div>
|
<div class="t-desc">每 30 天校准</div>
|
</div>
|
<div class="template-card" :class="{ selected: selectedTemplate === 90 }" @click="selectTemplate(90)">
|
<div class="t-icon">📆</div>
|
<div class="t-name">季度</div>
|
<div class="t-desc">每 90 天校准</div>
|
</div>
|
<div class="template-card" :class="{ selected: selectedTemplate === 360 }" @click="selectTemplate(360)">
|
<div class="t-icon">🗂️</div>
|
<div class="t-name">年度</div>
|
<div class="t-desc">每 360 天校准</div>
|
</div>
|
<div class="template-card" :class="{ selected: selectedTemplate === 'custom' }" @click="selectTemplate('custom')">
|
<div class="t-icon">✏️</div>
|
<div class="t-name">自定义</div>
|
<n-input-number v-model:value="customDays" placeholder="天数" class="t-custom-input" />
|
</div>
|
</div>
|
|
<div class="form-group" style="margin-top: 16px;">
|
<label class="form-label">提前提醒天数</label>
|
<div class="form-row">
|
<n-input-number v-model:value="form.remindDays" style="max-width: 100px;" />
|
<span class="form-unit">天(应用到所有选中盒子)</span>
|
</div>
|
</div>
|
|
<div class="apply-target" style="margin-top: 16px;">
|
<label class="form-label">应用范围</label>
|
<div class="radio-group">
|
<label class="radio-item" @click="selectApplyScope('all')">
|
<n-radio :checked="form.applyScope === 'all'" name="applyScope" value="all" />
|
全部已启用盒子
|
</label>
|
<label class="radio-item" @click="selectApplyScope('selected')">
|
<n-radio :checked="form.applyScope === 'selected'" name="applyScope" value="selected" />
|
仅选中项({{ selectedRows.length }}个)
|
</label>
|
</div>
|
</div>
|
<template #footer>
|
<div class="modal-footer">
|
<span class="modal-hint">将覆盖选中盒子的校准周期和提醒天数</span>
|
<div class="modal-footer-right">
|
<n-button @click="handleCancel">取消</n-button>
|
<n-button type="primary" @click="handleSubmit">✅ 应用配置</n-button>
|
</div>
|
</div>
|
</template>
|
</n-modal>
|
</template>
|
|
<script setup lang="ts">
|
import { ref, reactive, watch } from 'vue';
|
import { weighingBoxApi } from '@/service/api/md/weighing-box';
|
import { useMessage } from 'naive-ui';
|
|
const props = defineProps({
|
visible: {
|
type: Boolean,
|
default: false
|
},
|
selectedRows: {
|
type: Array,
|
default: () => []
|
},
|
type: {
|
type: String,
|
default: 'all'
|
}
|
});
|
|
const emit = defineEmits(['update:visible', 'submitted']);
|
|
const message = useMessage();
|
|
const form = reactive({
|
calibCycleDays: 30,
|
remindDays: 7,
|
applyScope: props.type
|
});
|
|
const customDays = ref(30);
|
const selectedTemplate = ref(30);
|
|
const bodyStyle = {
|
width: '600px'
|
};
|
|
watch(() => props.visible, (newValue) => {
|
if (newValue) {
|
form.calibCycleDays = 30;
|
form.remindDays = 7;
|
form.applyScope = props.type;
|
customDays.value = 30;
|
selectedTemplate.value = 30;
|
}
|
});
|
|
const selectTemplate = (days) => {
|
selectedTemplate.value = days;
|
if (days === 'custom') {
|
form.calibCycleDays = customDays.value;
|
} else {
|
form.calibCycleDays = days;
|
}
|
};
|
|
const selectApplyScope = (scope) => {
|
form.applyScope = scope;
|
};
|
|
const handleCancel = () => {
|
emit('update:visible', false);
|
};
|
|
const handleSubmit = async () => {
|
try {
|
const response = await weighingBoxApi.batchConfig({
|
calibCycleDays: form.calibCycleDays,
|
remindDays: form.remindDays,
|
applyScope: form.applyScope,
|
boxIds: props.selectedRows.map(row => row.id)
|
});
|
const res = response.response.data;
|
|
if (res.code === 200) {
|
message.success('批量配置成功');
|
emit('update:visible', false);
|
emit('submitted');
|
} else {
|
message.error(res.msg || '批量配置失败');
|
}
|
} catch (error) {
|
message.error('批量配置失败');
|
}
|
};
|
</script>
|
|
<style scoped>
|
/* 表单样式 */
|
.form-label {
|
font-size: 14px;
|
font-weight: 500;
|
color: #333;
|
margin-bottom: 8px;
|
}
|
|
.form-row {
|
display: flex;
|
gap: 10px;
|
align-items: center;
|
}
|
|
.form-unit {
|
font-size: 14px;
|
color: #666;
|
}
|
|
/* 配置模板 */
|
.config-template-grid {
|
display: grid;
|
grid-template-columns: repeat(3, 1fr);
|
gap: 12px;
|
margin-bottom: 20px;
|
}
|
|
.template-card {
|
border: 2px solid #e5e7eb;
|
border-radius: 8px;
|
padding: 16px;
|
cursor: pointer;
|
transition: all 0.2s ease;
|
text-align: center;
|
background: #fff;
|
}
|
|
.template-card:hover {
|
border-color: #91d5ff;
|
box-shadow: 0 2px 8px rgba(24, 144, 255, 0.1);
|
}
|
|
.template-card.selected {
|
border-color: #1890ff;
|
box-shadow: 0 2px 8px rgba(24, 144, 255, 0.2);
|
background: #e6f7ff;
|
}
|
|
.template-card .t-icon {
|
font-size: 24px;
|
margin-bottom: 8px;
|
}
|
|
.template-card .t-name {
|
font-size: 14px;
|
font-weight: 600;
|
color: #333;
|
margin-bottom: 4px;
|
}
|
|
.template-card .t-desc {
|
font-size: 12px;
|
color: #666;
|
}
|
|
.template-card .t-custom-input {
|
margin-top: 8px;
|
}
|
|
/* 应用范围 */
|
.apply-target {
|
margin-top: 16px;
|
}
|
|
.radio-group {
|
display: flex;
|
gap: 20px;
|
margin-top: 8px;
|
flex-wrap: wrap;
|
}
|
|
.radio-item {
|
display: flex;
|
align-items: center;
|
gap: 8px;
|
font-size: 14px;
|
color: #333;
|
cursor: pointer;
|
}
|
|
/* 模态框底部 */
|
.modal-footer {
|
width: 100%;
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
}
|
|
.modal-hint {
|
font-size: 12px;
|
color: #999;
|
}
|
|
.modal-footer-right {
|
display: flex;
|
gap: 10px;
|
}
|
</style>
|