<template>
|
<n-modal
|
:show="visible"
|
@update:show="(value) => emit('update:visible', value)"
|
:title="operateType === 'add' ? '📦 新增称重盒子' : '📦 编辑称重盒子'"
|
preset="card"
|
size="medium"
|
:style="bodyStyle"
|
:bordered="false"
|
>
|
<n-form ref="formRef" :model="form" :rules="rules" label-placement="top">
|
<n-grid :cols="2" :x-gap="12" :y-gap="0">
|
<!-- 基本信息 -->
|
<n-grid-item :span="2">
|
<div class="form-section-title">📦 基本信息</div>
|
</n-grid-item>
|
|
<n-form-item-gi path="name" label="盒子名称" required>
|
<n-input v-model:value="form.name" placeholder="如:标准砝码盒 A-01" />
|
</n-form-item-gi>
|
|
<n-form-item-gi path="code" label="盒子编号" required>
|
<n-input v-model:value="form.code" placeholder="如:WBOX-2024-001" />
|
</n-form-item-gi>
|
|
<n-form-item-gi path="weight" label="标准重量" required>
|
<div class="form-row">
|
<n-input-number v-model:value="form.weight" placeholder="500.00" />
|
<n-input v-model:value="form.unit" placeholder="g" style="max-width: 80px;" />
|
</div>
|
</n-form-item-gi>
|
|
<n-form-item-gi path="location" label="存放位置">
|
<n-input v-model:value="form.location" placeholder="如:1号产线·质检台A" />
|
</n-form-item-gi>
|
|
<!-- 校准设置 -->
|
<n-grid-item :span="2">
|
<hr class="form-divider">
|
<div class="form-section-title">📐 校准设置</div>
|
</n-grid-item>
|
|
<n-grid-item :span="2">
|
<div class="form-group full">
|
<label class="form-label">选择预设周期模板</label>
|
<div class="preset-bar">
|
<span class="preset-chip" @click="setPresetCycle(7)">每 7 天</span>
|
<span class="preset-chip" @click="setPresetCycle(14)">每 14 天</span>
|
<span class="preset-chip active" @click="setPresetCycle(30)">每 30 天</span>
|
<span class="preset-chip" @click="setPresetCycle(60)">每 60 天</span>
|
<span class="preset-chip" @click="setPresetCycle(90)">每 90 天</span>
|
<span class="preset-chip" @click="setPresetCycle(180)">每 180 天</span>
|
</div>
|
</div>
|
</n-grid-item>
|
|
<n-form-item-gi path="calibCycleDays" label="校准周期" required>
|
<div class="form-row">
|
<n-input-number v-model:value="form.calibCycleDays" placeholder="30" />
|
<span class="form-unit">天</span>
|
</div>
|
</n-form-item-gi>
|
|
<n-form-item-gi path="remindDays" label="提前提醒天数">
|
<div class="form-row">
|
<n-input-number v-model:value="form.remindDays" placeholder="7" />
|
<span class="form-unit">天</span>
|
</div>
|
</n-form-item-gi>
|
|
<n-form-item-gi label="上次校准日期">
|
<n-date-picker v-model:value="form.lastCalibDate" type="date" />
|
</n-form-item-gi>
|
|
<n-form-item-gi label="启用状态">
|
<div class="switch-wrap">
|
<n-switch v-model:value="form.activeStatus" />
|
<span class="switch-label">{{ form.activeStatus ? '已启用' : '已停用' }}</span>
|
</div>
|
</n-form-item-gi>
|
|
<!-- 备注描述 -->
|
<n-grid-item :span="2">
|
<hr class="form-divider">
|
</n-grid-item>
|
|
<n-form-item-gi label="备注描述" :span="2">
|
<n-input v-model:value="form.description" type="textarea" placeholder="可填写盒子规格说明、注意事项等…" />
|
</n-form-item-gi>
|
</n-grid>
|
</n-form>
|
<template #footer>
|
<div class="modal-footer">
|
<span class="modal-hint">💡 按 Ctrl+Enter 快速保存</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
|
},
|
operateType: {
|
type: String,
|
default: 'add'
|
},
|
rowData: {
|
type: Object,
|
default: () => ({})
|
}
|
});
|
|
const emit = defineEmits(['update:visible', 'submitted']);
|
|
const message = useMessage();
|
const formRef = ref();
|
|
const form = reactive({
|
id: undefined,
|
name: '',
|
code: '',
|
weight: null,
|
unit: 'g',
|
location: '',
|
calibCycleDays: 30,
|
remindDays: 7,
|
lastCalibDate: null,
|
activeStatus: true,
|
description: ''
|
});
|
|
const rules = {
|
name: [{ required: true, message: '请输入盒子名称', trigger: 'blur' }],
|
code: [{ required: true, message: '请输入盒子编号', trigger: 'blur' }],
|
weight: [{ type: 'number', required: true, message: '请输入标准重量', trigger: 'blur' }],
|
unit: [{ required: true, message: '请输入单位', trigger: 'blur' }],
|
calibCycleDays: [{ type: 'number', required: true, message: '请输入校准周期', trigger: 'blur' }]
|
};
|
|
const bodyStyle = {
|
width: '800px'
|
};
|
|
watch(() => props.visible, (newValue) => {
|
if (newValue) {
|
if (props.operateType === 'edit' && props.rowData) {
|
console.log("编辑数据:", props.rowData);
|
Object.assign(form, props.rowData);
|
// 将启用状态转换为数值
|
form.activeStatus = form.activeStatus === 1;
|
form.weight = Number(form.weight);
|
} else {
|
console.log("新增数据:", form);
|
form.id = undefined;
|
form.name = '';
|
form.code = '';
|
form.weight = null;
|
form.unit = 'g';
|
form.location = '';
|
form.calibCycleDays = 30;
|
form.remindDays = 7;
|
form.activeStatus = true;
|
form.description = '';
|
form.lastCalibDate = null;
|
|
}
|
}
|
});
|
|
const setPresetCycle = (days) => {
|
form.calibCycleDays = days;
|
};
|
|
const handleCancel = () => {
|
emit('update:visible', false);
|
};
|
|
const handleSubmit = async () => {
|
if (!formRef.value) return;
|
try {
|
await formRef.value.validate();
|
// 将启用状态转换为数值
|
form.activeStatus = form.activeStatus ? 1 : 0;
|
|
let response;
|
if (form.id) {
|
response = await weighingBoxApi.edit(form);
|
} else {
|
response = await weighingBoxApi.add(form);
|
}
|
const res = response.response.data;
|
|
if (res.code === 200) {
|
message.success(form.id ? '修改成功' : '新增成功');
|
emit('update:visible', false);
|
emit('submitted');
|
} else {
|
message.error(res.msg || '操作失败');
|
}
|
} catch (error: any) {
|
console.error('Form validation failed', error);
|
if (error.message) {
|
message.error(error.message);
|
} else {
|
message.error('操作失败');
|
}
|
}
|
};
|
</script>
|
|
<style scoped>
|
/* 表单样式 */
|
.form-grid {
|
display: grid;
|
grid-template-columns: 1fr 1fr;
|
}
|
|
.form-group {
|
display: flex;
|
flex-direction: column;
|
}
|
|
.form-group.full {
|
grid-column: 1 / -1;
|
}
|
|
.form-label {
|
font-size: 14px;
|
font-weight: 500;
|
color: #333;
|
margin-bottom: 8px;
|
}
|
|
.form-label .required {
|
color: #ff4d4f;
|
margin-left: 4px;
|
}
|
|
.form-row {
|
display: flex;
|
gap: 10px;
|
align-items: center;
|
}
|
|
.form-hint {
|
font-size: 12px;
|
color: #999;
|
margin-top: 4px;
|
}
|
|
.form-divider {
|
grid-column: 1 / -1;
|
border: none;
|
border-top: 1px solid #e5e7eb;
|
margin: 12px 0;
|
}
|
|
.form-section-title {
|
grid-column: 1 / -1;
|
font-size: 14px;
|
font-weight: 600;
|
color: #1890ff;
|
margin: 12px 0 8px;
|
}
|
|
/* 预设模板 */
|
.preset-bar {
|
grid-column: 1 / -1;
|
display: flex;
|
align-items: center;
|
gap: 8px;
|
flex-wrap: wrap;
|
margin-bottom: 12px;
|
}
|
|
.preset-chip {
|
padding: 6px 16px;
|
border-radius: 20px;
|
border: 1px solid #e5e7eb;
|
font-size: 14px;
|
color: #666;
|
cursor: pointer;
|
transition: all 0.2s ease;
|
background: #fff;
|
}
|
|
.preset-chip:hover {
|
border-color: #1890ff;
|
color: #1890ff;
|
}
|
|
.preset-chip.active {
|
background: #1890ff;
|
color: #fff;
|
border-color: #1890ff;
|
}
|
|
/* 模态框底部 */
|
.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;
|
}
|
|
/* 开关 */
|
.switch-wrap {
|
display: flex;
|
align-items: center;
|
gap: 10px;
|
}
|
|
.switch-label {
|
font-size: 14px;
|
color: #666;
|
}
|
</style>
|