项目重构,从零开始搭建一套新的后台管理系统

news2025/7/21 5:34:59

背景

应公司发展需求,我决定重构公司的后台管理系统,从提出需求建议到现在的实施,期间花了将近半个月的时间,决定把这些都记录下来。

之前的后台管理系统实在是为了实现功能而实现的,没有考虑到后期的扩展性,也没有考虑到后期的维护性,所以我下定决心,向领导提出了重构的建议,经过领导的同意,我开始了重构的工作。

项目前身

之前的后台管理系统是基于ant design pro for vue搭建的,我在开发的过程中,遇到了很多问题,比如:

1.项目功能模块没有统一规划。
2.项目的代码风格不统一,代码杂乱无章。
3.各种第三方库的依赖,有重复的,有无用的。
4.项目的目录结构不合理。
5.项目API接口没有统一规划。
6.项目的权限管理不明确,几乎无用。
7.等等等…

当我接手这个项目的时候,我开发了两个大的功能模块,讲道理我这两个功能模块应该是强关联之前的某些功能的;

但是因为这个项目就是为了满足当前的需求,根本就不给你扩展的机会,所以我开发的两个功能模块都是独立的,没有任何关联,造成了相当多的重复工作,但是又不得不重复。

这就导致了后期的维护成本很高,因为我要维护的东西太多了,而且这些东西都是没有关联的,所以我决定重构这个项目。

项目重构

重构是一件很大的事情,当我提出重构的建议时,是确定了我手头上的工作已经完结,后续没有多少工作,所以不要有想法就提,要考虑到后续的工作量以及工作的优先级。

项目规划

当我决定重构这个项目的时候,我就开始了项目的规划,在开始之前我向领导提出了我的想法;

领导肯定不会轻易的同意我的想法,所以我就开始整理项目当中的问题,写文档,画流程图,多次和领导沟通,最终领导同意了我的想法。

我在争取领导的意见做了下面的准备:

1.老项目的整体流程我走了一遍,找我我觉得不合理的地方,以及可以优化的地方。
2.整理项目的功能模块,以及功能模块之间的关系。
3.整理我心中对这个项目的优化建议以及后续的规划。
4.画出我心中优化后的项目功能模块的流程图。
5.写出我优化项目需要时间的估算。
6.制订项目的开发计划,以及开发的功能模块优先级。

上面的准备工作也是修修改改,大会小会开了很多次,最终的结果是领导同意了我的想法,我开始了项目的重构。

技术选型

在领导同意了我的想法之后,我就开始了项目重构前的准备,包括技术选型,项目的目录结构,以及项目的开发计划。

技术选型沿用了之前的技术栈,但是会对一些技术进行升级迭代;

1.脚手架由vue-cli修改为vite
2.前端框架由vue2修改为vue3
3.UI框架由ant-design-vue修改为element-plus
4.状态管理由vuex修改为pinia
5.路由由vue-router修改为vue-router-next

除了上述这些技术的升级迭代之外,还会规划一些代码规范,以及项目的目录结构。

项目目录结构

项目的目录结构以及文件名的命名规范是非常重要的,因为这些都是团队协作的基础,当然我也不会去弄一个很复杂的目录结构或者特立独行的文件名命名规范,我会根据团队或者业界的一些规范来进行规划。

目录结构:

├── public
│ └──favicon.ico
├── src
│ ├── api # 接口请求
│ │ ├── index.js
│ │ └── user.js
│ ├── assets# 静态资源
│ │ └── logo.png
│ ├── components# 公共组件
│ │ └── Table # 表格组件
│ │ └── index.vue
│ ├── layout# 布局组件
| | ├── components
│ │ └── index.vue
│ ├── pages # 页面
│ │ ├── index
│ │ │ └── index.vue
│ │ └── login
│ │ └── index.vue
│ ├── router# 路由
│ │ ├── index.js
│ │ └── routes.js
│ ├── store # 状态管理
│ │ ├── index.js
│ │ └── modules
│ │ └── user.js
│ ├── styles# 样式
│ │ └── index.scss
│ ├── utils # 工具函数
│ │ ├── index.ts
│ │ └── request.ts
│ ├── App.vue# 入口组件
│ └── main.js# 入口文件
├── .editorconfig# 编辑器配置
├── .env.development # 开发环境变量
├── .env.production# 生产环境变量
├── .eslintrc.json # eslint配置
├── .gitignore # git忽略文件
|── index.html # 入口html文件
├── package.json # 依赖包
├── README.md# 项目说明
└── vite.config.js # vite配置 

