mirror of https://github.com/veypi/OneAuth.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
631 lines
32 KiB
HTML
631 lines
32 KiB
HTML
<!doctype html>
|
|
<html>
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>多字段表格管理界面</title>
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<style>
|
|
@font-face {
|
|
font-family: 'LucideIcons';
|
|
src: url(https://cdn.jsdelivr.net/npm/lucide-static@latest/font/Lucide.ttf) format('truetype');
|
|
}
|
|
.lucide {
|
|
font-family: 'LucideIcons';
|
|
font-style: normal;
|
|
font-weight: normal;
|
|
font-variant: normal;
|
|
text-rendering: auto;
|
|
line-height: 1;
|
|
-webkit-font-smoothing: antialiased;
|
|
-moz-osx-font-smoothing: grayscale;
|
|
}
|
|
body {
|
|
font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
background-color: #f8fafc;
|
|
}
|
|
.modal-backdrop {
|
|
background-color: rgba(0, 0, 0, 0.5);
|
|
transition: opacity 0.3s ease-in-out;
|
|
}
|
|
.modal-content {
|
|
transition: transform 0.3s ease-in-out;
|
|
}
|
|
.hidden {
|
|
display: none;
|
|
}
|
|
::-webkit-scrollbar {
|
|
width: 6px;
|
|
height: 6px;
|
|
}
|
|
::-webkit-scrollbar-track {
|
|
background: #f1f1f1;
|
|
border-radius: 10px;
|
|
}
|
|
::-webkit-scrollbar-thumb {
|
|
background: #cbd5e1;
|
|
border-radius: 10px;
|
|
}
|
|
::-webkit-scrollbar-thumb:hover {
|
|
background: #94a3b8;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body class="p-6 md:p-10">
|
|
<div class="max-w-7xl mx-auto bg-white p-6 rounded-lg shadow-lg">
|
|
<h1 class="text-2xl font-semibold text-gray-800 mb-6">客户信息管理</h1>
|
|
|
|
<div class="flex flex-col md:flex-row justify-between items-center mb-6 gap-4">
|
|
<div class="relative w-full md:w-1/3">
|
|
<input
|
|
type="text"
|
|
placeholder="搜索姓名或记录编号..."
|
|
!value="searchQuery"
|
|
@input="searchQuery = $event.target.value"
|
|
class="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
|
/>
|
|
<span class="lucide absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400">search</span>
|
|
</div>
|
|
<button
|
|
@click="openModal('addEditModal', 'add')"
|
|
class="w-full md:w-auto bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2 px-4 rounded-lg flex items-center justify-center gap-2 transition duration-150 ease-in-out"
|
|
>
|
|
<span class="lucide">plus</span> 新增记录
|
|
</button>
|
|
</div>
|
|
|
|
<div class="overflow-x-auto">
|
|
<table class="min-w-full divide-y divide-gray-200 border border-gray-200 rounded-lg">
|
|
<thead class="bg-gray-50">
|
|
<tr>
|
|
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
记录编号
|
|
</th>
|
|
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
姓名
|
|
</th>
|
|
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
状态
|
|
</th>
|
|
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
创建日期
|
|
</th>
|
|
<th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
操作
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="bg-white divide-y divide-gray-200">
|
|
<tr v-for="(record, index) in filteredRecords" :key="index">
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{{ record.id }}</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{{ record.name }}</td>
|
|
<td class="px-6 py-4 whitespace-nowrap">
|
|
<span
|
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full"
|
|
:class="{
|
|
'bg-green-100 text-green-800': record.status === 'active',
|
|
'bg-yellow-100 text-yellow-800': record.status === 'pending',
|
|
'bg-red-100 text-red-800': record.status === 'inactive',
|
|
}"
|
|
>
|
|
{{ record.status }}
|
|
</span>
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{{ record.createdAt }}</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-center text-sm font-medium space-x-2">
|
|
<button
|
|
@click="openModal('viewModal', record)"
|
|
title="查看"
|
|
class="text-blue-600 hover:text-blue-800 transition duration-150 ease-in-out"
|
|
>
|
|
<span class="lucide">eye</span>
|
|
</button>
|
|
<button
|
|
@click="openModal('addEditModal', 'edit', record)"
|
|
title="编辑"
|
|
class="text-yellow-600 hover:text-yellow-800 transition duration-150 ease-in-out"
|
|
>
|
|
<span class="lucide">pencil</span>
|
|
</button>
|
|
<button
|
|
@click="openModal('deleteConfirmModal', record)"
|
|
title="删除"
|
|
class="text-red-600 hover:text-red-800 transition duration-150 ease-in-out"
|
|
>
|
|
<span class="lucide">trash-2</span>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="mt-6 flex justify-center">
|
|
<nav class="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination">
|
|
<a href="#" class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50">
|
|
<span class="sr-only">Previous</span>
|
|
<span class="lucide h-5 w-5">chevron-left</span>
|
|
</a>
|
|
<a href="#" aria-current="page" class="z-10 bg-blue-50 border-blue-500 text-blue-600 relative inline-flex items-center px-4 py-2 border text-sm font-medium">
|
|
1
|
|
</a>
|
|
<a href="#" class="bg-white border-gray-300 text-gray-500 hover:bg-gray-50 relative inline-flex items-center px-4 py-2 border text-sm font-medium">
|
|
2
|
|
</a>
|
|
<span class="relative inline-flex items-center px-4 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-700">
|
|
...
|
|
</span>
|
|
<a href="#" class="bg-white border-gray-300 text-gray-500 hover:bg-gray-50 relative inline-flex items-center px-4 py-2 border text-sm font-medium">
|
|
10
|
|
</a>
|
|
<a href="#" class="relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50">
|
|
<span class="sr-only">Next</span>
|
|
<span class="lucide h-5 w-5">chevron-right</span>
|
|
</a>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 查看弹窗 -->
|
|
<div id="viewModal" class="fixed inset-0 z-50 hidden items-center justify-center p-4 modal-backdrop">
|
|
<div class="bg-white rounded-lg shadow-xl w-full max-w-3xl max-h-[90vh] overflow-hidden flex flex-col modal-content transform scale-95">
|
|
<div class="flex justify-between items-center p-4 border-b border-gray-200">
|
|
<h2 class="text-xl font-semibold text-gray-800">记录详情 ({{ currentRecord.id }})</h2>
|
|
<button @click="closeModal('viewModal')" class="text-gray-400 hover:text-gray-600">
|
|
<span class="lucide text-2xl">x</span>
|
|
</button>
|
|
</div>
|
|
<div class="p-6 overflow-y-auto">
|
|
<!-- 显示当前记录详细信息 -->
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-x-6 gap-y-4">
|
|
<fieldset class="border border-gray-300 p-4 rounded-md md:col-span-2">
|
|
<legend class="text-lg font-medium text-gray-700 px-2">基本信息</legend>
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 mt-2">
|
|
<div><strong class="text-gray-600">ID:</strong> <span class="text-gray-800">{{ currentRecord.id }}</span></div>
|
|
<div><strong class="text-gray-600">记录编号:</strong> <span class="text-gray-800">{{ currentRecord.recordNumber }}</span></div>
|
|
<div><strong class="text-gray-600">状态:</strong> <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full" :class="statusClass(currentRecord.status)">{{ currentRecord.status }}</span></div>
|
|
<div><strong class="text-gray-600">创建日期:</strong> <span class="text-gray-800">{{ currentRecord.createdAt }}</span></div>
|
|
<div><strong class="text-gray-600">创建人:</strong> <span class="text-gray-800">{{ currentRecord.createdBy }}</span></div>
|
|
<div><strong class="text-gray-600">最后修改日期:</strong> <span class="text-gray-800">{{ currentRecord.lastModifiedAt }}</span></div>
|
|
<div><strong class="text-gray-600">修改人:</strong> <span class="text-gray-800">{{ currentRecord.lastModifiedBy }}</span></div>
|
|
<div><strong class="text-gray-600">类别:</strong> <span class="text-gray-800">{{ currentRecord.category }}</span></div>
|
|
<div><strong class="text-gray-600">类型:</strong> <span class="text-gray-800">{{ currentRecord.type }}</span></div>
|
|
<div><strong class="text-gray-600">优先级:</strong> <span class="text-gray-800">{{ currentRecord.priority }}</span></div>
|
|
</div>
|
|
</fieldset>
|
|
|
|
<fieldset class="border border-gray-300 p-4 rounded-md md:col-span-2">
|
|
<legend class="text-lg font-medium text-gray-700 px-2">联系信息</legend>
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 mt-2">
|
|
<div><strong class="text-gray-600">姓名:</strong> <span class="text-gray-800">{{ currentRecord.fullName }}</span></div>
|
|
<div><strong class="text-gray-600">邮箱:</strong> <span class="text-gray-800">{{ currentRecord.email }}</span></div>
|
|
<div><strong class="text-gray-600">电话:</strong> <span class="text-gray-800">{{ currentRecord.phone }}</span></div>
|
|
<div class="sm:col-span-2"><strong class="text-gray-600">地址1:</strong> <span class="text-gray-800">{{ currentRecord.address1 }}</span></div>
|
|
<div><strong class="text-gray-600">地址2:</strong> <span class="text-gray-800">{{ currentRecord.address2 }}</span></div>
|
|
<div><strong class="text-gray-600">城市:</strong> <span class="text-gray-800">{{ currentRecord.city }}</span></div>
|
|
<div><strong class="text-gray-600">省份:</strong> <span class="text-gray-800">{{ currentRecord.province }}</span></div>
|
|
<div><strong class="text-gray-600">邮编:</strong> <span class="text-gray-800">{{ currentRecord.postalCode }}</span></div>
|
|
<div><strong class="text-gray-600">国家:</strong> <span class="text-gray-800">{{ currentRecord.country }}</span></div>
|
|
</div>
|
|
</fieldset>
|
|
|
|
<fieldset class="border border-gray-300 p-4 rounded-md md:col-span-2">
|
|
<legend class="text-lg font-medium text-gray-700 px-2">其他信息</legend>
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 mt-2">
|
|
<div><strong class="text-gray-600">开始日期:</strong> <span class="text-gray-800">{{ currentRecord.startDate }}</span></div>
|
|
<div><strong class="text-gray-600">结束日期:</strong> <span class="text-gray-800">{{ currentRecord.endDate }}</span></div>
|
|
<div><strong class="text-gray-600">金额:</strong> <span class="text-gray-800">{{ currentRecord.amount }}</span></div>
|
|
<div><strong class="text-gray-600">数量:</strong> <span class="text-gray-800">{{ currentRecord.quantity }}</span></div>
|
|
<div class="sm:col-span-2 md:col-span-3"><strong class="text-gray-600">描述:</strong> <p class="text-gray-800 mt-1">{{ currentRecord.description }}</p></div>
|
|
<div class="sm:col-span-2 md:col-span-3"><strong class="text-gray-600">备注:</strong> <p class="text-gray-800 mt-1">{{ currentRecord.notes }}</p></div>
|
|
</div>
|
|
</fieldset>
|
|
</div>
|
|
</div>
|
|
<div class="flex justify-end p-4 border-t border-gray-200 bg-gray-50">
|
|
<button @click="closeModal('viewModal')" class="bg-gray-500 hover:bg-gray-600 text-white font-semibold py-2 px-4 rounded-lg transition duration-150 ease-in-out">
|
|
关闭
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 新增/编辑弹窗 -->
|
|
<div id="addEditModal" class="fixed inset-0 z-50 hidden items-center justify-center p-4 modal-backdrop">
|
|
<div class="bg-white rounded-lg shadow-xl w-full max-w-4xl max-h-[90vh] overflow-hidden flex flex-col modal-content transform scale-95">
|
|
<div class="flex justify-between items-center p-4 border-b border-gray-200">
|
|
<h2 id="modalTitle" class="text-xl font-semibold text-gray-800">{{ isEditMode ? '编辑记录' : '新增记录' }}</h2>
|
|
<button @click="closeModal('addEditModal')" class="text-gray-400 hover:text-gray-600">
|
|
<span class="lucide text-2xl">x</span>
|
|
</button>
|
|
</div>
|
|
<form class="flex-grow overflow-y-auto p-6 space-y-6">
|
|
<fieldset class="border border-gray-300 p-4 rounded-md">
|
|
<legend class="text-lg font-medium text-gray-700 px-2">基本信息</legend>
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 mt-2">
|
|
<div>
|
|
<label for="recordNumber" class="block text-sm font-medium text-gray-700">记录编号</label>
|
|
<input
|
|
type="text"
|
|
id="recordNumber"
|
|
name="recordNumber"
|
|
!value="currentRecord.recordNumber"
|
|
readonly
|
|
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm bg-gray-100 focus:outline-none sm:text-sm"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label for="status" class="block text-sm font-medium text-gray-700">状态 *</label>
|
|
<select
|
|
id="status"
|
|
name="status"
|
|
!value="currentRecord.status"
|
|
@change="currentRecord.status = $event.target.value"
|
|
required
|
|
class="mt-1 block w-full px-3 py-2 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
|
>
|
|
<option value="active">活动</option>
|
|
<option value="pending">待定</option>
|
|
<option value="inactive">非活动</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label for="category" class="block text-sm font-medium text-gray-700">类别</label>
|
|
<input
|
|
type="text"
|
|
id="category"
|
|
name="category"
|
|
!value="currentRecord.category"
|
|
@input="currentRecord.category = $event.target.value"
|
|
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label for="type" class="block text-sm font-medium text-gray-700">类型</label>
|
|
<input
|
|
type="text"
|
|
id="type"
|
|
name="type"
|
|
!value="currentRecord.type"
|
|
@input="currentRecord.type = $event.target.value"
|
|
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label for="priority" class="block text-sm font-medium text-gray-700">优先级</label>
|
|
<select
|
|
id="priority"
|
|
name="priority"
|
|
!value="currentRecord.priority"
|
|
@change="currentRecord.priority = $event.target.value"
|
|
class="mt-1 block w-full px-3 py-2 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
|
>
|
|
<option value="high">高</option>
|
|
<option value="medium">中</option>
|
|
<option value="low">低</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</fieldset>
|
|
|
|
<fieldset class="border border-gray-300 p-4 rounded-md">
|
|
<legend class="text-lg font-medium text-gray-700 px-2">联系信息</legend>
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 mt-2">
|
|
<div>
|
|
<label for="fullName" class="block text-sm font-medium text-gray-700">姓名 *</label>
|
|
<input
|
|
type="text"
|
|
id="fullName"
|
|
name="fullName"
|
|
!value="currentRecord.fullName"
|
|
@input="currentRecord.fullName = $event.target.value"
|
|
required
|
|
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label for="email" class="block text-sm font-medium text-gray-700">邮箱</label>
|
|
<input
|
|
type="email"
|
|
id="email"
|
|
name="email"
|
|
!value="currentRecord.email"
|
|
@input="currentRecord.email = $event.target.value"
|
|
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label for="phone" class="block text-sm font-medium text-gray-700">电话</label>
|
|
<input
|
|
type="tel"
|
|
id="phone"
|
|
name="phone"
|
|
!value="currentRecord.phone"
|
|
@input="currentRecord.phone = $event.target.value"
|
|
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
|
/>
|
|
</div>
|
|
<div class="sm:col-span-2">
|
|
<label for="address1" class="block text-sm font-medium text-gray-700">地址1</label>
|
|
<input
|
|
type="text"
|
|
id="address1"
|
|
name="address1"
|
|
!value="currentRecord.address1"
|
|
@input="currentRecord.address1 = $event.target.value"
|
|
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label for="address2" class="block text-sm font-medium text-gray-700">地址2</label>
|
|
<input
|
|
type="text"
|
|
id="address2"
|
|
name="address2"
|
|
!value="currentRecord.address2"
|
|
@input="currentRecord.address2 = $event.target.value"
|
|
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label for="city" class="block text-sm font-medium text-gray-700">城市</label>
|
|
<input
|
|
type="text"
|
|
id="city"
|
|
name="city"
|
|
!value="currentRecord.city"
|
|
@input="currentRecord.city = $event.target.value"
|
|
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label for="province" class="block text-sm font-medium text-gray-700">省份</label>
|
|
<input
|
|
type="text"
|
|
id="province"
|
|
name="province"
|
|
!value="currentRecord.province"
|
|
@input="currentRecord.province = $event.target.value"
|
|
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label for="postalCode" class="block text-sm font-medium text-gray-700">邮编</label>
|
|
<input
|
|
type="text"
|
|
id="postalCode"
|
|
name="postalCode"
|
|
!value="currentRecord.postalCode"
|
|
@input="currentRecord.postalCode = $event.target.value"
|
|
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label for="country" class="block text-sm font-medium text-gray-700">国家</label>
|
|
<input
|
|
type="text"
|
|
id="country"
|
|
name="country"
|
|
!value="currentRecord.country"
|
|
@input="currentRecord.country = $event.target.value"
|
|
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</fieldset>
|
|
|
|
<fieldset class="border border-gray-300 p-4 rounded-md">
|
|
<legend class="text-lg font-medium text-gray-700 px-2">其他信息</legend>
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 mt-2">
|
|
<div>
|
|
<label for="startDate" class="block text-sm font-medium text-gray-700">开始日期</label>
|
|
<input
|
|
type="date"
|
|
id="startDate"
|
|
name="startDate"
|
|
!value="currentRecord.startDate"
|
|
@input="currentRecord.startDate = $event.target.value"
|
|
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label for="endDate" class="block text-sm font-medium text-gray-700">结束日期</label>
|
|
<input
|
|
type="date"
|
|
id="endDate"
|
|
name="endDate"
|
|
!value="currentRecord.endDate"
|
|
@input="currentRecord.endDate = $event.target.value"
|
|
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label for="amount" class="block text-sm font-medium text-gray-700">金额</label>
|
|
<input
|
|
type="number"
|
|
id="amount"
|
|
name="amount"
|
|
step="0.01"
|
|
!value="currentRecord.amount"
|
|
@input="currentRecord.amount = $event.target.value"
|
|
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label for="quantity" class="block text-sm font-medium text-gray-700">数量</label>
|
|
<input
|
|
type="number"
|
|
id="quantity"
|
|
name="quantity"
|
|
!value="currentRecord.quantity"
|
|
@input="currentRecord.quantity = $event.target.value"
|
|
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
|
/>
|
|
</div>
|
|
<div class="sm:col-span-2 md:col-span-3">
|
|
<label for="description" class="block text-sm font-medium text-gray-700">描述</label>
|
|
<textarea
|
|
id="description"
|
|
name="description"
|
|
rows="3"
|
|
!value="currentRecord.description"
|
|
@input="currentRecord.description = $event.target.value"
|
|
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
|
></textarea>
|
|
</div>
|
|
<div class="sm:col-span-2 md:col-span-3">
|
|
<label for="notes" class="block text-sm font-medium text-gray-700">备注</label>
|
|
<textarea
|
|
id="notes"
|
|
name="notes"
|
|
rows="3"
|
|
!value="currentRecord.notes"
|
|
@input="currentRecord.notes = $event.target.value"
|
|
class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
|
></textarea>
|
|
</div>
|
|
</div>
|
|
</fieldset>
|
|
</form>
|
|
<div class="flex justify-end p-4 border-t border-gray-200 bg-gray-50">
|
|
<button @click="closeModal('addEditModal')" class="bg-gray-200 hover:bg-gray-300 text-gray-800 font-semibold py-2 px-4 rounded-lg mr-2 transition duration-150 ease-in-out">
|
|
取消
|
|
</button>
|
|
<button @click="saveRecord" class="bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2 px-4 rounded-lg transition duration-150 ease-in-out">
|
|
保存
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 删除确认弹窗 -->
|
|
<div id="deleteConfirmModal" class="fixed inset-0 z-50 hidden items-center justify-center p-4 modal-backdrop">
|
|
<div class="bg-white rounded-lg shadow-xl w-full max-w-md modal-content transform scale-95">
|
|
<div class="flex justify-between items-center p-4 border-b border-gray-200">
|
|
<h2 class="text-lg font-semibold text-gray-800">确认删除</h2>
|
|
<button @click="closeModal('deleteConfirmModal')" class="text-gray-400 hover:text-gray-600">
|
|
<span class="lucide text-2xl">x</span>
|
|
</button>
|
|
</div>
|
|
<div class="p-6">
|
|
<p class="text-sm text-gray-600">您确定要删除记录 "{{ currentRecord.recordNumber }}" 吗?此操作无法撤销。</p>
|
|
</div>
|
|
<div class="flex justify-end p-4 border-t border-gray-200 bg-gray-50">
|
|
<button @click="closeModal('deleteConfirmModal')" class="bg-gray-200 hover:bg-gray-300 text-gray-800 font-semibold py-2 px-4 rounded-lg mr-2 transition duration-150 ease-in-out">
|
|
取消
|
|
</button>
|
|
<button @click="confirmDelete" class="bg-red-600 hover:bg-red-700 text-white font-semibold py-2 px-4 rounded-lg transition duration-150 ease-in-out">
|
|
确认删除
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
<script setup>
|
|
searchQuery = '';
|
|
records = [
|
|
{ id: 1, recordNumber: 'REC-001', name: '张三', status: 'active', createdAt: '2024-01-15', category: '重要客户', type: '企业' },
|
|
{ id: 2, recordNumber: 'REC-002', name: '李四', status: 'pending', createdAt: '2024-02-20', category: '普通客户', type: '个人' },
|
|
{ id: 3, recordNumber: 'REC-003', name: '王五', status: 'inactive', createdAt: '2024-03-10', category: '潜在客户', type: '企业' },
|
|
];
|
|
currentRecord = {};
|
|
isEditMode = false;
|
|
|
|
filteredRecords = () => {
|
|
return records.filter((record) =>
|
|
record.recordNumber.includes(searchQuery) || record.name.includes(searchQuery)
|
|
);
|
|
};
|
|
|
|
openModal = (modalId, mode, recordData) => {
|
|
const modal = document.getElementById(modalId);
|
|
if (!modal) return;
|
|
|
|
if (mode === 'add') {
|
|
isEditMode = false;
|
|
currentRecord = { recordNumber: '自动生成', status: 'active', category: '', type: '' };
|
|
} else if (mode === 'edit') {
|
|
isEditMode = true;
|
|
currentRecord = { ...recordData };
|
|
} else if (mode === 'view') {
|
|
currentRecord = { ...recordData };
|
|
}
|
|
|
|
modal.classList.remove('hidden');
|
|
modal.classList.add('flex');
|
|
|
|
requestAnimationFrame(() => {
|
|
const backdrop = modal.querySelector('.modal-backdrop') || modal;
|
|
const content = modal.querySelector('.modal-content');
|
|
backdrop.style.opacity = '1';
|
|
if (content) content.style.transform = 'scale(1)';
|
|
});
|
|
|
|
document.body.style.overflow = 'hidden';
|
|
};
|
|
|
|
closeModal = (modalId) => {
|
|
const modal = document.getElementById(modalId);
|
|
if (!modal) return;
|
|
|
|
const backdrop = modal.querySelector('.modal-backdrop') || modal;
|
|
const content = modal.querySelector('.modal-content');
|
|
backdrop.style.opacity = '0';
|
|
if (content) content.style.transform = 'scale(0.95)';
|
|
|
|
setTimeout(() => {
|
|
modal.classList.add('hidden');
|
|
modal.classList.remove('flex');
|
|
|
|
if (!document.querySelector('.modal-backdrop:not(.hidden)')) {
|
|
document.body.style.overflow = 'auto';
|
|
}
|
|
}, 300);
|
|
};
|
|
|
|
saveRecord = () => {
|
|
if (isEditMode) {
|
|
const index = records.findIndex((record) => record.id === currentRecord.id);
|
|
records[index] = { ...currentRecord };
|
|
} else {
|
|
currentRecord.id = records.length + 1;
|
|
records.push({ ...currentRecord });
|
|
}
|
|
closeModal('addEditModal');
|
|
};
|
|
|
|
confirmDelete = () => {
|
|
records = records.filter((record) => record.id !== currentRecord.id);
|
|
closeModal('deleteConfirmModal');
|
|
};
|
|
|
|
statusClass = (status) => {
|
|
if (status === 'active') return 'bg-green-100 text-green-800';
|
|
if (status === 'pending') return 'bg-yellow-100 text-yellow-800';
|
|
if (status === 'inactive') return 'bg-red-100 text-red-800';
|
|
};
|
|
</script>
|
|
<script>
|
|
// 初始化:确保所有弹窗开始时都是隐藏的,并设置初始状态
|
|
const modals = document.querySelectorAll('.modal-backdrop');
|
|
modals.forEach((modal) => {
|
|
modal.classList.add('hidden');
|
|
modal.style.opacity = '0';
|
|
const content = modal.querySelector('.modal-content');
|
|
if (content) {
|
|
content.style.transform = 'scale(0.95)';
|
|
}
|
|
});
|
|
|
|
// 点击弹窗外部区域关闭 (可选)
|
|
window.addEventListener('click', (event) => {
|
|
const modals = document.querySelectorAll('.modal-backdrop');
|
|
modals.forEach((modal) => {
|
|
if (event.target === modal) {
|
|
closeModal(modal.id);
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
</html>
|