从零开始构建后台管理系统列表:新手友好教程,全程使用 HTML+CSS+JavaScript,涵盖增删查改、导入导出、排序等功能(含完整源码)

news2024/11/19 7:24:39

b站视频演示效果:

效果图:

完整代码:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>后台管理系统</title>
    <!-- 引入正确的 Vue.js 版本 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.min.js"></script>
    <!-- 引入样式 -->
    <style>
        /* 原有样式保持不变 */
        body {
            font-family: Arial, sans-serif;
            background-color: #f4f4f9;
            margin: 0;
            padding: 20px;
        }

        #app {
            max-width: 800px;
            margin: 0 auto;
        }

        h1 {
            text-align: center;
            color: #333;
        }

        table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 20px;
        }

        th, td {
            padding: 10px;
            border: 1px solid #ddd;
            text-align: left;
        }

        th {
            background-color: #5a67d8;
            color: white;
            cursor: pointer; /* 添加鼠标指针样式 */
            position: relative; /* 为排序箭头定位 */
        }

        th.sort-asc::after {
            content: '▲';
            position: absolute;
            right: 10px;
        }

        th.sort-desc::after {
            content: '▼';
            position: absolute;
            right: 10px;
        }

        button {
            padding: 10px 15px;
            margin: 5px;
            background-color: #5a67d8;
            color: white;
            border: none;
            cursor: pointer;
        }

        button:hover {
            background-color: #434190;
        }

        /* 弹框样式 */
        .modal {
            display: none; /* 默认隐藏 */
            position: fixed;
            z-index: 1;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            overflow: auto;
            background-color: rgba(0,0,0,0.5); /* 半透明背景 */
        }

        .modal.show {
            display: block; /* 显示弹框 */
        }

        .modal-content {
            background-color: #fefefe;
            margin: 10% auto;
            padding: 20px;
            border: 1px solid #888;
            width: 400px;
            border-radius: 5px;
        }

        .modal-header h2 {
            margin: 0;
        }

        .modal-footer {
            text-align: right;
        }

        .input-group {
            margin-bottom: 15px;
        }

        .input-group label {
            display: block;
            margin-bottom: 5px;
            color: #333;
        }

        .input-group input, .input-group select {
            width: 100%;
            padding: 8px;
            box-sizing: border-box;
        }

    </style>
