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

后台管理系统通用页面抽离=>高阶组件+配置文件+hooks

目录结构

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

配置文件和通用页面组件

content.config.ts

const contentConfig = {pageName: "role",header: {title: "角色列表",btnText: "新建角色"},propsList: [{ type: "selection", label: "选择", width: "80px" },{ type: "index", label: "序号", width: "80px" },{ type: "normal", prop: "name", label: "角色名称", width: "180px" },{ type: "normal", prop: "intro", label: "角色权限", width: "180px" },{ type: "timer", prop: "createAt", label: "创建时间" },{ type: "timer", prop: "updateAt", label: "更新时间" },{ type: "handler", label: "操作", width: "180px" }]
};export default contentConfig;

modal.config.ts

const modalConfig = {pageName: "role",header: {newTitle: "新建角色",editTitle: "编辑角色"},formItems: [{type: "input",label: "角色名称",prop: "name",placeholder: "请输入角色名称"},{type: "input",label: "权限介绍",prop: "intro",placeholder: "请输入权限介绍"},{type: "custom",slotName: "menuList"}]
};export default modalConfig;

search.config.ts

const searchConfig = {formItems: [{type: 'input',prop: 'name',label: '角色名称',placeholder: '请输入查询的角色名称'},{type: 'input',prop: 'intro',label: '角色权限',placeholder: '请输入查询的角色权限'},{type: 'date-picker',prop: 'createAt',label: '创建时间'}]
}
export default searchConfig;

role.vue

<script setup lang="ts">
import PageSearch from "@/components/page-search/page-search.vue";
import PageModal from "@/components/page-modal/page-modal.vue";
import PageContent from "@/components/page-content/page-content.vue";
import searchConfig from "@/views/main/system/role/config/search.config";
import contentConfig from "@/views/main/system/role/config/content.config";
import modalConfig from "@/views/main/system/role/config/modal.config";
import usePageContent from "@/hooks/usePageContent";
import usePageModal from "@/hooks/usePageModal";
import useSystemStore from "@/stores/modules/main/system/system";
import { ref, useTemplateRef, nextTick } from "vue";
import { ElTree } from "element-plus";
import {mapMenuListToIds} from "@/utils/mapMenus";/*** 新增角色时,清空菜单列表*/
const newCallback = () => {nextTick(() => {treeRef.value?.setCheckedKeys([]);})
}/*** 编辑角色时,回显角色所拥有的菜单列表* @param itemData 当前编辑的角色信息*/
const editCallback = (itemData: any) => {nextTick(() => {const menuIds = mapMenuListToIds(itemData.menuList)treeRef.value?.setCheckedKeys(menuIds);})
}const { contentRef, handleQueryClick, handleResetClick } = usePageContent();
const { modalRef, handleNewClick, handleEditClick } = usePageModal(newCallback, editCallback); // editCallback 必须在 usePageModal() 方法前初始化const systemStore = useSystemStore();
const menuList = systemStore.menuList;const treeRef = useTemplateRef<InstanceType<typeof ElTree>>("treeRef");
const treeInfo = ref({});/*** 选择某菜单节点的回调函数* @param node 传递给 data 属性的数组中该节点所对应的对象* @param checked 树目前的选中状态对象*/
const handleElTreeCheck = (node: any, checked: any) => {const menuList = [...checked.checkedKeys, ...checked.halfCheckedKeys];treeInfo.value = { menuList };
};</script><template><div class="role"><page-search:searchConfig="searchConfig":query-click="handleQueryClick"@reset-click="handleResetClick"/><page-contentref="contentRef":content-config="contentConfig"@new-data-click="handleNewClick"@edit-data-click="handleEditClick"/><page-modal ref="modalRef" :modal-config="modalConfig" :treeInfo="treeInfo"><template #menuList><el-treeref="treeRef":data="menuList"show-checkboxnode-key="id":props="{ children: 'children', label: 'name' }"@check="handleElTreeCheck"/></template></page-modal></div>
</template><style scoped></style>

高阶组件

page-search.vue

