Mars Developer 51f8d95bf9 first commit
2025-06-26 11:24:11 +08:00

440 lines
15 KiB
Vue
Raw Permalink 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>
<div class="space-y-6">
<!-- 页面头部 -->
<div class="flex items-center justify-between">
<div>
<h1 class="text-2xl font-bold text-gray-900">添加用户</h1>
<p class="text-gray-600 mt-1">创建新的系统用户</p>
</div>
<div class="flex space-x-3">
<button
@click="$router.back()"
class="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50"
>
返回
</button>
</div>
</div>
<!-- 用户表单 -->
<div class="bg-white shadow rounded-lg">
<form @submit.prevent="handleSubmit" class="p-6 space-y-6">
<!-- 基本信息 -->
<div>
<h3 class="text-lg font-medium text-gray-900 mb-4">基本信息</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label for="name" class="block text-sm font-medium text-gray-700 mb-2">
姓名 *
</label>
<input
id="name"
v-model="userForm.name"
type="text"
required
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
placeholder="请输入用户姓名"
/>
</div>
<div>
<label for="email" class="block text-sm font-medium text-gray-700 mb-2">
邮箱地址 *
</label>
<input
id="email"
v-model="userForm.email"
type="email"
required
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
placeholder="请输入邮箱地址"
/>
</div>
<div>
<label for="phone" class="block text-sm font-medium text-gray-700 mb-2">
手机号码 *
</label>
<input
id="phone"
v-model="userForm.phone"
type="tel"
required
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
placeholder="请输入手机号码"
/>
</div>
<div>
<label for="role" class="block text-sm font-medium text-gray-700 mb-2">
用户角色 *
</label>
<select
id="role"
v-model="userForm.role"
required
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
>
<option value="">请选择用户角色</option>
<option value="user">普通用户</option>
<option value="interpreter">译员</option>
<option value="admin">管理员</option>
</select>
</div>
<div>
<label for="gender" class="block text-sm font-medium text-gray-700 mb-2">
性别
</label>
<select
id="gender"
v-model="userForm.gender"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
>
<option value="">请选择性别</option>
<option value="male"></option>
<option value="female"></option>
<option value="other">其他</option>
</select>
</div>
<div>
<label for="birthDate" class="block text-sm font-medium text-gray-700 mb-2">
出生日期
</label>
<input
id="birthDate"
v-model="userForm.birthDate"
type="date"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
/>
</div>
</div>
</div>
<!-- 账户设置 -->
<div>
<h3 class="text-lg font-medium text-gray-900 mb-4">账户设置</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label for="password" class="block text-sm font-medium text-gray-700 mb-2">
初始密码 *
</label>
<input
id="password"
v-model="userForm.password"
type="password"
required
minlength="6"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
placeholder="请输入初始密码至少6位"
/>
</div>
<div>
<label for="confirmPassword" class="block text-sm font-medium text-gray-700 mb-2">
确认密码 *
</label>
<input
id="confirmPassword"
v-model="userForm.confirmPassword"
type="password"
required
minlength="6"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
placeholder="请再次输入密码"
/>
</div>
<div>
<label for="status" class="block text-sm font-medium text-gray-700 mb-2">
账户状态 *
</label>
<select
id="status"
v-model="userForm.status"
required
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
>
<option value="active">激活</option>
<option value="inactive">未激活</option>
<option value="suspended">暂停</option>
</select>
</div>
<div class="flex items-center">
<input
id="requirePasswordChange"
v-model="userForm.requirePasswordChange"
type="checkbox"
class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
/>
<label for="requirePasswordChange" class="ml-2 block text-sm text-gray-900">
首次登录要求修改密码
</label>
</div>
</div>
</div>
<!-- 译员专业信息仅译员角色显示-->
<div v-if="userForm.role === 'interpreter'">
<h3 class="text-lg font-medium text-gray-900 mb-4">译员专业信息</h3>
<div class="space-y-6">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
专业语言 *
</label>
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
<div v-for="lang in availableLanguages" :key="lang.code" class="flex items-center">
<input
:id="`lang_${lang.code}`"
v-model="userForm.languages"
:value="lang.code"
type="checkbox"
class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
/>
<label :for="`lang_${lang.code}`" class="ml-2 block text-sm text-gray-900">
{{ lang.name }}
</label>
</div>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label for="experience" class="block text-sm font-medium text-gray-700 mb-2">
工作经验
</label>
<input
id="experience"
v-model.number="userForm.experience"
type="number"
min="0"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
placeholder="请输入工作经验"
/>
</div>
<div>
<label for="hourlyRate" class="block text-sm font-medium text-gray-700 mb-2">
时薪/小时
</label>
<input
id="hourlyRate"
v-model.number="userForm.hourlyRate"
type="number"
min="0"
step="0.01"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
placeholder="请输入时薪"
/>
</div>
</div>
<div>
<label for="specialties" class="block text-sm font-medium text-gray-700 mb-2">
专业领域
</label>
<div class="grid grid-cols-2 md:grid-cols-3 gap-4">
<div v-for="specialty in availableSpecialties" :key="specialty" class="flex items-center">
<input
:id="`specialty_${specialty}`"
v-model="userForm.specialties"
:value="specialty"
type="checkbox"
class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
/>
<label :for="`specialty_${specialty}`" class="ml-2 block text-sm text-gray-900">
{{ specialty }}
</label>
</div>
</div>
</div>
<div>
<label for="certifications" class="block text-sm font-medium text-gray-700 mb-2">
资质证书
</label>
<textarea
id="certifications"
v-model="userForm.certifications"
rows="3"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
placeholder="请输入相关资质证书信息"
></textarea>
</div>
</div>
</div>
<!-- 联系信息 -->
<div>
<h3 class="text-lg font-medium text-gray-900 mb-4">联系信息</h3>
<div class="space-y-6">
<div>
<label for="address" class="block text-sm font-medium text-gray-700 mb-2">
地址
</label>
<textarea
id="address"
v-model="userForm.address"
rows="3"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
placeholder="请输入详细地址"
></textarea>
</div>
<div>
<label for="notes" class="block text-sm font-medium text-gray-700 mb-2">
备注
</label>
<textarea
id="notes"
v-model="userForm.notes"
rows="4"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
placeholder="请输入备注信息"
></textarea>
</div>
</div>
</div>
<!-- 提交按钮 -->
<div class="flex justify-end space-x-3 pt-6 border-t border-gray-200">
<button
type="button"
@click="$router.back()"
class="px-6 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50"
>
取消
</button>
<button
type="submit"
:disabled="isSubmitting"
class="px-6 py-2 text-sm font-medium text-white bg-blue-600 border border-transparent rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed"
>
{{ isSubmitting ? '创建中...' : '创建用户' }}
</button>
</div>
</form>
</div>
</div>
</template>
<script setup>
// 页面元数据
definePageMeta({
middleware: 'auth'
})
// 页面标题
useHead({
title: '添加用户 - 翻译管理系统'
})
// 路由
const router = useRouter()
// 表单数据
const userForm = ref({
name: '',
email: '',
phone: '',
role: '',
gender: '',
birthDate: '',
password: '',
confirmPassword: '',
status: 'active',
requirePasswordChange: false,
languages: [],
experience: 0,
hourlyRate: 0,
specialties: [],
certifications: '',
address: '',
notes: ''
})
// 提交状态
const isSubmitting = ref(false)
// 可用语言列表
const availableLanguages = [
{ code: 'zh', name: '中文' },
{ code: 'en', name: '英文' },
{ code: 'ja', name: '日文' },
{ code: 'ko', name: '韩文' },
{ code: 'fr', name: '法文' },
{ code: 'de', name: '德文' },
{ code: 'es', name: '西班牙文' },
{ code: 'ru', name: '俄文' },
{ code: 'ar', name: '阿拉伯文' },
{ code: 'it', name: '意大利文' }
]
// 专业领域列表
const availableSpecialties = [
'商务会议',
'法律翻译',
'医疗翻译',
'技术翻译',
'学术会议',
'旅游陪同',
'展会翻译',
'政府会议',
'金融翻译',
'文学翻译'
]
// 处理表单提交
const handleSubmit = async () => {
try {
isSubmitting.value = true
// 基本验证
if (!userForm.value.name || !userForm.value.email || !userForm.value.phone ||
!userForm.value.role || !userForm.value.password || !userForm.value.confirmPassword) {
throw new Error('请填写所有必填字段')
}
// 密码确认验证
if (userForm.value.password !== userForm.value.confirmPassword) {
throw new Error('两次输入的密码不一致')
}
// 译员角色语言验证
if (userForm.value.role === 'interpreter' && userForm.value.languages.length === 0) {
throw new Error('译员角色需要选择至少一种专业语言')
}
// 模拟API调用
await new Promise(resolve => setTimeout(resolve, 1000))
// 创建用户数据
const newUser = {
id: `usr_${Date.now()}`,
...userForm.value,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
}
// 移除确认密码字段
delete newUser.confirmPassword
console.log('创建用户:', newUser)
// 显示成功消息
alert('用户创建成功')
// 返回用户列表页面
router.push('/users')
} catch (error) {
alert(error.message || '创建用户失败,请重试')
} finally {
isSubmitting.value = false
}
}
</script>