当前位置: 首页 > news >正文

html+css+vue实现增删改查

代码如下:

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>优化版 Vue.js CRUD 示例</title><script src="https://unpkg.com/vue@3/dist/vue.global.js"></script><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"><style>* {margin: 0;padding: 0;box-sizing: border-box;font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;}body {background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);color: #333;padding: 20px;min-height: 100vh;}.container {max-width: 1000px;margin: 0 auto;background: white;border-radius: 15px;box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);padding: 30px;position: relative;overflow: hidden;}.container::before {content: '';position: absolute;top: 0;left: 0;right: 0;height: 5px;background: linear-gradient(90deg, #3498db, #2ecc71, #f39c12, #e74c3c);}h1 {text-align: center;margin: 15px 0 30px;color: #2c3e50;font-weight: 600;position: relative;padding-bottom: 15px;}h1::after {content: '';position: absolute;bottom: 0;left: 50%;transform: translateX(-50%);width: 80px;height: 4px;background: linear-gradient(90deg, #3498db, #2ecc71);border-radius: 2px;}.header {display: flex;justify-content: space-between;align-items: center;margin-bottom: 25px;flex-wrap: wrap;gap: 15px;padding: 20px;background: #f8fafc;border-radius: 10px;box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);}.search-container {position: relative;flex-grow: 1;}.search-box {padding: 12px 45px 12px 15px;border: 2px solid #e2e8f0;border-radius: 8px;width: 100%;font-size: 16px;transition: all 0.3s;box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);}.search-box:focus {border-color: #3498db;box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.2);outline: none;}.search-icon {position: absolute;right: 15px;top: 50%;transform: translateY(-50%);color: #64748b;}.search-clear {position: absolute;right: 40px;top: 50%;transform: translateY(-50%);background: none;border: none;color: #94a3b8;cursor: pointer;font-size: 16px;transition: color 0.3s;}.search-clear:hover {color: #e74c3c;}.btn {padding: 12px 24px;border: none;border-radius: 8px;cursor: pointer;font-weight: 500;transition: all 0.3s;display: flex;align-items: center;gap: 8px;}.btn-primary {background: linear-gradient(135deg, #3498db 0%, #2980b9 100%);color: white;box-shadow: 0 4px 6px rgba(52, 152, 219, 0.3);}.btn-primary:hover {transform: translateY(-2px);box-shadow: 0 6px 8px rgba(52, 152, 219, 0.4);}.btn-edit {background: linear-gradient(135deg, #f39c12 0%, #e67e22 100%);color: white;box-shadow: 0 4px 6px rgba(243, 156, 18, 0.3);}.btn-edit:hover {transform: translateY(-2px);box-shadow: 0 6px 8px rgba(243, 156, 18, 0.4);}.btn-delete {background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%);color: white;box-shadow: 0 4px 6px rgba(231, 76, 60, 0.3);}.btn-delete:hover {transform: translateY(-2px);box-shadow: 0 6px 8px rgba(231, 76, 60, 0.4);}table {width: 100%;border-collapse: separate;border-spacing: 0;margin-top: 20px;border-radius: 10px;overflow: hidden;box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);}th, td {padding: 16px;text-align: left;border-bottom: 1px solid #e2e8f0;}th {background: linear-gradient(to bottom, #f8fafc, #f1f5f9);font-weight: 600;color: #334155;}tr:last-child td {border-bottom: none;}tr:hover {background-color: #f8fafc;}.actions {display: flex;gap: 10px;}.modal {position: fixed;top: 0;left: 0;width: 100%;height: 100%;background-color: rgba(0, 0, 0, 0.5);display: flex;justify-content: center;align-items: center;z-index: 1000;opacity: 0;animation: fadeIn 0.3s forwards;}@keyframes fadeIn {to { opacity: 1; }}.modal-content {background-color: white;padding: 30px;border-radius: 15px;width: 500px;max-width: 90%;box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);transform: translateY(20px);animation: slideUp 0.3s forwards;}@keyframes slideUp {to { transform: translateY(0); }}.modal-header {display: flex;justify-content: space-between;align-items: center;margin-bottom: 25px;padding-bottom: 15px;border-bottom: 1px solid #e2e8f0;}.modal-title {font-size: 22px;font-weight: 600;color: #2c3e50;}.modal-close {background: none;border: none;font-size: 24px;cursor: pointer;color: #94a3b8;transition: color 0.3s;}.modal-close:hover {color: #e74c3c;}.form-group {margin-bottom: 20px;position: relative;}label {display: block;margin-bottom: 8px;font-weight: 500;color: #334155;}input, select {width: 100%;padding: 14px;border: 2px solid #e2e8f0;border-radius: 8px;font-size: 16px;transition: all 0.3s;}input:focus, select:focus {border-color: #3498db;box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.2);outline: none;}.error-message {color: #e74c3c;font-size: 14px;margin-top: 5px;display: none;}input.invalid, select.invalid {border-color: #e74c3c;}input.invalid + .error-message, select.invalid + .error-message {display: block;}.form-actions {display: flex;justify-content: flex-end;gap: 12px;margin-top: 30px;}.empty-state {text-align: center;padding: 60px 20px;color: #64748b;}.empty-state i {font-size: 60px;margin-bottom: 15px;color: #cbd5e1;}.empty-state p {margin-top: 15px;font-size: 18px;}.search-hint {text-align: center;padding: 15px;color: #64748b;font-style: italic;background: #f8fafc;border-radius: 8px;margin-top: 10px;display: none;}.search-hint.visible {display: block;animation: fadeIn 0.5s;}@media (max-width: 768px) {.header {flex-direction: column;align-items: stretch;}.search-box {width: 100%;}.actions {flex-direction: column;}th, td {padding: 12px;}.btn {width: 100%;justify-content: center;}}.user-avatar {width: 40px;height: 40px;border-radius: 50%;background: linear-gradient(135deg, #3498db 0%, #2ecc71 100%);display: flex;align-items: center;justify-content: center;color: white;font-weight: 600;margin-right: 10px;}.user-info {display: flex;align-items: center;}.role-badge {padding: 4px 12px;border-radius: 20px;font-size: 12px;font-weight: 600;}.role-admin {background: #ffeaa7;color: #d35400;}.role-user {background: #d6eaf8;color: #2980b9;}.role-editor {background: #e8f8f5;color: #16a085;}</style>
</head>
<body><div id="app"><div class="container"><h1><i class="fas fa-users-cog"></i> 用户管理系统</h1><div class="header"><div class="search-container"><input v-model="searchQuery" class="search-box" placeholder="搜索用户..." @input="handleSearch"/><button v-if="searchQuery" class="search-clear" @click="clearSearch"><i class="fas fa-times"></i></button><div class="search-icon"><i class="fas fa-search"></i></div></div><button class="btn btn-primary" @click="openModal(null)"><i class="fas fa-plus"></i> 添加用户</button></div><div class="search-hint" :class="{visible: searchQuery && filteredUsers.length > 0}">找到 {{ filteredUsers.length }} 个匹配"{{ searchQuery }}"的用户</div><div v-if="filteredUsers.length > 0"><table><thead><tr><th>用户</th><th>邮箱</th><th>角色</th><th>操作</th></tr></thead><tbody><tr v-for="user in filteredUsers" :key="user.id"><td><div class="user-info"><div class="user-avatar">{{ user.name.charAt(0) }}</div><div><div>{{ user.name }}</div><div style="font-size: 12px; color: #64748b;">ID: {{ user.id }}</div></div></div></td><td>{{ user.email }}</td><td><span class="role-badge" :class="'role-' + user.role">{{ user.role }}</span></td><td class="actions"><button class="btn btn-edit" @click="openModal(user)"><i class="fas fa-edit"></i> 编辑</button><button class="btn btn-delete" @click="deleteUser(user.id)"><i class="fas fa-trash"></i> 删除</button></td></tr></tbody></table></div><div v-else class="empty-state"><i class="fas fa-user-slash"></i><p>{{ searchQuery ? '没有找到匹配的用户' : '暂无用户数据' }}</p><button v-if="!searchQuery" class="btn btn-primary" @click="openModal(null)" style="margin-top: 20px;"><i class="fas fa-plus"></i> 添加第一个用户</button><button v-else class="btn btn-primary" @click="clearSearch" style="margin-top: 20px;"><i class="fas fa-times"></i> 清除搜索</button></div><!-- 添加/编辑用户的模态框 --><div class="modal" v-if="showModal" @click.self="closeModal"><div class="modal-content"><div class="modal-header"><h2 class="modal-title"><i :class="editingUser ? 'fas fa-user-edit' : 'fas fa-user-plus'"></i>{{ editingUser ? '编辑用户' : '添加用户' }}</h2><button class="modal-close" @click="closeModal"><i class="fas fa-times"></i></button></div><div class="form-group"><label for="name">姓名</label><input type="text" id="name" v-model="currentUser.name" placeholder="请输入姓名":class="{invalid: !currentUser.name && formSubmitted}"><div class="error-message">请输入姓名</div></div><div class="form-group"><label for="email">邮箱</label><input type="email" id="email" v-model="currentUser.email" placeholder="请输入邮箱":class="{invalid: (!currentUser.email || !isValidEmail) && formSubmitted}"><div class="error-message">{{ !currentUser.email ? '请输入邮箱' : '请输入有效的邮箱地址' }}</div></div><div class="form-group"><label for="role">角色</label><select id="role" v-model="currentUser.role"><option value="用户">用户</option><option value="管理员">管理员</option><option value="编辑">编辑</option></select></div><div class="form-actions"><button class="btn" @click="closeModal"><i class="fas fa-times"></i> 取消</button><button class="btn btn-primary" @click="saveUser"><i class="fas fa-save"></i> 保存</button></div></div></div></div></div><script>const { createApp, ref, computed, onMounted, watch } = Vue;createApp({setup() {// 用户数据const users = ref([]);// 搜索查询const searchQuery = ref('');// 控制模态框显示const showModal = ref(false);// 当前正在编辑的用户const currentUser = ref({ id: null, name: '', email: '', role: '用户' });// 判断是否为编辑模式const editingUser = ref(false);// 表单提交状态const formSubmitted = ref(false);// 邮箱验证状态const isValidEmail = ref(true);// 初始化一些示例数据onMounted(() => {users.value = [{ id: 1, name: '张三', email: 'zhangsan@example.com', role: '管理员' },{ id: 2, name: '李四', email: 'lisi@example.com', role: '用户' },{ id: 3, name: '王五', email: 'wangwu@example.com', role: '编辑' },{ id: 4, name: '赵六', email: 'zhaoliu@example.com', role: '用户' },{ id: 5, name: '钱七', email: 'qianqi@example.com', role: '编辑' }];});// 邮箱验证const validateEmail = () => {const email = currentUser.value.email;if (!email) {isValidEmail.value = false;return false;}const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;isValidEmail.value = re.test(email);return isValidEmail.value;};// 过滤用户列表const filteredUsers = computed(() => {if (!searchQuery.value) {return users.value;}const query = searchQuery.value.toLowerCase();return users.value.filter(user => user.name.toLowerCase().includes(query) || user.email.toLowerCase().includes(query) ||user.role.toLowerCase().includes(query));});// 处理搜索const handleSearch = () => {// 可以添加搜索延迟处理};// 清除搜索const clearSearch = () => {searchQuery.value = '';};// 打开模态框const openModal = (user) => {formSubmitted.value = false;if (user) {// 编辑模式currentUser.value = { ...user };editingUser.value = true;} else {// 添加模式currentUser.value = { id: null, name: '', email: '', role: '用户' };editingUser.value = false;}showModal.value = true;};// 关闭模态框const closeModal = () => {showModal.value = false;};// 保存用户const saveUser = () => {formSubmitted.value = true;// 验证表单if (!currentUser.value.name || !currentUser.value.email || !validateEmail()) {return;}if (editingUser.value) {// 更新现有用户const index = users.value.findIndex(u => u.id === currentUser.value.id);if (index !== -1) {users.value[index] = { ...currentUser.value };}} else {// 添加新用户const newId = users.value.length > 0 ? Math.max(...users.value.map(u => u.id)) + 1 : 1;users.value.push({id: newId,name: currentUser.value.name,email: currentUser.value.email,role: currentUser.value.role});}showModal.value = false;};// 删除用户const deleteUser = (id) => {if (confirm('确定要删除这个用户吗?此操作不可撤销。')) {users.value = users.value.filter(user => user.id !== id);}};// 监听邮箱变化watch(() => currentUser.value.email, () => {if (formSubmitted.value) {validateEmail();}});return {users,searchQuery,showModal,currentUser,editingUser,formSubmitted,isValidEmail,filteredUsers,handleSearch,clearSearch,openModal,closeModal,saveUser,deleteUser,validateEmail};}}).mount('#app');</script>
</body>
</html>


文章转载自:

http://bgT9GRiK.qmhcc.cn
http://1VhdFLBn.qmhcc.cn
http://agKpQsx7.qmhcc.cn
http://aemWs9TP.qmhcc.cn
http://UF1h744I.qmhcc.cn
http://GnJHZT7b.qmhcc.cn
http://sufCgbOf.qmhcc.cn
http://Kt5yzb0B.qmhcc.cn
http://FjFaqdao.qmhcc.cn
http://11aT0qIR.qmhcc.cn
http://YCC3amnr.qmhcc.cn
http://bnJ33w5Z.qmhcc.cn
http://3ShcwFQP.qmhcc.cn
http://6lodD1Wl.qmhcc.cn
http://sNRlWFgV.qmhcc.cn
http://YfP7pEIC.qmhcc.cn
http://l91Coxn1.qmhcc.cn
http://e7OlLKTo.qmhcc.cn
http://w1jxdGzl.qmhcc.cn
http://GlppYgma.qmhcc.cn
http://jVWVmBQX.qmhcc.cn
http://Z4UHsDWQ.qmhcc.cn
http://PLxnmeHE.qmhcc.cn
http://h09N2A9g.qmhcc.cn
http://KFhHJCe4.qmhcc.cn
http://BXsTaPwP.qmhcc.cn
http://D0kqSAkf.qmhcc.cn
http://krcgS4Q4.qmhcc.cn
http://FeWoByGB.qmhcc.cn
http://PR6rLnBJ.qmhcc.cn
http://www.dtcms.com/a/368128.html

相关文章:

  • 在Unity中实现DTLN-AEC处理音频文件的功能
  • 关于kubernetes和docker版本的一些总结
  • 图像的几种成像方式简介
  • AI 基础设施新范式,百度百舸 5.0 技术深度解析
  • 中创中间件适配HGDB
  • 没 iCloud, 如何数据从iPhone转移到iPhone
  • 【技术教程】如何将文档编辑器集成至基于Java的Web应用程序
  • 基于华为云平台的STM32F103C8T6工业生产线温湿度监控系统
  • js设计模式-状态模式
  • 一文从零部署vLLM+qwen0.5b(mac本地版,不可以实操GPU单元)
  • Python核心基础:运算符、流程控制与字符串操作详解
  • Follow 幂如何刷屏?拆解淘宝闪购×杨幂的情绪共振品牌营销
  • 嵌入式学习4——硬件
  • 数据标注:人工智能视觉感知的基石
  • 【Linux系统】POSIX信号量
  • 【Python - 类库 - requests】(02)使用“requests“发起GET请求的详细教程
  • XSCT/Vitis 裸机 JTAG 调试与常用命令
  • 【GitHub每日速递】不止 TeamViewer 替代!RustDesk 与 PowerToys,Windows 效率神器
  • 使用海康机器人相机SDK实现基本参数配置(C语言示例)
  • Go 服务注册 Nacos 的坑与解决方案——从 404 到连接成功的排查之路
  • 智能相机还是视觉系统?一文讲透工业视觉两大选择的取舍之道
  • Go语言中atomic.Value结构体嵌套指针的直接修改带来的困惑
  • react+umi项目如何添加electron的功能
  • 告别 OpenAI SDK:如何使用 Python requests 库调用大模型 API(例如百度的ernie-4.5-turbo)
  • 《sklearn机器学习——聚类性能指数》同质性,完整性和 V-measure
  • C#海康车牌识别实战指南带源码
  • 五、Docker 核心技术:容器数据持久化之数据卷
  • (计算机网络)DNS解析流程及两种途径
  • 3-8〔OSCP ◈ 研记〕❘ WEB应用攻击▸REST API枚举
  • Tabby使用sftp上传文件服务器ssh一直断开