原生html+css+ajax实现二级下拉选择的增删改及树形结构列出

 

<?php
$db_host = 'localhost';
$db_user = 'info_chalide';
$db_pass = 'j8c2rRr2RnA';
$db_name = 'info_chalide';
/*
数据库结构SQL
CREATE TABLE categories (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
parent_id INT DEFAULT 0
);
*/
try {
$pdo = new PDO("mysql:host=$db_host;dbname=$db_name;charset=utf8mb4", $db_name, $db_pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
die("连接失败: " . $e->getMessage());
}
// AJAX处理
if (!empty($_GET['act'])) {
header('Content-Type: application/json');
switch ($_GET['act']) {
case 'list':
// 获取所有类别
try {
$sql = "SELECT * FROM cat ORDER BY parent_id, id";
$stmt = $pdo->query($sql);
$categories = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 组织树形结构
$tree = [];
foreach ($categories as $cat) {
if ($cat['parent_id'] == 0) {
$cat['children'] = [];
$tree[$cat['id']] = $cat;
}
}
foreach ($categories as $cat) {
if ($cat['parent_id'] > 0 && isset($tree[$cat['parent_id']])) {
$tree[$cat['parent_id']]['children'][] = $cat;
}
}
echo json_encode(['status' => 'success', 'data' => array_values($tree)]);
} catch (PDOException $e) {
echo json_encode(['status' => 'error', 'message' => '获取类别失败:' . $e->getMessage()]);
}
break;
case 'add':
if (empty($_POST['name'])) {
echo json_encode(['status' => 'error', 'message' => '类别名称不能为空']);
exit;
}
try {
$name = trim($_POST['name']);
$parent_id = isset($_POST['parent_id']) ? intval($_POST['parent_id']) : 0;
$sql = "INSERT INTO cat (name, parent_id) VALUES (?, ?)";
$stmt = $pdo->prepare($sql);
$stmt->execute([$name, $parent_id]);
echo json_encode(['status' => 'success', 'message' => '添加成功']);
} catch (PDOException $e) {
echo json_encode(['status' => 'error', 'message' => '添加失败:' . $e->getMessage()]);
}
break;
case 'edit':
if (empty($_POST['name']) || empty($_POST['id'])) {
echo json_encode(['status' => 'error', 'message' => '参数错误']);
exit;
}
try {
$name = trim($_POST['name']);
$id = intval($_POST['id']);
$sql = "UPDATE cat SET name = ? WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$name, $id]);
echo json_encode(['status' => 'success', 'message' => '修改成功']);
} catch (PDOException $e) {
echo json_encode(['status' => 'error', 'message' => '修改失败:' . $e->getMessage()]);
}
break;
case 'delete':
if (empty($_POST['id'])) {
echo json_encode(['status' => 'error', 'message' => '参数错误']);
exit;
}
try {
$id = intval($_POST['id']);
// 删除该类别及其子类别
$sql = "DELETE FROM cat WHERE id = ? OR parent_id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$id, $id]);
echo json_encode(['status' => 'success', 'message' => '删除成功']);
} catch (PDOException $e) {
echo json_encode(['status' => 'error', 'message' => '删除失败:' . $e->getMessage()]);
}
break;
}
exit;
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>类别管理</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: Arial, sans-serif; padding: 20px; }
/* 树形结构样式 */
.tree-item { margin: 5px 0; }
.tree-item.child { margin-left: 30px; }
.category-name { display: inline-block; border: 1px solid #ddd; min-width: 150px; }
/* 按钮样式 */
button {
padding: 3px 5px;
margin: 0 2px;
cursor: pointer;
border: 1px solid #ddd;
background: #f8f8f8;
border-radius: 3px;
}
button:hover { background: #e8e8e8; }
/* 遮罩层样式 */
.overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.5);
z-index: 1000;
}
.modal {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: white;
padding: 20px;
border-radius: 5px;
min-width: 300px;
max-width: 90%;
max-height: 90vh;
display: flex;
flex-direction: column;
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.modal-body {
overflow-y: auto;
margin-bottom: 20px;
}
.modal-footer {
border-top: 1px solid #eee;
padding-top: 15px;
text-align: right;
}
.close-btn {
cursor: pointer;
font-size: 20px;
}
/* 表单样式 */
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
}
.form-group input,
.form-group select {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 3px;
}
</style>
</head>
<body>
<h1>类别管理</h1>
<button onclick="showAddModal()">添加类别</button>
<div id="category-tree"></div>
<!-- 添加/修改类别的遮罩层 -->
<div id="categoryModal" class="overlay">
<div class="modal">
<div class="modal-header">
<h3 id="modalTitle">添加类别</h3>
<span class="close-btn" onclick="closeModal()">&times;</span>
</div>
<div class="modal-body">
<form id="categoryForm">
<input type="hidden" id="categoryId">
<div class="form-group">
<label for="categoryName">类别名称:</label>
<input type="text" id="categoryName" required>
</div>
<div class="form-group" id="parentSelectGroup">
<label for="parentCategory">上级类别:</label>
<select id="parentCategory">
<option value="0">无 (新增一级类别)</option>
</select>
</div>
</form>
</div>
<div class="modal-footer">
<button onclick="closeModal()">取消</button>
<button onclick="saveCategory()">保存</button>
</div>
</div>
</div>
<script>
// 加载类别列表
function loadCategories() {
fetch('?act=list')
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
renderCategoryTree(data.data);
updateParentSelect(data.data);
} else {
alert(data.message);
}
});
}
// 渲染类别树
function renderCategoryTree(categories) {
const tree = document.getElementById('category-tree');
tree.innerHTML = '';
categories.forEach(category => {
// 渲染一级类别
const item = document.createElement('div');
item.className = 'tree-item';
item.innerHTML = `
<span class="category-name">${category.name}</span>
<button onclick="showEditModal(${category.id}, '${category.name}')">修改</button>
<button onclick="deleteCategory(${category.id})">删除</button>
`;
tree.appendChild(item);
// 渲染二级类别
if (category.children && category.children.length > 0) {
category.children.forEach(child => {
const childItem = document.createElement('div');
childItem.className = 'tree-item child';
childItem.innerHTML = `
<span class="category-name">${child.name}</span>
<button onclick="showEditModal(${child.id}, '${child.name}')">修改</button>
<button onclick="deleteCategory(${child.id})">删除</button>
`;
tree.appendChild(childItem);
});
}
});
}
// 更新上级类别选择框
function updateParentSelect(categories) {
const select = document.getElementById('parentCategory');
select.innerHTML = '<option value="0">无 (新增一级类别)</option>';
categories.forEach(category => {
select.innerHTML += `<option value="${category.id}">${category.name}</option>`;
});
}
// 显示添加模态框
function showAddModal() {
document.getElementById('modalTitle').textContent = '添加类别';
document.getElementById('categoryId').value = '';
document.getElementById('categoryName').value = '';
document.getElementById('parentSelectGroup').style.display = 'block';
document.getElementById('categoryModal').style.display = 'block';
}
// 显示编辑模态框
function showEditModal(id, name) {
document.getElementById('modalTitle').textContent = '修改类别';
document.getElementById('categoryId').value = id;
document.getElementById('categoryName').value = name;
document.getElementById('parentSelectGroup').style.display = 'none';
document.getElementById('categoryModal').style.display = 'block';
}
// 关闭模态框
function closeModal() {
document.getElementById('categoryModal').style.display = 'none';
}
// 保存类别
function saveCategory() {
const id = document.getElementById('categoryId').value;
const name = document.getElementById('categoryName').value;
const parent_id = document.getElementById('parentCategory').value;
if (!name) {
alert('请输入类别名称');
return;
}
const formData = new FormData();
formData.append('name', name);
if (id) {
// 修改
formData.append('id', id);
fetch('?act=edit', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
closeModal();
loadCategories();
}
alert(data.message);
});
} else {
// 添加
formData.append('parent_id', parent_id);
fetch('?act=add', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
closeModal();
loadCategories();
}
alert(data.message);
});
}
}
// 删除类别
function deleteCategory(id) {
if (!confirm('确定要删除该类别吗?此操作无法恢复!')) {
return;
}
const formData = new FormData();
formData.append('id', id);
fetch('?act=delete', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
alert(data.message);
if (data.status === 'success') {
loadCategories();
}
});
}
// 页面加载完成后加载类别列表
window.onload = loadCategories;
</script>
</body>
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/929402.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序介绍-以及写项目流程(重要)