文件名命名规范:

1.文件名全部小写,多个单词用_连接,如:user_info.js
2.组件命名大驼峰,如TableComponent
3.一个功能模块一个文件夹,文件夹名全部小写,入口文件为index.vue
4.公共组件放在components文件夹下,页面组件放在对应的页面文件夹下。
5.公共样式放在styles文件夹下,页面样式放在对应的页面文件夹下。
6.公共工具函数放在utils文件夹下,页面工具函数放在对应的页面文件夹下。
7.所有的请求接口放在api文件夹下,每个模块一个文件,入口文件为index.js

差不多久这么多吧,不需要那么严格,但是项目结构一定要整洁,不然后期维护起来会很麻烦。

项目实战

直接实战环节吧,不多说废话了。

因为我的项目已经都配置好了,后面的讲解可能跨度比较大,所以就不按照流程一步一步的来,这次直接一步到位。

首先附上我的package.json文件,

{"name": "my-vue-app","private": true,"version": "0.0.0","type": "module","scripts": {"dev": "vite --mode development","build": "vite build --mode production","preview": "vite preview"},"dependencies": {"@vueuse/core": "^9.5.0","axios": "^1.1.3","element-plus": "^2.2.22","pinia": "^2.0.24","vue": "^3.2.41","vue-router": "^4.1.6"},"devDependencies": {"@babel/eslint-parser": "^7.19.1","@vitejs/plugin-legacy": "^2.3.1","@vitejs/plugin-vue": "^3.2.0","@vitejs/plugin-vue-jsx": "^2.1.1","consola": "^2.15.3","eslint": "^8.28.0","eslint-config-airbnb-base": "^15.0.0","eslint-plugin-import": "^2.26.0","eslint-plugin-vue": "^9.7.0","less": "^4.1.3","unplugin-vue-components": "^0.22.9","unplugin-vue-define-options": "^0.12.8","vite": "^3.2.3","vite-plugin-eslint": "^1.8.1","vite-plugin-style-import": "^2.0.0"}
} 

项目初始化

我们使用vite来初始化项目,根据官网的提示,不同版本的npm安装命令不一样,直接上命令:

# npm 6.x
npm create vite@latest my-vue-app --template vue

# npm 7+, extra double-dash is needed:
npm create vite@latest my-vue-app -- --template vue 

安装完成后,进入项目目录,安装依赖,项目前期安装的并不用很多,就是vue全家桶:

cd my-vue-app

npm install vue vue-router@4 pinia axios element-plus -S 

安装完成之后,我们需要在main.js中引入对应的依赖:

import {createApp} from "vue"; // 引入vue
import "./styles/index.less"; // 引入全局样式
import App from "./App.vue"; // 引入入口组件
import store from "./store"; // 引入状态管理
import router from "./router"; // 引入路由

import ElementPlus from "element-plus"; // 引入element-plus
import "element-plus/dist/index.css"; // 引入element-plus样式
import * as ElementPlusIconsVue from '@element-plus/icons-vue' // 引入element-plus图标

// 创建vue实例
const app = createApp(App); 

// 注册状态管理
app.use(store); 

// 注册路由
app.use(router); 

// 注册element-plus
app.use(ElementPlus);

// 注册element-plus图标
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {app.component(key, component)
}

// 挂载vue实例
app.mount("#app"); 

main.js中的代码比较多,我们一个一个的实现。

引入全局样式

上面的main.js中,已经是全的了,所以后面讲的东西,都是在main.js中的,就不会讲引入了。