</head>
<body>
    <div id="app">
        <h1>后台管理系统</h1>
        <div class="action-buttons">
            <button @click="showAddModal">添加商品</button>
            <button @click="exportTable">导出表格</button>
            <input type="file" @change="importTable" style="display: inline-block; margin-left: 10px;" />
        </div>
        <table>
            <thead>
                <tr>
                    <th @click="sortBy('name')" :class="getSortClass('name')">名称</th>
                    <th @click="sortBy('price')" :class="getSortClass('price')">价格</th>
                    <th @click="sortBy('description')" :class="getSortClass('description')">描述</th>
                    <th @click="sortBy('category')" :class="getSortClass('category')">类别</th>
                    <th @click="sortBy('stock')" :class="getSortClass('stock')">库存</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody>
                <tr v-for="(item, index) in sortedItems" :key="index">
                    <td>{{ item.name }}</td>
                    <td>{{ item.price.toFixed(2) }}</td>
                    <td>{{ item.description }}</td>
                    <td>{{ item.category }}</td>
                    <td>{{ item.stock }}</td>
                    <td>
                        <button @click="showEditModal(index)">编辑</button>
                        <button @click="removeItem(index)">删除</button>
                    </td>
                </tr>
            </tbody>
        </table>

        <!-- 添加商品的模态框 -->
        <div class="modal" :class="{ show: isAddModalVisible }">
            <div class="modal-content">
                <div class="modal-header">
                    <h2>添加商品</h2>
                </div>
                <div class="modal-body">
                    <div class="input-group">
                        <label>名称</label>
                        <input v-model="newItem.name" placeholder="请输入名称" />
                    </div>
                    <div class="input-group">
                        <label>价格</label>
                        <input v-model.number="newItem.price" placeholder="请输入价格" type="number" />
                    </div>
                    <div class="input-group">
                        <label>描述</label>
                        <input v-model="newItem.description" placeholder="请输入描述" />
                    </div>
                    <div class="input-group">
                        <label>类别</label>
                        <select v-model="newItem.category">
                            <option disabled value="">请选择类别</option>
                            <option>电子产品</option>
                            <option>服装</option>
                            <option>食品</option>
                            <option>书籍</option>
                        </select>
                    </div>
                    <div class="input-group">
                        <label>库存</label>
                        <input v-model.number="newItem.stock" placeholder="请输入库存数量" type="number" />
                    </div>
                </div>
                <div class="modal-footer">
                    <button @click="addItem">添加</button>
                    <button @click="isAddModalVisible = false">取消</button>
                </div>
            </div>
        </div>

        <!-- 编辑商品的模态框 -->
        <div class="modal" :class="{ show: isEditModalVisible }">
            <div class="modal-content">
                <div class="modal-header">
                    <h2>编辑商品</h2>
                </div>
                <div class="modal-body">
                    <div class="input-group">
                        <label>名称</label>
                        <input v-model="editItemData.name" placeholder="请输入名称" />
                    </div>
                    <div class="input-group">
                        <label>价格</label>
                        <input v-model.number="editItemData.price" placeholder="请输入价格" type="number" />
                    </div>
                    <div class="input-group">
                        <label>描述</label>
                        <input v-model="editItemData.description" placeholder="请输入描述" />
                    </div>
                    <div class="input-group">
                        <label>类别</label>
                        <select v-model="editItemData.category">
                            <option disabled value="">请选择类别</option>
                            <option>电子产品</option>
                            <option>服装</option>
                            <option>食品</option>
                            <option>书籍</option>
                        </select>
                    </div>
                    <div class="input-group">
                        <label>库存</label>
                        <input v-model.number="editItemData.stock" placeholder="请输入库存数量" type="number" />
                    </div>
                </div>
                <div class="modal-footer">
                    <button @click="updateItem">更新</button>
                    <button @click="isEditModalVisible = false">取消</button>
                </div>
            </div>
        </div>
    </div>

    <!-- 引入 Vue.js 脚本 -->
    <script>
    new Vue({
        el: '#app',
        data: {
            items: [],
            newItem: {
                name: '',
                price: 0,
                description: '',
                category: '',
                stock: 0
            },
            editIndex: null,
            editItemData: {
                name: '',
                price: 0,
                description: '',
                category: '',
                stock: 0
            },
            isAddModalVisible: false,
            isEditModalVisible: false,
            sortKey: '', // 当前排序的列
            sortOrders: { // 每列的排序顺序,1 为升序,-1 为降序
                name: 1,
                price: 1,
                description: 1,
                category: 1,
                stock: 1
            }
        },
        computed: {
            sortedItems() {
                let items = this.items.slice();
                if (this.sortKey) {
                    items.sort((a, b) => {
                        let result = 0;
                        let aVal = a[this.sortKey];
                        let bVal = b[this.sortKey];

                        // 处理空值
                        if (aVal === undefined || aVal === null) aVal = '';
                        if (bVal === undefined || bVal === null) bVal = '';

                        // 数值排序
                        if (typeof aVal === 'number' && typeof bVal === 'number') {
                            result = aVal - bVal;
                        } else {
                            // 字符串排序,使用 localeCompare 支持中文
                            result = aVal.toString().localeCompare(bVal.toString(), 'zh-Hans-CN', {numeric: true});
                        }
                        return result * this.sortOrders[this.sortKey];
                    });
                }
                return items;
            }
        },
        methods: {
            showAddModal() {
                // 重置 newItem 数据
                this.newItem = {
                    name: '',
                    price: 0,
                    description: '',
                    category: '',
                    stock: 0
                };
                this.isAddModalVisible = true;
            },
            addItem() {
                if (this.newItem.name && this.newItem.price >= 0 && this.newItem.category && this.newItem.stock >= 0) {
                    this.items.push({ ...this.newItem });
                    this.isAddModalVisible = false;
                } else {
                    alert('请填写完整的商品信息');
                }
            },
            removeItem(index) {
                this.items.splice(index, 1);
            },
            showEditModal(index) {
                this.editIndex = index;
                this.editItemData = { ...this.items[index] };
                this.isEditModalVisible = true;
            },
            updateItem() {
                if (this.editItemData.name && this.editItemData.price >= 0 && this.editItemData.category && this.editItemData.stock >= 0) {
                    this.$set(this.items, this.editIndex, this.editItemData);
                    this.isEditModalVisible = false;
                    this.editIndex = null;
                } else {
                    alert('请填写完整的商品信息');
                }
            },
            exportTable() {
                const headers = ['名称', '价格', '描述', '类别', '库存'];
                const csvContent = "data:text/csv;charset=utf-8," 
                    + headers.join(",") + "\n"
                    + this.items.map(item => 
                        `${item.name},${item.price},${item.description},${item.category},${item.stock}`
                    ).join("\n");
                const encodedUri = encodeURI(csvContent);
                const link = document.createElement("a");
                link.setAttribute("href", encodedUri);
                link.setAttribute("download", "data.csv");
                document.body.appendChild(link);
                link.click();
                document.body.removeChild(link);
            },
            importTable(event) {
                const file = event.target.files[0];
                if (!file) return;

                const reader = new FileReader();
                reader.onload = (e) => {
                    const text = e.target.result;
                    const rows = text.trim().split("\n").map(row => row.split(","));
                    const headers = rows[0];
                    const dataRows = rows.slice(1);
                    this.items = dataRows.map(row => ({
                        name: row[0],
                        price: parseFloat(row[1]),
                        description: row[2],
                        category: row[3],
                        stock: parseInt(row[4])
                    }));
                };
                reader.readAsText(file);
            },
            sortBy(key) {
                if (this.sortKey === key) {
                    this.sortOrders[key] = -this.sortOrders[key]; // 切换排序顺序
                } else {
                    this.sortKey = key;
                }
            },
            getSortClass(key) {
                if (this.sortKey === key) {
                    return this.sortOrders[key] === 1 ? 'sort-asc' : 'sort-desc';
                }
                return '';
            }
        }
    });
    </script>