<template><div class="search"><!-- 1.1.表单输入 --><el-form :model="searchForm" ref="formRef" label-width="120px" size="large"><el-row :gutter="20"><template v-for="item in searchConfig.formItems" :key="item.prop"><el-col :span="8"><el-form-item :label="item.label" :prop="item.prop"><template v-if="item.type === 'input'"><el-input v-model="searchForm[item.prop]" :placeholder="item.placeholder" /></template><template v-if="item.type === 'date-picker'"><el-date-pickerv-model="searchForm[item.prop]"type="daterange"range-separator="至"start-placeholder="开始日期"end-placeholder="结束日期"/></template></el-form-item></el-col></template></el-row></el-form><!-- 1.2.搜索按钮  --><div class="btns"><el-button size="large" icon="Refresh" @click="handleResetClick">重置</el-button><el-button size="large" icon="Search" type="primary" @click="handleQueryClick">查询</el-button></div></div>
</template><script setup lang="ts" name="page-search">
import type {ElForm} from 'element-plus'
import {reactive, ref} from 'vue'const emit = defineEmits(['queryClick', 'resetClick'])// 根据配置初始化表单数据
const {searchConfig} = defineProps(['searchConfig'])
const initialForm: any = {}
for (const item of searchConfig.formItems) {initialForm[item.prop] = ""
}
// console.log('初始化表单数据', initialForm)
// 1.创建表单的数据
const searchForm = reactive(initialForm)// 2.监听按钮的点击
const formRef = ref<InstanceType<typeof ElForm>>()function handleResetClick() {formRef.value?.resetFields()emit('resetClick')
}function handleQueryClick() {emit('queryClick', searchForm)
}
</script><style scoped lang="less">
.search {background-color: #fff;padding: 20px;border-radius: 5px;.el-form-item {padding: 20px 40px;margin-bottom: 0;}
}.btns {text-align: right;padding: 0 50px 10px 0;
}
</style>

page-content.vue

  1. header
  2. propList
    1. 插槽(定制化)=> 作用域插槽
  3. pageName
<template><div class="content"><div class="header"><h3 class="title">{{ contentConfig?.header?.title ?? "数据列表" }}</h3><el-button v-if="isCreate" type="primary" @click="handleNewData">{{contentConfig?.header?.btnText ?? "新建数据"}}</el-button></div><div class="table"><el-table:data="pageList":border="true":row-key="contentConfig?.childrenTree?.rowKey"style="width: 100%"><template v-for="item in contentConfig.propsList" :key="item.prop"><!-- <el-table-column align="center" :label="item.label" :prop="item.prop" :width="item.width ?? '150px'"></el-table-column>--><el-table-columnv-if="item.type === 'index' || item.type === 'selection'"align="center"v-bind="item"/><el-table-column v-else-if="item.type === 'custom'" align="center" v-bind="item"><template #default="scope"><slot :name="item.slotName" v-bind="scope" :prop="item.prop" :leaderRange="10" /></template></el-table-column><el-table-column v-else align="center" v-bind="item"><template #default="scope"><span v-if="item.type === 'timer'">{{ formatUTC(scope.row[item.prop]) }}</span><span v-else-if="item.type === 'handler'"><el-buttonv-if="isUpdate"type="primary"size="small"icon="EditPen"link@click="handleEditClick(scope.row)">编辑</el-button><el-buttonv-if="isDelete"type="danger"size="small"icon="Delete"link@click="handleDeleteClick(scope.row.id)">删除</el-button></span><span v-else>{{ scope.row[item.prop] }}</span></template></el-table-column></template></el-table></div><div class="footer"><el-paginationv-model:currentPage="currentPage"v-model:pageSize="pageSize":page-sizes="[10, 20, 30]"layout="total, sizes, prev, pager, next, jumper":total="pageTotalCount"@update:currentPage="handleCurrentChange"@update:pageSize="handlePageSizeChange"/></div></div>
</template><script setup lang="ts" name="content">
import { storeToRefs } from "pinia";
import { ref } from "vue";
import useSystemStore from "@/stores/modules/main/system/system";
import { formatUTC } from "@/utils/format";
import usePermission from "@/hooks/usePermission";const { contentConfig } = defineProps(["contentConfig"]);
const emit = defineEmits(["newDataClick", "editDataClick"]);// 0.判断是否有增删改查的权限
const isCreate = usePermission(contentConfig.pageName, "create");
const isDelete = usePermission(contentConfig.pageName, "delete");
const isUpdate = usePermission(contentConfig.pageName, "update");
const isQuery = usePermission(contentConfig.pageName, "query");// 1.请求数据
const systemStore = useSystemStore();
const currentPage = ref(1);
const pageSize = ref(10);systemStore.$onAction(({ name, after }) => {after(() => {if (name === "deletePageByIdAction" ||name === "editPageDataAction" ||name === "newPageDataAction") {currentPage.value = 1;}})
});function fetchPageListData(queryInfo: any = {}) {// 0.判断是否具有查询权限if (!isQuery) return;// 1.获取offset和sizeconst size = pageSize.value;const offset = (currentPage.value - 1) * size;// 2.发生网络请求systemStore.postPageListAction(contentConfig.pageName, { offset, size, ...queryInfo });
}fetchPageListData();// 2.展示数据
const { pageList, pageTotalCount } = storeToRefs(systemStore);// 3.绑定分页数据
function handleCurrentChange() {fetchPageListData();
}function handlePageSizeChange(newPageSize: number) {pageSize.value = newPageSize;fetchPageListData();
}function handleResetClick() {currentPage.value = 1;pageSize.value = 10;fetchPageListData();
}// 4.新建数据的处理
function handleNewData() {emit("newDataClick");
}// 5.删除和编辑操作
function handleDeleteClick(id: number) {systemStore.deletePageByIdAction(contentConfig.pageName, id);
}function handleEditClick(data: any) {emit("editDataClick", data);
}// 暴露函数
defineExpose({fetchPageListData,handleResetClick
});
</script><style scoped lang="less">
.content {margin-top: 20px;padding: 20px;background-color: #fff;.header {display: flex;height: 45px;padding: 0 5px;justify-content: space-between;align-items: center;.title {font-size: 20px;font-weight: 700;}.handler {align-items: center;}}.table {:deep(.el-table__cell) {padding: 14px 0;}}.footer {display: flex;justify-content: flex-end;margin-top: 15px;}
}
</style>

