This repository has been archived on 2025-10-29. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
FPGA_WebLab/src/views/User/AddBoardDialog.vue

251 lines
5.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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: '',
ipAddr: '',
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 = '';
form.ipAddr = '';
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>