</body>
</html>

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

各位同学们:还有啥想看的功能或者特效不?欢迎在评论区留言哦!

本人承接网网站开发,如有需要,欢迎私信咨询!

如果您感觉文章对您有帮助~
那就打赏一下,请笔者喝杯咖啡吧~

给新手学习前端开发的建议:

  1. 了解基础知识

    • 学习HTML、CSS和JavaScript的基础知识。它们是前端开发的核心,构成了网页的基本结构和样式,以及交互功能。
    • 掌握HTML的标签和语义化,了解CSS的选择器和布局技巧,熟悉JavaScript的基本语法和DOM操作。
  2. 实践项目

    • 不要仅仅停留在理论学习上,通过实践项目来巩固和应用所学知识。
    • 可以从简单的静态页面开始,逐渐尝试添加交互效果和动态数据。
    • 参与开源项目或自己动手创建一个个人网站,将所学知识应用到实际场景中。
  3. 学习工具和框架

    • 了解并学习前端开发中常用的工具和框架,如构建工具(Webpack、Gulp等)、版本控制工具(Git)、前端框架(React、Vue、Angular等)。
    • 这些工具和框架能够提高开发效率,简化开发流程,是前端开发的重要组成部分。
  4. 关注前端趋势

    • 前端开发是一个快速发展的领域,新的技术和工具不断涌现。
    • 关注前端社区、博客和会议,了解最新的技术趋势和发展方向,保持学习的热情和动力。
  5. 培养解决问题的能力

    • 前端开发常常会遇到各种问题和挑战,学会独立思考和解决问题是非常重要的。
    • 遇到问题时,可以先尝试自己解决,通过查阅文档、搜索资料和社区讨论来找到答案。
    • 如果实在无法解决,可以向同事或社区求助,但也要学会总结和分享自己的经验和教训。
  6. 不断学习和提升

    • 前端开发是一个不断学习和提升的过程,要保持对知识的渴望和追求。
    • 可以通过阅读书籍、参加培训、参与开源项目等方式来不断提升自己的技能水平。
    • 同时,也要关注自己的职业发展,了解行业的需求和趋势,规划自己的职业道路。
  7. 注重代码质量和可维护性

    • 编写高质量的代码是前端开发的基本要求之一。
    • 学习并遵循代码规范,使用适当的命名和注释来提高代码的可读性。
    • 注重代码的结构和逻辑,避免过度嵌套和复杂的逻辑。
    • 考虑代码的可维护性,尽量编写可复用和可扩展的代码。
  8. 参与社区和交流

    • 加入前端开发的社区和论坛,与其他开发者进行交流和分享。
    • 通过参与社区活动、回答问题、分享经验等方式,不仅可以提升自己的技能水平,还可以结识更多的同行和朋友。