前言&#xff1a;本篇文章介绍微信小程序以及项目介绍&#xff1a; 文章介绍&#xff1a;介绍了微信小程序常用的指令、组件、api。tips&#xff1a;最好按照官方文档来进行学习&#xff0c;大致可以我的目录来学习&#xff0c;对于写项目是没有问题的 微信小程序官方文档https…

Data Uncertainty Learning in Face Recognition 论文阅读

Data Uncertainty Learning in Face Recognition 论文阅读 Abstract1. Introduction2. Related Work3. Methodology3.1. Preliminaries3.2. Classification-based DUL for FR3.3. Regression-based DUL for FR3.4. Discussion of Related Works 4. Experiments4.1. Datasets an…

汽车产业数字化转型:协同创新破解挑战,平衡安全与流通

在数字经济时代的浪潮中&#xff0c;数据资源和数据信息已成为驱动各行各业转型升级的“新石油”。汽车产业&#xff0c;作为国民经济的重要支柱&#xff0c;正经历着前所未有的变革。随着数字化创新和转型的深入&#xff0c;数据在汽车全产业链中的作用和价值日益凸显。在这个…

vulnhub kioptirx1.2 超详细wp

探测 nmap --min-rate 10000 -p- 192.168.128.134 最小速率10000 nmap -sT -sV -sC -O 192.168.128.134 web打点 无弱口令 暴露cms寻找exp searchsploit LotusCMS -m 16982 [输入id号和参数m可以直接把东西复制到当前目录] 查看txt里面发现 都是xss没有rce github搜索到一个…

