项目重构,从零开始搭建一套新的后台管理系统
背景
应公司发展需求,我决定重构公司的后台管理系统,从提出需求建议到现在的实施,期间花了将近半个月的时间,决定把这些都记录下来。
之前的后台管理系统实在是为了实现功能而实现的,没有考虑到后期的扩展性,也没有考虑到后期的维护性,所以我下定决心,向领导提出了重构的建议,经过领导的同意,我开始了重构的工作。
项目前身
之前的后台管理系统是基于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-appnpm 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-plus、vite-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个技巧》。内容比较详实,对各个知识点的讲解也十分到位。




有需要的小伙伴,可以点击下方卡片领取,无偿分享
相关文章:
项目重构,从零开始搭建一套新的后台管理系统
背景 应公司发展需求,我决定重构公司的后台管理系统,从提出需求建议到现在的实施,期间花了将近半个月的时间,决定把这些都记录下来。 之前的后台管理系统实在是为了实现功能而实现的,没有考虑到后期的扩展性…...
day20_Map
今日内容 上课同步视频:CuteN饕餮的个人空间_哔哩哔哩_bilibili 同步笔记沐沐霸的博客_CSDN博客-Java2301 零、 复习昨日 一、作业 二、比较器排序 三、Collections 四、Map 五、HashMap 六、TreeMap 零、 复习昨日 HashSet 不允许重复元素,无序 HashSet去重原理: 先比较hashco…...
localStorage和sessionStorage
目录 一、localStorage和SessionStorage在哪里,是什么 二、localStorage和sessionStorage区别 三、localStorage常用方法 四、sessionStorage常用方法 一、localStorage和SessionStorage在哪里,是什么 【1】在浏览器开发者工具的Application栏目里&…...
IP地址,子网掩码,网段 概念详解
文章目录1. 子网掩码1.1 子网掩码的概念及作用1.2 子网掩码的组成1.3 子网掩码的表示方法1.4 为什么要使用子网掩码?1.5 子网掩码的分类2. 子网掩码和IP地址的关系2.1 根据掩码确定网段IP地址是以 网络号和 主机号来标示网络上的主机的,我们把网络号相同…...
数影周报:动视暴雪疑似数据泄露,数据出境安全评估申报最新进展
本周看点:动视暴雪疑似员工敏感信息及游戏数据泄露;谷歌云计算部门:两名员工合用一个工位;数据出境安全评估申报最新进展;TikTok Shop东南亚商城在泰国和菲律宾公布;智己汽车获九大金融机构50亿元贷款签约.…...
Web安全最详细学习路线指南,从入门到入职(含书籍、工具包)
在这个圈子技术门类中,工作岗位主要有以下三个方向: 安全研发 安全研究:二进制方向 安全研究:网络渗透方向 下面逐一说明一下. 第一个方向:安全研发 你可以把网络安全理解成电商行业、教育行业等其他行业一样&#x…...
ChatGPT?听说Biying把它下架了
ChatGPT被玩疯了,开始放飞自我 ChatGPT版微软必应上线不到10天…就被网友玩坏了 先说这个词,放飞自我,什么东西才会放飞自我? 人放飞自我,人?你确定是人? 所以让我们来把上面的句子改写一下。…...
中电金信:金融数字化转型路在何方?这里有答案
近期,媒体大数网整合了业内10份研究报告,详解金融数字化转型的思路、方法与路径。其中「中国电子金融级数字底座“源启”白皮书」也被收录其中。让我们一同阅读文章,探究金融数字化转型相关问题的答案吧。 当前,金融科技正在回归…...
【Leedcode】数据结构中链表必备的面试题(第五期)
【Leedcode】数据结构中链表必备的面试题(第五期) 文章目录【Leedcode】数据结构中链表必备的面试题(第五期)1.题目2.思路图解(1)第一步:复制每一个结点,插入到原结点和下一个结点之…...
ECDH secp256k1 集成
在Android 原生api是不支持secp256k1算法的,所以要先集成以下库:implementation com.madgag.spongycastle:core:1.58.0.0compile com.madgag.spongycastle:prov:1.54.0.0compile com.madgag.spongycastle:pkix:1.54.0.0compile com.madgag.spongycastle:…...
工单模型的理解与应用
工单(任务单)模型的定义 工单模型是一种分派任务的方法,可以用来跟踪、评估和报告任务的完成情况。它通常用于针对特定目标的重复性任务或项目,以确保任务能够按时完成并符合期望的标准。 工单模型的基本流程为:提…...
Python年利率计算器【N日年化收益率】
现在有闲钱的人,按照聪明等级从低到高排序应该是钱买股票,一年利率约为-20%钱放银行活期,年利率约为0.3%钱放银行定期,一年利率约为1.5%钱放余额宝(支付宝)或零钱通(微信)࿰…...
3年测试拿8K,被校招来的实习生反超薪资,其实你在假装努力
最近朋友给我分享了一个他公司发生的事 大概的内容呢:公司一位工作3年的测试工资还没有新人高,对此怨气不小,她来公司辛辛苦苦三年,三年内迟到次数都不超过5次,每天都是按时上下班,工作也按量完成…...
因子分析计算权重
因子分析两类权重计算方法总结 案例背景 疫情爆发以来,越来越多的人为了避免线下与人接触,选择了线上购买生活必需品。网购虽然方便快捷,但是随着订单压力的增加,物流问题也随之出现,近期有很多卖家收到物流投诉的问题…...
国家调控油价预测案例+源码
项目git地址:https://github.com/Boris-2021/Oil-price-control-forecast 使用已知的历史数据:日期、汇率、布伦特、WTI、阿曼原油价格,预测下一个调价周期中的汽油、柴油零售限价的调价价格。 一. 需求 1.1 需求说明 使用已知的历史数据&a…...
Gephi快速入门
Gephi快速入门1. 导入文件(Import file)2. 布局(Layout)3. 排序(Ranking)4. 指标(Metrics)5. 标签(Label)6. 社区发现(Community detection&#…...
GitHub
什么是 Github?GitHub是一个面向开源及私有软件项目的托管平台,因为只支持Git作为唯一的版本库格式进行托管,故名GitHub。一、常用词Watch:观察。如果watch了一个项目,之后这个项目有更新,你会在第一时间收到该项目更…...
QT基础入门【调试篇】QT远程部署与调试嵌入式ARM开发板
目录 一、环境配置 1、根据开发板完成交叉编译链以及GDB的配置(因开发板而异)...
可观测性最佳实践|阿里云事件总线 EventBridge 最佳实践
本文介绍如何把阿里云事件总线 EventBridge 的内容接入观测云平台,通过观测云强大的统一汇聚能力轻松获取阿里云事件,实时追踪最新的数据信息。 背景信息 事件总线 EventBridge 是阿里云提供的一款无服务器事件总线服务,支持阿里云服务、自定…...
设计模式-行为型
设计模式-行为型 行为型设计模式主要用于软件运行时复杂的流程控制。包含:模板方法模式、策略模式、命令模式、职责链模式、状态模式、观察者模式、中介者模式、迭代器模式、访问者模式、备忘录模式和解释器模式 模板方法模式 在软件设计时,很多时候系…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