总之,学习前端开发需要耐心和毅力,要保持对技术的热情和兴趣,不断学习和提升自己。通过实践项目、学习工具和框架、关注前端趋势等方式,你可以逐渐成为一名优秀的前端开发者。

加油吧!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

鸿蒙 OS 开发零基础快速入门教程

视频课程: 东西比较多, 这里主要分享一些代码和案例. 开关灯效果案例: 开灯 开关灯效果案例: 关灯 Column 和 Row 的基本用法 Entry Component struct Index {State message: string 张三;build() {// 一行内容Row() {// 一列内容Column() {// 文本内容Text(this.mess…

27 C 语言标准库 <stdio.h> 中的两个重要字符串函数:sprintf、sscanf

目录 1 sprintf 1.1 函数原型 1.2 功能说明 1.3 案例演示 1.4 注意事项 2 sscanf 2.1 函数原型 2.2 功能说明 2.3 案例演示 2.4 注意事项 1 sprintf 1.1 函数原型 sprintf 函数是 C 语言标准库中的一个函数&#xff0c;用于将格式化的数据写入字符串。其函数原型定义…

9.24作业

将昨天的My_string类中的所有能重载的运算符全部进行重载 、[] 、>、<、、>、<、! 、&#xff08;可以加等一个字符串&#xff0c;也可以加等一个字符&#xff09;、输入输出(<< 、 >>) 代码如下 MyString.h #ifndef MYSTRING_H #define MYSTRING_…

使用Docker和cpolar在Linux服务器上搭建DashDot监控面板

使用Docker和cpolar在Linux服务器上搭建DashDot监控面板 前言环境准备安装Docker下载Dashdot镜像 部署DashDot应用本地访问DashDot服务安装cpolar内网穿透固定DashDot公网地址结语 前言 在这个数字化飞速发展的时代&#xff0c;服务器作为支撑各种应用和服务的基础设施&#xf…

C++类和对象(中)【下篇】

&#x1f31f;个人主页&#xff1a;落叶 &#x1f31f;当前专栏: C专栏 目录 赋值运算符重载 运算符重载 赋值运算符重载 日期类实现 运算符重载<和运算符重载 运算符重载进行复用 运算符重载< 运算符重载> 运算符重载> 运算符重载! 获取某年某月的天数…

大模型算法岗常见面试题100道(值得收藏)非常详细收藏我这一篇就够了

大模型应该是目前当之无愧的最有影响力的AI技术&#xff0c;它正在革新各个行业&#xff0c;包括自然语言处理、机器翻译、内容创作和客户服务等等&#xff0c;正在成为未来商业环境的重要组成部分。 截至目前大模型已经超过200个&#xff0c;在大模型纵横的时代&#xff0c;不…

在Markdown中实现内部查询

markdown实现内部查询 在想要跳转到的位置添加 <a idxxx></a> 标签&#xff0c;如下图&#xff1a; 然后按如下格式添加目录 [跳转文字](#id)&#xff1a; 如上操作即可实现markdown内部查询。 具体实现效果如下&#xff1a;

八大排序——万字长文带你剖析八大排序(C语言)

本篇文章主要介绍八大排序的思想和具体实现&#xff0c;也会分析具体的时间复杂度和空间复杂度&#xff0c;提醒一些容易出现的坑和实现一些不同版本的排序&#xff0c;以及这些不同排序之间的效率分析 目录 1.插入排序 1.1直接插入排序 1.1.1 直接插入排序的思想&#xff…

PyTorch模型转ONNX量化模型

你是否发现模型太大&#xff0c;无法部署在你想要的云服务上&#xff1f;或者你是否发现 TensorFlow 和 PyTorch 等框架对于你的云服务来说太臃肿了&#xff1f;ONNX Runtime 可能是你的救星。 如果你的模型在 PyTorch 中&#xff0c;你可以轻松地在 Python 中将其转换为 ONNX…

关于YOLOX的一些优势

YOLOX 是旷视开源的高性能检测器。旷视的研究者将解耦头、数据增强、无锚点以及标签分类等目 标检测领域的优秀进展与 YOLO 进行了巧妙的集成组合&#xff0c;提出了 YOLOX&#xff0c;不仅实现了超越 YOLOv3、 YOLOv4 和 YOLOv5 的 AP&#xff0c;而且取得了极具竞争力的推理速…

FME学习笔记

读取数据 方法一&#xff1a;add reader 通过读模块来进行数据的读取 方法二&#xff1a;FeatureReader Parameters 通过转换器来进行数据的读取 可以通过空间范围进行筛选 在FME中&#xff0c;所有数据处理都要用到的&#xff0c;绝对的重点&#xff1a;转换器&#xff…

深圳某局联想SR850服务器黄灯 不开机维修

深圳 福田区1台Lenovo Thinksystem SR850 四路服务器黄灯问题现场处理。 1&#xff1a;型号&#xff1a;联想SR850 机架式2U服务器 2&#xff1a;故障&#xff1a;能通电&#xff0c;开机按钮快闪&#xff0c;随后叹号警告灯常亮 3&#xff1a;用户自行折腾无果后找到我们tech …

【推文制作】秀米简明教程 1.0

【前言】本文内容主要是针对一些常用的秀米操作进行介绍&#xff0c;并说明一些往年的经验要求。但是&#xff0c;最重要的是&#xff0c;请发挥你的艺术创造力&#xff0c;相信你一定可以做出更好看的推文。 一、秀米页面介绍 在使用秀米之前&#xff0c;我们会有一个通过浏览…

Maya学习笔记:项目设置和快捷键

文章目录 项目设置工程文件夹 快捷键 项目设置 工程文件夹 maya需要一个文件夹存放自己的工程内容 先指定一个文件夹 文件/项目窗口 选择一个文件夹&#xff0c;然后选择创建默认工作区 然后生成文件目录 在项目窗口里&#xff0c;选择要生成的子文件夹&#xff08;保持默认…

【ASE】第二课_溶解效果

今天我们一起来学习ASE插件&#xff0c;希望各位点个关注&#xff0c;一起跟随我的步伐 今天我们来学习溶解效果&#xff0c;通过渐变纹理达到好像燃烧效果的溶解效果 今天我们的效果很简单&#xff0c;但是其中包含没有学习的节点&#xff0c;所以还是要拿出来学习一下 最终…

ESP32异常报错2

出现这种情况 一般是缺少";"分号. 或者缺少, 仔细查找代码.查看是哪儿缺少了这些代码

【2024W35】肖恩技术周刊(第 13 期):肉,好次!

周刊内容: 对一周内阅读的资讯或技术内容精品&#xff08;个人向&#xff09;进行总结&#xff0c;分类大致包含“业界资讯”、“技术博客”、“开源项目”和“工具分享”等。为减少阅读负担提高记忆留存率&#xff0c;每类下内容数一般不超过3条。 更新时间: 星期天 历史收录:…

docker快速部署zabbix

两台主机 一台作为server 一台作为agent 安装好docker 并保证服务正常运行&#xff0c;镜像正常pull 分析&#xff1a; 部署 Zabbix 容器环境&#xff0c;通常会涉及几个主要组件&#xff1a; MySQL&#xff08;或 MariaDB 数据库&#xff09;、Zabbix Server 和 Zabbix Web I…

c++ 继承 和 组合

目录 一. 继承 1.1 继承的概念 1.2 继承定义 1.3 继承类模板 1.4. 继承中的作用域 二. 派生类&#xff08;子类&#xff09;的默认成员函数 2.1 概念&#xff1a; 2.2 实现⼀个不能被继承的类 2.3 继承与友元 2.4继承与静态成员 三.多继承及其菱形继承问题 3.1继承方…