扫二维码进小程序的指定页面

草料二维码解码器 微信开发者工具 获取二维码解码的参数->是否登陆->跳转 options.q onLoad: function (options) {// console.log("options",options.q)if (options && options.q) {// 解码二维码携带的链接信息let qrUrl decodeURIComponent(optio…

mysql基础学习1

useradd -r -g mysql -s /bin/false mysql (-r)系统用户 不能登录 A temporary password is generated for rootlocalhost: d>#jT7rfoaz) 看是否启动 看进程 端口 直接连接 看日志 varchar (20) char(20)更耗空间 create table student_info(id int,name varchar(20),s…

Echarts使用平面方法绘制三维立体柱状图表

目录 一、准备工作 1.下载引入ECharts库 2.创建容器 二、绘制基本柱状 三、绘制立体柱状方法一 1.定义立方体形状 2.注册立方体形状 3.配置custom系列 4.设置数据 5.渲染图表 四、绘制立体柱状方法二 1.画前知识 2.计算坐标renderItem 函数 &#xff08;1&#x…

基于 MindQuantum 实现对 “天衍” 量子云平台真机的比特映射

MindQuantum 目前只支持量子模拟器&#xff0c;如果需要获得量子算法在真机上的实测数据&#xff0c;可以借助“天衍”量子云平台提供的真机。本文将介绍如何基于 MindQuantum 绘制“天衍”真机的拓扑图&#xff0c;并进而实现比特映射。 关于 MindQuantum 涉及比特映射的教程…

OpenBayes贝式计算创始人受邀参加第九届中国开源年会,分享 AI4S 前沿洞察

Open Source&#xff0c;Open Life&#xff0c;开源新生活&#xff01; 由开源社主办的第九届中国开源年会 (COSCon24) 于 2024 年 11 月 3 日在北京圆满落幕。本届大会为期 2 天&#xff0c;以 「开源新生活 - Open Source, Open Life 」 为主题&#xff0c;汇聚了来自全国各…

Day1 生信新手笔记

生信新手笔记 生信学习第一天笔记打卡。 转录组学中&#xff1a; 上游分析-基于linux&#xff0c;包括质控、过滤、比对、定量&#xff1b; 下游分析-基于R语言&#xff0c;包括差异分析、富集分析、可视化。 1. 级别标题 一个井号加空格 就是一级标题&#xff0c;两个井号加…

日拱一卒(9)——leetcode学习记录:两数组中位数

一、问题 给定两个大小分别为 m 和 n 的排序数组 nums1 和 nums2&#xff0c;要求你在 O(log(mn)) 的时间复杂度内找出这两个数组的中位数。 二、思路 时间复杂度O(log(n))代表随着操作数增加&#xff0c;剩余操作数递减&#xff0c;如二分法。 首先要建模&#xff0c;对这…

从 HTML 到 CSS:开启网页样式之旅(五)—— CSS盒子模型

从 HTML 到 CSS&#xff1a;开启网页样式之旅&#xff08;五&#xff09;—— CSS盒子模型 前言一、盒子模型的组成margin&#xff08;外边距&#xff09;&#xff1a;border&#xff08;边框&#xff09;&#xff1a;padding&#xff08;内边距&#xff09;&#xff1a;conten…

【区块链】深入理解区块链中的 Gas 机制

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 深入理解区块链中的 Gas 机制一、Gas 的基本概念1.1 为什么需要 Gas&#xff1f…

黑马JavaWeb-day06、07、08(SQL部分) _

文章目录 MYSQL概述数据模型SQL简介SQL分类 DDL数据库操作表操作 DML增&#xff08;INSERT&#xff09;改&#xff08;UPDATE&#xff09;删&#xff08;DELETE&#xff09; DQL基本查询条件查询&#xff08;where&#xff09;分组查询&#xff08;group by&#xff09;排序查询…

Kubernetes集群操作

查看集群信息&#xff1a; kubectl get nodes 删除节点 &#xff08;⽆效且显示的也可以删除&#xff09; 后期如果 要删除某个节点&#xff0c;为了不增加其他节点的访问压力&#xff0c;先增加一个节点&#xff0c;再删除要删除的节点 语法 &#xff1a;kubect delete…

基于PSO粒子群优化的CNN-LSTM-SAM网络时间序列回归预测算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 matlab2022a 3.部分核心程序 &#xff08;完整版代码包含详细中文注释和操作步骤视频&#xff09…

三步入门Log4J 的使用

本篇基于Maven 的Project项目&#xff0c; 快速演示Log4j 的导入和演示。 第一步&#xff1a; 导入Log4j依赖 <dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-api</artifactId><version>2.24.2</version&…

Redis 基础、Redis 应用

Redis 基础 什么是 Redis&#xff1f; Redis &#xff08;REmote DIctionary Server&#xff09;是一个基于 C 语言开发的开源 NoSQL 数据库&#xff08;BSD 许可&#xff09;。与传统数据库不同的是&#xff0c;Redis 的数据是保存在内存中的&#xff08;内存数据库&#xf…

3D数据大屏实现过程,使用echarts、Next.js

&#x1f4dc; 本文主要内容 数据大屏自适应方案动效 echarts&#xff1a; 3D 立体柱状图动态流光折线图 3D 地球&#xff08;飞线、柱状图&#xff09;无限滚动列表 &#x1f50d; 大屏效果 数据大屏&#xff1a; 点击预览 &#x1f579; 运行条件 next 12.3.4echarts 5.4…

标贝科技受邀出席2024东湖国际人工智能高峰论坛并入选数据要素合作伙伴名单

近日&#xff0c;备受瞩目的2024东湖国际人工智能高峰论坛在中国光谷科技会展中心隆重召开。会议以“智联世界&#xff0c;共创未来”为主题&#xff0c;省市相关单位、专家学者、产学研各界百余家联合体单位齐聚一堂&#xff0c;共话人工智能领域的最新技术及产业发展趋势。会…