我们在src目录下新建一个styles目录,然后在styles目录下新建一个index.less文件,这个就是全局样式文件,里面写入:

html, body {margin: 0;padding: 0;
} 

引入状态管理

我们在src目录下新建一个store目录,然后在store目录下新建一个index.js文件,这个文件就是状态管理文件,里面写入:

import {createPinia} from "pinia";

const pinia = createPinia();

export default pinia; 

引入路由

我们在src目录下新建一个router目录,然后在router目录下新建一个index.js文件,这个文件就是路由文件,里面写入:

import {createRouter, createWebHashHistory} from "vue-router";
import routes from "./routes";

const router = createRouter({history: createWebHashHistory(),routes,
});

export default router; 

然后我们在router目录下新建一个routes.js文件,这个文件就是路由配置文件,里面写入:

import Layout from "@/layout/index.vue";

const routes = [{path: "/",redirect: "/index",component: Layout,meta: {title: "首页",},children: [{path: "/index",name: "Index",component: () => import("@/pages/index/index.vue"),meta: {title: "首页",},}]},{path: "/login",name: "Login",meta: {title: "登录",keepAlive: true,requireAuth: false},component: () => import("@/pages/login/index.vue")},
];

export default routes; 

引入入口组件

这个在创建项目的时候,已经创建好了,所以不用再创建了。

我们在src目录下的App.vue文件,这个文件就是入口组件,里面写入:

<template><router-view/>
</template>

<script>
export default {name: "App",
};
</script>

<style lang="less" scoped>
</style> 

布局组件

我们在src目录下新建一个layout目录,然后在layout目录下新建一个Layout.vue文件,这个文件就是布局组件,里面写入:

<template><el-container><el-aside width="260px"><right-panel/></el-aside><el-container><el-header height="64px"><header-panel/></el-header><el-main><router-view/></el-main></el-container></el-container>
</template>

<script>
import RightPanel from "@/components/RightPanel/index.vue";
import HeaderPanel from "@/components/HeaderPanel/index.vue";
export default {name: "Layout",components: {RightPanel,HeaderPanel}
};
</script>

<style lang="less" scoped>
</style> 

右侧面板组件

我们在src目录下新建一个components目录,然后在components目录下新建一个RightPanel目录,然后在RightPanel目录下新建一个index.vue文件,这个文件就是右侧面板组件,里面写入:

<template><div class="right-panel-container"><el-menustyle="border: none;"background-color="#2a5eff"class="el-menu-vertical-demo"default-active="2"text-color="#fff"router><menu-item v-for="route in routes" :route="route" :key="route.path"/></el-menu></div>
</template>

<script setup>
import { defineComponent, computed } from "vue";
import MenuItem from "@/components/RightPanel/MenuItem.vue";
import routes from "@/router/routes.js";
defineComponent({components: {MenuItem}
});

computed({routes: routes
});

</script>

<style lang="less" scoped>

.right-panel-container {width: 100%;height: 100vh;background-color: #2a5eff;color: #fff;overflow-y: auto;:deep(.el-menu .el-sub-menu.is-active .el-sub-menu__title),:deep(.el-menu .el-menu-item.is-active) {background-color: var(--el-menu-hover-bg-color);color: #52cca3;}:deep(.el-menu .el-menu-item.is-active) {border-left: 3px solid #52cca3;}:deep(.el-sub-menu .el-menu) {background-color: darken(#224bcc, 10%);}

}

.right-logo-container {display: flex;justify-content: center;align-items: center;height: 64px;.right-logo {height: 48px;display: flex;justify-content: center;align-items: center;margin: 0 8px;img {height: 48px;}}
}

</style> 

菜单组件

RightPanel目录下新建一个MenuItem.vue文件,这个文件就是菜单组件,里面写入:

<template><el-sub-menu v-if="route.children && route.children.length > 0" :index="route.path"><template #title><span>{{ (route.meta || {title: route.path}).title }}</span></template><menu-itemv-for="item in route.children":route="item":key="item.path"/></el-sub-menu><el-menu-item :index="route.path" v-else><template #title><span>{{ (route.meta || {title: route.path}).title }}</span></template></el-menu-item>
</template>