page-modal.vue

  1. header
    1. newTitle
    2. editTitle
  2. pageName
  3. formItems
<template><div class="modal"><el-dialog v-model="dialogVisible" :title="modalConfig.header.newTitle" width="30%" center><div class="form"><el-form :model="formData" label-width="80px" size="large"><template v-for="item in modalConfig.formItems" :key="item.prop"><el-form-item :label="item.label" :prop="item.prop"><template v-if="item.type === 'input'"><el-input v-model="formData[item.prop]" :placeholder="item.placeholder" /></template><template v-if="item.type === 'password'"><el-inputshow-passwordv-model="formData[item.prop]":placeholder="item.placeholder"/></template><template v-if="item.type === 'select'"><el-selectv-model="formData.parentId":placeholder="item.placeholder"style="width: 100%"><template v-for="value in item.options" :key="value.value"><el-option :value="value.value" :label="value.label" /></template></el-select></template><template v-if="item.type === 'date-picker'"><el-date-pickertype="daterange"range-separator="-"start-placeholder="开始时间"end-placeholder="结束时间"v-model="formData[item.prop]"/></template><template v-if="item.type === 'custom'"><slot :name="item.slotName"></slot></template></el-form-item></template></el-form></div><template #footer><span class="dialog-footer"><el-button @click="dialogVisible = false">取消</el-button><el-button type="primary" @click="handleConfirmClick">确定</el-button></span></template></el-dialog></div>
</template><script setup lang="ts" name="modal">
import { storeToRefs } from "pinia";
import { reactive, ref } from "vue";
import useSystemStore from "@/stores/modules/main/system/system";const dialogVisible = ref(false);
const isEdit = ref(false);
const editData = ref();// 定义数据绑定
const formData = reactive<any>({name: "",leader: "",parentId: ""
});const { modalConfig, treeInfo } = defineProps(["modalConfig", "treeInfo"]);
// 点击确定
const systemStore = useSystemStore();
const { departmentList } = storeToRefs(systemStore);const initialData: any = {};
for (const item of modalConfig?.formItems) {initialData[item.prop] = item.initialValue ?? "";
}function handleConfirmClick() {dialogVisible.value = false;// 判断是否存在含树形菜单权限的formDatalet treeFormData = { ...formData };if (treeInfo) {treeFormData = {...treeFormData,...treeInfo};}console.log(treeFormData);if (!isEdit.value) {systemStore.newPageDataAction(modalConfig.pageName, treeFormData);} else {systemStore.editPageDataAction(modalConfig.pageName, editData.value.id, treeFormData);}
}// 新建或者编辑
function setDialogVisible(isNew: boolean = true, data: any = {}) {dialogVisible.value = true;isEdit.value = !isNew;editData.value = data;for (const key in formData) {if (isNew) {formData[key] = "";} else {formData[key] = data[key];}}
}defineExpose({setDialogVisible
});
</script><style scoped lang="less">
.form {padding: 10px 30px;
}
</style>

