251 lines
5.9 KiB
Vue
251 lines
5.9 KiB
Vue
<template>
|
||
<dialog class="modal" :class="{ 'modal-open': visible }">
|
||
<div class="modal-box w-96 max-w-md">
|
||
<h3 class="text-lg font-bold mb-4">新增实验板</h3>
|
||
|
||
<form @submit.prevent="handleSubmit" class="space-y-4">
|
||
<!-- 实验板名称 -->
|
||
<div class="form-control">
|
||
<label class="label">
|
||
<span class="label-text">实验板名称 <span class="text-error">*</span></span>
|
||
</label>
|
||
<input
|
||
v-model="form.name"
|
||
type="text"
|
||
placeholder="请输入实验板名称"
|
||
class="input input-bordered"
|
||
:class="{ 'input-error': errors.name }"
|
||
required
|
||
/>
|
||
<label v-if="errors.name" class="label">
|
||
<span class="label-text-alt text-error">{{ errors.name }}</span>
|
||
</label>
|
||
</div>
|
||
|
||
<!-- IP 地址 -->
|
||
<div class="form-control">
|
||
<label class="label">
|
||
<span class="label-text">IP 地址 <span class="text-error">*</span></span>
|
||
</label>
|
||
<input
|
||
v-model="form.ipAddr"
|
||
type="text"
|
||
placeholder="例如:192.168.1.100"
|
||
class="input input-bordered"
|
||
:class="{ 'input-error': errors.ipAddr }"
|
||
required
|
||
/>
|
||
<label v-if="errors.ipAddr" class="label">
|
||
<span class="label-text-alt text-error">{{ errors.ipAddr }}</span>
|
||
</label>
|
||
</div>
|
||
|
||
<!-- 端口号 -->
|
||
<div class="form-control">
|
||
<label class="label">
|
||
<span class="label-text">端口号 <span class="text-error">*</span></span>
|
||
</label>
|
||
<input
|
||
v-model.number="form.port"
|
||
type="number"
|
||
placeholder="例如:1234"
|
||
min="1"
|
||
max="65535"
|
||
class="input input-bordered"
|
||
:class="{ 'input-error': errors.port }"
|
||
required
|
||
/>
|
||
<label v-if="errors.port" class="label">
|
||
<span class="label-text-alt text-error">{{ errors.port }}</span>
|
||
</label>
|
||
</div>
|
||
|
||
<!-- 操作按钮 -->
|
||
<div class="modal-action">
|
||
<button
|
||
type="button"
|
||
class="btn btn-ghost"
|
||
@click="handleCancel"
|
||
:disabled="isSubmitting"
|
||
>
|
||
取消
|
||
</button>
|
||
<button
|
||
type="submit"
|
||
class="btn btn-primary"
|
||
:class="{ 'loading': isSubmitting }"
|
||
:disabled="isSubmitting"
|
||
>
|
||
{{ isSubmitting ? '添加中...' : '确认添加' }}
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<!-- 点击背景关闭 -->
|
||
<form method="dialog" class="modal-backdrop">
|
||
<button type="button" @click="handleCancel">close</button>
|
||
</form>
|
||
</dialog>
|
||
</template>
|
||
|
||
<script lang="ts" setup>
|
||
import { ref, reactive, watch } from 'vue';
|
||
import { useBoardManager } from '../../utils/BoardManager';
|
||
|
||
// Props 和 Emits
|
||
interface Props {
|
||
visible: boolean;
|
||
}
|
||
|
||
interface Emits {
|
||
(e: 'update:visible', value: boolean): void;
|
||
(e: 'success'): void;
|
||
}
|
||
|
||
const props = defineProps<Props>();
|
||
const emit = defineEmits<Emits>();
|
||
|
||
// 使用 BoardManager
|
||
const boardManager = useBoardManager()!;
|
||
|
||
// 表单数据
|
||
const form = reactive({
|
||
name: 'Board1',
|
||
ipAddr: '169.254.103.0',
|
||
port: 1234
|
||
});
|
||
|
||
// 表单错误
|
||
const errors = reactive({
|
||
name: '',
|
||
ipAddr: '',
|
||
port: ''
|
||
});
|
||
|
||
// 提交状态
|
||
const isSubmitting = ref(false);
|
||
|
||
// IP地址验证正则
|
||
const IP_REGEX = /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
||
|
||
// 验证表单
|
||
function validateForm(): boolean {
|
||
// 清空之前的错误
|
||
errors.name = '';
|
||
errors.ipAddr = '';
|
||
errors.port = '';
|
||
|
||
let isValid = true;
|
||
|
||
// 验证名称
|
||
if (!form.name.trim()) {
|
||
errors.name = '请输入实验板名称';
|
||
isValid = false;
|
||
} else if (form.name.trim().length < 2) {
|
||
errors.name = '实验板名称至少需要2个字符';
|
||
isValid = false;
|
||
} else if (form.name.trim().length > 50) {
|
||
errors.name = '实验板名称不能超过50个字符';
|
||
isValid = false;
|
||
}
|
||
|
||
// 验证IP地址
|
||
if (!form.ipAddr.trim()) {
|
||
errors.ipAddr = '请输入IP地址';
|
||
isValid = false;
|
||
} else if (!IP_REGEX.test(form.ipAddr.trim())) {
|
||
errors.ipAddr = '请输入有效的IP地址格式';
|
||
isValid = false;
|
||
}
|
||
|
||
// 验证端口号
|
||
if (!form.port) {
|
||
errors.port = '请输入端口号';
|
||
isValid = false;
|
||
} else if (form.port < 1 || form.port > 65535) {
|
||
errors.port = '端口号必须在1-65535之间';
|
||
isValid = false;
|
||
} else if (!Number.isInteger(form.port)) {
|
||
errors.port = '端口号必须是整数';
|
||
isValid = false;
|
||
}
|
||
|
||
return isValid;
|
||
}
|
||
|
||
// 重置表单
|
||
function resetForm() {
|
||
form.name = 'Board1';
|
||
form.ipAddr = '169.254.103.0';
|
||
form.port = 1234;
|
||
errors.name = '';
|
||
errors.ipAddr = '';
|
||
errors.port = '';
|
||
}
|
||
|
||
// 处理取消
|
||
function handleCancel() {
|
||
if (!isSubmitting.value) {
|
||
emit('update:visible', false);
|
||
resetForm();
|
||
}
|
||
}
|
||
|
||
// 处理提交
|
||
async function handleSubmit() {
|
||
if (!validateForm()) {
|
||
return;
|
||
}
|
||
|
||
isSubmitting.value = true;
|
||
|
||
try {
|
||
const success = await boardManager.addBoard(
|
||
form.name.trim(),
|
||
form.ipAddr.trim(),
|
||
form.port
|
||
);
|
||
|
||
if (success) {
|
||
emit('success');
|
||
resetForm();
|
||
}
|
||
} catch (error) {
|
||
console.error('添加实验板失败:', error);
|
||
} finally {
|
||
isSubmitting.value = false;
|
||
}
|
||
}
|
||
|
||
// 监听对话框显示状态,重置表单
|
||
watch(() => props.visible, (newVisible) => {
|
||
if (newVisible) {
|
||
resetForm();
|
||
}
|
||
});
|
||
</script>
|
||
|
||
<style scoped lang="postcss">
|
||
@import "@/assets/main.css";
|
||
|
||
.form-control {
|
||
@apply w-full;
|
||
}
|
||
|
||
.label-text {
|
||
@apply font-medium;
|
||
}
|
||
|
||
.input-error {
|
||
@apply border-error;
|
||
}
|
||
|
||
.text-error {
|
||
@apply text-red-500;
|
||
}
|
||
|
||
.loading {
|
||
@apply opacity-50 cursor-not-allowed;
|
||
}
|
||
</style> |