<script setup>
import { defineProps } from "vue";

defineProps({route: {type: Object,default: () => ({})},
});
</script>

<style scoped>

</style> 

头部面板组件

components目录下新建一个HeaderPanel目录,然后在HeaderPanel目录下新建一个index.vue文件,这个文件就是头部面板组件,里面写入:

<template>
<div class="header-panel-container"><div class="header-breadcrumb"><el-breadcrumb><el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item><el-breadcrumb-item>活动管理</el-breadcrumb-item><el-breadcrumb-item>活动列表</el-breadcrumb-item><el-breadcrumb-item>活动详情</el-breadcrumb-item></el-breadcrumb></div><div class="header-operate"><el-icon><Bell /></el-icon><el-dropdown><span class="user-info"><el-avatar size="small" src="avatar.png"></el-avatar><span>admin</span><i class="el-icon-arrow-down el-icon--right"></i></span><template #dropdown><el-dropdown-menu><el-dropdown-item>个人中心</el-dropdown-item><el-dropdown-item>切换账号</el-dropdown-item><el-dropdown-item>退出登录</el-dropdown-item></el-dropdown-menu></template></el-dropdown></div>
</div>
</template>

<script>
export default {name: "HeaderPanel"
};
</script>

<style lang="less" scoped>
.header-panel-container {width: 100%;height: 100%;background-color: #fff;color: #333;display: flex;align-items: center;justify-content: space-between;padding: 0 20px;box-sizing: border-box;border-bottom: 1px solid #ebeef5;.header-operate {display: flex;align-items: center;justify-content: center;:deep(.el-icon) {font-size: 20px;color: #333;cursor: pointer;padding: 10px;}}.user-info {display: flex;align-items: center;justify-content: space-between;margin-left: 10px;cursor: pointer;span {margin-left: 10px;}}
}

</style> 

到此整个项目的基本框架就搭建完成了,以上是极简主义,没有多余的东西,只是一个最基本的框架,后面会慢慢完善。

vite 配置

上面的准备只是项目结构的搭建,还需要配置一下vite,在项目根目录下新建一个vite.config.js文件,里面写入:

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import * as path from 'path';
import {createStyleImportPlugin,ElementPlusResolve,
} from 'vite-plugin-style-import'
import eslintPlugin from 'vite-plugin-eslint'
import vueJsx from '@vitejs/plugin-vue-jsx'
import legacy from '@vitejs/plugin-legacy'
import DefineOptions from 'unplugin-vue-define-options/vite'