hooks

usePageContent.ts

import { useTemplateRef } from "vue";
import PageContent from "@/components/page-content/page-content.vue";function usePageContent() {const contentRef = useTemplateRef<InstanceType<typeof PageContent>>("contentRef");const handleQueryClick = (queryInfo: any) => {contentRef.value?.fetchPageListData(queryInfo);};const handleResetClick = () => {contentRef.value?.fetchPageListData();};return {contentRef,handleQueryClick,handleResetClick};
}export default usePageContent;

usePageModal.ts

import { useTemplateRef } from "vue";
import PageModal from "@/components/page-modal/page-modal.vue";function usePageModal(newCallback?: () => void, editCallback?: (itemData: any) => void) {const modalRef = useTemplateRef<InstanceType<typeof PageModal>>("modalRef");const handleNewClick = () => {modalRef.value?.setDialogVisible(true);if (newCallback) newCallback();};const handleEditClick = (itemData: any) => {modalRef.value?.setDialogVisible(false, itemData);if (editCallback) editCallback(itemData)};return {modalRef,handleNewClick,handleEditClick};
}export default usePageModal;

最终呈现

在这里插入图片描述

相关文章:

后台管理系统通用页面抽离=>高阶组件+配置文件+hooks

目录结构 配置文件和通用页面组件 content.config.ts const contentConfig {pageName: "role",header: {title: "角色列表",btnText: "新建角色"},propsList: [{ type: "selection", label: "选择", width: "80px&q…...

8.原型模式(Prototype)

动机 在软件系统中&#xff0c;经常面临着某些结构复杂的对象的创建工作&#xff1b;由于需求的变化&#xff0c;这些对象经常面临着剧烈的变化&#xff0c;但是它们却拥有比较稳定一致的接口。 之前的工厂方法和抽象工厂将抽象基类和具体的实现分开。原型模式也差不多&#…...

Python-基于PyQt5,pdf2docx,pathlib的PDF转Word工具(专业版)

前言:日常生活中,我们常常会跟WPS Office打交道。作表格,写报告,写PPT......可以说,我们的生活已经离不开WPS Office了。与此同时,我们在这个过程中也会遇到各种各样的技术阻碍,例如部分软件的PDF转Word需要收取额外费用等。那么,可不可以自己开发一个小工具来实现PDF转…...

13 尺寸结构模块(size.rs)

一、size.rs源码 // Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE…...

STM32单片机学习记录(2.2)

一、STM32 13.1 - PWR简介 1. PWR&#xff08;Power Control&#xff09;电源控制 &#xff08;1&#xff09;PWR负责管理STM32内部的电源供电部分&#xff0c;可以实现可编程电压监测器和低功耗模式的功能&#xff1b; &#xff08;2&#xff09;可编程电压监测器&#xff08;…...

CSS 样式化表格:从基础到高级技巧

CSS 样式化表格&#xff1a;从基础到高级技巧 1. 典型的 HTML 表格结构2. 为表格添加样式2.1 间距和布局2.2 简单的排版2.3 图形和颜色2.4 斑马条纹2.5 样式化标题 3. 完整的示例代码4. 总结 在网页设计中&#xff0c;表格是展示数据的常见方式。然而&#xff0c;默认的表格样式…...

【python】tkinter实现音乐播放器(源码+音频文件)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;专__注&#x1f448;&#xff1a;专注主流机器人、人工智能等相关领域的开发、测试技术。 【python】tkinter实现音乐播放器&#xff08;源码…...

javascript常用函数大全

javascript函数一共可分为五类&#xff1a; •常规函数 •数组函数 •日期函数 •数学函数 •字符串函数 1.常规函数 javascript常规函数包括以下9个函数&#xff1a; (1)alert函数&#xff1a;显示一个警告对话框&#xff0c;包括一个OK按钮。 (2)confirm函数&#xff1a;显…...

C#属性和字段(访问修饰符)

不同点逻辑性/灵活性存储性访问性使用范围安全性属性(Property)源于字段,对字段的扩展,逻辑字段并不占用实际的内存可以被其他类访问对接收的数据范围做限定,外部使用增加了数据的安全性字段(Field)不经过逻辑处理占用内存的空间及位置大部分字段不能直接被访问内存使用不安全 …...

DeepSeek为什么超越了OpenAI?从“存在主义之问”看AI的觉醒

悉尼大学学者Teodor Mitew向DeepSeek提出的问题&#xff0c;在推特上掀起了一场关于AI与人类意识的大讨论。当被问及"你最想问人类什么问题"时&#xff0c;DeepSeek的回答直指人类存在的本质&#xff1a;"如果意识是进化的偶然&#xff0c;宇宙没有内在的意义&a…...

langchain基础(二)

一、输出解析器&#xff08;Output Parser&#xff09; 作用&#xff1a;&#xff08;1&#xff09;让模型按照指定的格式输出&#xff1b; &#xff08;2&#xff09;解析模型输出&#xff0c;提取所需的信息 1、逗号分隔列表 CommaSeparatedListOutputParser&#xff1a;…...

数据库安全管理中的权限控制:保护数据资产的关键措施

title: 数据库安全管理中的权限控制:保护数据资产的关键措施 date: 2025/2/2 updated: 2025/2/2 author: cmdragon excerpt: 在信息化迅速发展的今天,数据库作为关键的数据存储和管理中心,已经成为了企业营运和决策的核心所在。然而,伴随着数据规模的不断扩大和数据价值…...

Leetcode598:区间加法 II

题目描述&#xff1a; 给你一个 m x n 的矩阵 M 和一个操作数组 op 。矩阵初始化时所有的单元格都为 0 。ops[i] [ai, bi] 意味着当所有的 0 < x < ai 和 0 < y < bi 时&#xff0c; M[x][y] 应该加 1。 在 执行完所有操作后 &#xff0c;计算并返回 矩阵中最大…...

【Proteus】NE555纯硬件实现LED呼吸灯效果,附源文件,效果展示

本文通过NE555定时器芯片和简单的电容充放电电路,设计了一种纯硬件实现的呼吸灯方案,并借助Proteus仿真软件验证其功能。方案无需编程,成本低且易于实现,适合电子爱好者学习PWM(脉宽调制)和定时器电路原理。 一、呼吸灯原理与NE555功能分析 1. 呼吸灯核心原理 呼吸灯的…...

SAP HCM insufficient authorization, no.skipped personnel 总结归纳

导读 权限:HCM模块中有普通权限和结构化权限。普通权限就是PFCG的权限&#xff0c;结构化权限就是按照部门ID授权&#xff0c;颗粒度更细&#xff0c;对分工明细化的单位尤其重要&#xff0c;今天遇到的问题就是结构化权限的问题。 作者&#xff1a;vivi&#xff0c;来源&…...

五. Redis 配置内容(详细配置说明)

五. Redis 配置内容(详细配置说明) 文章目录 五. Redis 配置内容(详细配置说明)1. Units 单位配置2. INCLUDES (包含)配置3. NETWORK (网络)配置3.1 bind(配置访问内容)3.2 protected-mode (保护模式)3.3 port(端口)配置3.4 timeout(客户端超时时间)配置3.5 tcp-keepalive()配置…...

4 [危机13小时追踪一场GitHub投毒事件]

事件概要 自北京时间 2024.12.4 晚间6点起&#xff0c; GitHub 上不断出现“幽灵仓库”&#xff0c;仓库中没有任何代码&#xff0c;只有诱导性的病毒文件。当天&#xff0c;他们成为了 GitHub 上 star 增速最快的仓库。超过 180 个虚假僵尸账户正在传播病毒&#xff0c;等待不…...

Shadow DOM举例

这东西具有隔离效果&#xff0c;对于一些插件需要append一些div倒是不错的选择 <!DOCTYPE html> <html lang"zh-CN"> <head> <meta charset"utf-8"> <title>演示例子</title> </head> <body> <style&g…...

力扣动态规划-18【算法学习day.112】

前言 ###我做这类文章一个重要的目的还是记录自己的学习过程&#xff0c;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非常非常高滴&#xff01;&#xff01;&#xff01; 习题 1.下降路径最小和 题目链接:931. …...

网络基础

协议 协议就是约定 网络协议是协议中的一种 协议分层 协议本身也是软件&#xff0c;在设计上为了更好的模块化&#xff0c;解耦合&#xff0c;也是设计成为层状结构的 两个视角&#xff1a; 小白&#xff1a;同层协议&#xff0c;直接通信 工程师&#xff1a;同层协议&…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解

JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用&#xff0c;结合SQLite数据库实现联系人管理功能&#xff0c;并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能&#xff0c;同时可以最小化到系统…...