// https://vitejs.dev/config/
export default defineConfig({resolve: {//设置别名alias: {'@': path.resolve(__dirname, 'src')}},build: {target: 'es2015', // 默认 "modules"},plugins: [vue(),vueJsx({}),createStyleImportPlugin({resolves:[ElementPlusResolve()],libs: [// 如果没有你需要的resolve,可以在lib内直接写,也可以给我们提供PR{libraryName: 'element-plus',esModule: true,resolveStyle: (name) => {return `element-plus/lib/theme-chalk/${name}.css`},ensureStyleFile: true // 忽略文件是否存在, 导入不存在的CSS文件时防止错误。},],}),eslintPlugin({include: ['src/**/*.js', 'src/**/*.vue', 'src/*.js', 'src/*.vue']}),legacy({targets: ['defaults', 'not IE 11'],}),DefineOptions(),],server: {port: 8080, //启动端口hmr: {host: '127.0.0.1',port: 8080},// 设置 https 代理proxy: {'/api': {target: 'your https address',changeOrigin: true,rewrite: (path) => path.replace(/^/api/, '')}}}
}); 

别名配置

resolve中配置别名,这样在引入文件的时候就可以使用@代替src,比如:

export default defineConfig({resolve: {//设置别名alias: {'@': path.resolve(__dirname, 'src')}}
}); 

这样在引入文件的时候就可以使用@代替src,比如:

import HeaderPanel from '@/components/HeaderPanel.vue'; 

vue 插件

plugins中配置vue插件,这样就可以在vue文件中使用jsx语法了,比如:

export default defineConfig({plugins: [vue(),vueJsx({}),]
}); 

依赖:@vitejs/plugin-vue@vitejs/plugin-vue-jsx

element-plus

plugins中配置element-plus,这样就可以在vue文件中使用element-plus了,比如:

export default defineConfig({plugins: [createStyleImportPlugin({resolves:[ElementPlusResolve()],libs: [// 如果没有你需要的resolve,可以在lib内直接写,也可以给我们提供PR{libraryName: 'element-plus',esModule: true,resolveStyle: (name) => {return `element-plus/lib/theme-chalk/${name}.css`},ensureStyleFile: true // 忽略文件是否存在, 导入不存在的CSS文件时防止错误。},],}),]
}); 

依赖:element-plusvite-plugin-style-import

eslint

eslint先需要初始化,执行npx eslint -init,然后根据提示选择配置,最后在plugins中配置eslint,这样就可以在vue文件中使用eslint了,比如:

然后在plugins中配置eslint,这样就可以在vue文件中使用eslint了,比如:

export default defineConfig({plugins: [eslintPlugin({include: ['src/**/*.js', 'src/**/*.vue', 'src/*.js', 'src/*.vue']}),]
}); 

eslint还需要配置eslintConfig,在第一步的时候你应该已经自己选择好了,这里就不再赘述了,我的项目中是选择生成.eslintrc.js文件,所以在项目根目录下会生成.eslintrc.json文件。

依赖:vite-plugin-eslint

兼容性

plugins中配置legacy,这样就可以在vue文件中使用es6语法了,比如:

export default defineConfig({plugins: [legacy({targets: ['defaults', 'not IE 11'],}),]
}); 

依赖:@vitejs/plugin-legacy

环境变量

环境变量不需要配置,直接在根目录下创建.env文件,然后在vue文件中使用process.env就可以了,比如:

VTIE_APP_BASE_URL=http://localhost:8080 
console.log(import.meta.env.VTIE_APP_BASE_URL); 

注意:VITE_是固定的,后面的APP_BASE_URL是自定义的,可以随意命名,必须得带VITE_前缀,否则会被忽略。

代理配置

server中配置代理,这样在开发环境中就可以使用代理,比如:

export default defineConfig({
 server: {port: 8080, //启动端口hmr: {host: '127.0.0.1',port: 8080},// 设置 https 代理proxy: {'/api': {target: 'your https address',changeOrigin: true,rewrite: (path) => path.replace(/^/api/, '')}}}
}); 

这样在开发环境中就可以使用代理。

打包配置

build中配置打包,这样在打包时就可以使用打包配置,比如:

export default defineConfig({build: {target: 'es2015', // 默认 "modules"},
}); 

这里指示vite打包时使用es2015语法,而不是es6语法。

自此整个项目的配置就完成了,接下来就可以按照自己的需求进行开发了。

总结

根据实际情况来进行技术选型以及架构的搭建,这样才能更好的满足业务需求,提高开发效率。

我上面并没有上什么高级或者特别的技术,没有上TypeScript,没有上prettier,也没有规范提交的commitizen

如果是自己的项目,我随便玩我会考虑上,但是团队项目终究是要考虑团队的,它不是最好的,但是它是最合适的。

最后

最近找到一个VUE的文档,它将VUE的各个知识点进行了总结,整理成了《Vue 开发必须知道的36个技巧》。内容比较详实,对各个知识点的讲解也十分到位。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

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

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

相关文章

SpringMVC常见面试题(2023最新)

目录前言1.简单介绍下你对springMVC的理解?2.说一说SpringMVC的重要组件及其作用3.SpringMVC的工作原理或流程4.SpringMVC的优点5.SpringMVC常用注解6.SpringMVC和struts2的区别7.怎么实现SpringMVC拦截器8.SpringMvc的控制器是不是单例模式&#xff1f;如果是&#xff0c;有什…

关基系统三月重保安全监测怎么做?ScanV提供纯干货!

三月重保当前&#xff0c;以政府、大型国企央企、能源、金融等重要行业和领域为代表的关键信息基础设施运营单位都将迎来“网络安全大考”。 对重要关基系统进行安全风险监测并收敛暴露面&#xff0c;响应监管要求进行安全加固&#xff0c;重保期间实时安全监测与数据汇报等具体…

js函数声明方式*2,对象声明方式*7,不同的调用

目录 一、两种函数声明方式 二、七种对象声明方式 一、两种函数声明方式 【1】命名函数 形如&#xff1a; function fu1(){ let firstName 111111111 let lastName 2222222 console.log(firstName ,lastName ) } function fu2(firstName&#xff0c;lastName ){ …

Linux 线程优先级

目录标题概述Linux进程调度的三种策略Linux 线程优先级对于实时任务对于普通任务top中的PR和NI其他说明代码示例设置为实时进程优先级测试代码概述 概述内容 常见的运用场景&#xff1a; 1&#xff1a;2;3; Linux进程调度的三种策略 SCHED_OTHER&#xff0c;分时调度策略&#…

【读论文】AttentionFGAN

【读论文】AttentionFGAN介绍网络架构提取红外图像目标信息的网络辨别器损失函数生成器损失函数辨别器损失函数总结参考论文&#xff1a; https://ieeexplore.ieee.org/document/9103116/如有侵权请联系博主介绍 好久没有读过使用GAN来实现图像融合的论文了&#xff0c;正好看…

【Java面试八股文宝典之基础篇】备战2023 查缺补漏 你越早准备 越早成功!!!——Day14

大家好&#xff0c;我是陶然同学&#xff0c;软件工程大三今年实习。认识我的朋友们知道&#xff0c;我是科班出身&#xff0c;学的还行&#xff0c;但是对面试掌握不够&#xff0c;所以我将用这100多天更新Java面试题&#x1f643;&#x1f643;。 不敢苟同&#xff0c;相信大…

计算机专业要考什么证书?

大家好&#xff0c;我是良许。 从去年 12 月开始&#xff0c;我已经在视频号、抖音等主流视频平台上连续更新视频到现在&#xff0c;并得到了不错的评价。 视频 100% 原创录制&#xff0c;绝非垃圾搬运号&#xff0c;每个视频都花了很多时间精力用心制作&#xff0c;欢迎大家…

Android高仿陌陌应用点点滑动效果

效果图&#xff1a;分析:从效果上看图片的展示具有层次感&#xff0c;在数据结构上更像是stack,所以通过继承FrameLayout来实现&#xff08;不清楚FrameLayout布局特点的可以先百度下哈&#xff09;&#xff0c;外面是通过继承FrameLayout自定义的TinderStackLayout&#xff0c…

SpringBoot-基础篇

SpringBoot基础篇 ​ 在基础篇中&#xff0c;我给学习者的定位是先上手&#xff0c;能够使用SpringBoot搭建基于SpringBoot的web项目开发&#xff0c;所以内容设置较少&#xff0c;主要包含如下内容&#xff1a; SpringBoot快速入门SpringBoot基础配置基于SpringBoot整合SSMP…

为你的Vue2.x老项目安装Vite发动机吧

天下苦webpack久矣&#xff0c;相信作为前端开发者一定经历过在项目迭代时间较长的时候经历漫长等待的这一过程&#xff0c;每一次保存都会浪费掉大量时间&#xff0c;这是webpack这种机制所带来的问题。 于是&#xff0c;尤大为我们带来了新一代前端构建工具&#xff1a;vite…

搜索旋转排序数组、路径总和 II、拆分数字

文章目录搜索旋转排序数组&#xff08;数组、二分查找&#xff09;路径总和 II&#xff08;树、深度优先搜索&#xff09;拆分数字&#xff08;算法&#xff09;搜索旋转排序数组&#xff08;数组、二分查找&#xff09; 整数数组 nums 按升序排列&#xff0c;数组中的值 互不…

Transformer学习笔记

Transformer学习笔记1. 参考2. 模型图3.encoder部分3.1 Positional Encoding3.2 Muti-Head Attention3.3 ADD--残差连接3.4 Norm标准化3.5 单个Transformer Encoder流程图4.decoder部分4.1 mask Muti-Head Attention4.2 Muti-Head Attention5 多个Transformer Encoder和多个Tra…

详解数据库基本概念

数据库&#xff08;DataBase 简称 DB&#xff09;&#xff1a;是一个长期存储在计算机内的、有组织的、可共享的、统一管理的大量数据的集合数据库管理系统&#xff08;DataBase Management System 简称 DBMS&#xff09;&#xff1a;是一种操纵和管理数据库的大型软件&#xf…

基于嵌入式linux的DHCP服务器的搭建与移植(udhcp)

DHCP是Dynamic Host Configuration Protocol的缩写&#xff0c;即动态主机配置协议。DHCP是一个很重要的局域网的网络协议&#xff0c;使用UDP协议实现动态配置功能&#xff0c;主要有以下用途&#xff1a; 1、为内部网络或网络服务供应商自动分配IP地址&#xff1b; 2、为用…

利用Python和Sprak求曲线与X轴上方的面积

有n组标本(1, 2, 3, 4), 每组由m个( , , ...)元素( , )组成(m值不定), . 各组样本的分布 曲线如下图所示. 通过程序近似实现各曲线与oc, cd直线围成的⾯积. 思路 可以将图像分成若干个梯形&#xff0c;每个梯形的底边长为(Xn1 - Xn-1)&#xff0c;面积为矩形的一半&#xff0c…

原创壁纸小程序独立后台(1.3.5版本介绍)

1、新版本开发目的 历经前两次版本迭代&#xff0c;本人发现在整个系统的架构方面存在一定的缺陷&#xff0c;这种缺陷就是前后端不分离&#xff0c;导致在后期的维护方面遇到了很多问题。 那么这次版本更新并没有带来很多新的功能&#xff0c;而是重构了系统并优化UI&#x…

【PyQt5图形界面编程(2)】:创建工程

创建工程 一、创建工程二、开始开发1、运行Qt5Designer,创建QT窗口2、运行pyUIC,转换xx.ui成xx.py3、main.py中引用xx.py中的类4、打包main.py成main.exe来发布5、执行终端报警处理方法三、其他(如果涉及)1、配置环境变量一、创建工程 采用虚拟环境来创建工程 相关的paka…

STM32FreeRTOS - 按键实现任务挂起和恢复

STM32f103C8T6 FreeRTOS - 按键实现任务挂起和恢复&#xff0c;按键按下时&#xff0c;LED任务执行&#xff0c;led闪烁&#xff0c;当led任务挂起&#xff0c;Led停止闪烁。1.STM32CubeMX 创建任务1.1配置GPIO按键配置外部中断触发GPIO绿灯&#xff0c;红灯配置输出模式1.2配置…

Android中级——色彩处理和图像处理

色彩处理 通过色彩矩阵处理 色彩矩阵介绍 图像的RGBA可拆分为一个4行5列的矩阵和5行1列矩阵相乘 其中4行5列矩阵即为ColorMatrix&#xff0c;可通过调整ColorMatrix间接调整RGBA 第一行 abcde 决定新的 R第二行 fghij 决定新的 G第三行 klmno 决定新的 G第四行 pqrst 决定新…

Ubuntu64位下安装Anaconda3的详细过程

Ubuntu下安装Anaconda的详细过程 下载 Anaconda&#xff1a;首先&#xff0c;您需要在 Anaconda 的官网上下载适合您的 Linux 版本的安装包。您可以使用以下命令下载最新版本&#xff1a; wget https://repo.anaconda.com/archive/Anaconda3-2021.05-Linux-x86_64.sh下载完毕后…