• 通用后台管理系统前端界面Ⅵ——首页、登录页、404页面


    登录页

    1、为了方便起见,先将element-ui的使用改为全局引入的方式。修改main.js文件如下:

    1. import Vue from 'vue'
    2. import App from './App.vue'
    3. import ElementUI from 'element-ui'
    4. import 'element-ui/lib/theme-chalk/index.css'
    5. //这个是局部引入,前面的文章有讲过
    6. // import '../plugins/element'
    7. import 'font-awesome/css/font-awesome.min.css'
    8. import axios from 'axios'
    9. import router from './router/index'
    10. Vue.config.productionTip = false
    11. Vue.prototype.axios = axios
    12. Vue.use(ElementUI)
    13. new Vue({
    14. router,
    15. render: h => h(App),
    16. }).$mount('#app')

    2、写登陆页面:

            2.1、components文件夹下新建Login.vue

            2.2、从element-ui官网找需要的组件:+

     

             2.3、修改代码(包括数据和表单绑定)整合后:

    1. <template>
    2. <div class="login">
    3. <el-card class="box-card">
    4. <div slot="header" class="clearfix">
    5. <span>疫起健康后台管理系统span>
    6. div>
    7. <el-form
    8. :model="loginForm"
    9. ref="loginForm"
    10. label-width="100px"
    11. >
    12. <el-form-item label="用户名" prop="username">
    13. <el-input
    14. v-model="loginForm.username"
    15. autocomplete="off"
    16. >el-input>
    17. el-form-item>
    18. <el-form-item label="密码" prop="password">
    19. <el-input
    20. type="password"
    21. v-model="loginForm.password"
    22. autocomplete="off"
    23. >el-input>
    24. el-form-item>
    25. <el-form-item>
    26. <el-button type="primary" @click="submitForm('loginForm')"
    27. >登录el-button>
    28. <el-button @click="resetForm('loginForm')">重置el-button>
    29. el-form-item>
    30. el-form>
    31. el-card>
    32. div>
    33. template>
    34. <script>
    35. export default {
    36. data() {
    37. return{
    38. loginForm:{
    39. username:'',
    40. password:''
    41. }
    42. }
    43. },
    44. };
    45. script>
    46. <style lang="scss">
    47. .login{
    48. width: 100%;
    49. height: 100%;
    50. position:absolute;
    51. background: #88b2dc;
    52. .box-card{
    53. width: 450px;
    54. margin: 160px auto;
    55. .el-card__header{
    56. font-size: 34px;
    57. }
    58. .el-button{
    59. width: 30%;
    60. }
    61. }
    62. }
    63. style>

    3、修改路由:启动项目(使用重定向)和输入http://localhost/login,进入的页面都是为登录页面 

    1. import Vue from 'vue'
    2. import Router from 'vue-router'
    3. //import Home from '../components/Home.vue'
    4. Vue.use(Router)
    5. export default new Router({
    6. routes: [
    7. {
    8. path: '/',
    9. // component: Home
    10. redirect:'/login',
    11. component: () => import('@/components/Login') //路由懒加载
    12. //component: resolve => require(['@/components/Home'], resolve) //异步加载
    13. },
    14. {
    15. path: '/login',
    16. name:'Login',
    17. component: () => import('@/components/Login') //路由懒加载
    18. //component: resolve => require(['@/components/Home'], resolve) //异步加载
    19. },
    20. {
    21. path: '/home',
    22. // component: Home
    23. component: () => import('@/components/Home') //路由懒加载
    24. //component: resolve => require(['@/components/Home'], resolve) //异步加载
    25. }
    26. ],
    27. mode: 'history'
    28. })

    运行结果:

     4、登录验证

            4.1 简易版,适用于小项目和简单的验证规则,实现:将验证规则直接写在html中

    1. <template>
    2. <div class="login">
    3. <el-card class="box-card">
    4. <div slot="header" class="clearfix">
    5. <span>疫起健康后台管理系统span>
    6. div>
    7. <el-form :model="loginForm" ref="loginForm" label-width="100px">
    8. <el-form-item
    9. label="用户名"
    10. prop="username"
    11. :rules="[
    12. { required: true, message: '请输入用户名', trigger: 'blur' },
    13. {
    14. min: 4,
    15. max: 10,
    16. message: '长度在4-10位字符之间',
    17. trigger: 'blur',
    18. },
    19. ]"
    20. >
    21. <el-input v-model="loginForm.username" autocomplete="off">el-input>
    22. el-form-item>
    23. <el-form-item
    24. label="密码"
    25. prop="password"
    26. :rules="[
    27. { required: true, message: '请输入密码', trigger: 'blur' },
    28. {
    29. min: 6,
    30. max: 12,
    31. message: '长度在6-12位字符之间',
    32. trigger: 'blur',
    33. },
    34. ]"
    35. >
    36. <el-input
    37. type="password"
    38. v-model="loginForm.password"
    39. autocomplete="off"
    40. >el-input>
    41. el-form-item>
    42. <el-form-item>
    43. <el-button type="primary" @click="login('loginForm')"
    44. >登录
    45. >
    46. <el-button @click="resetForm('loginForm')">重置el-button>
    47. el-form-item>
    48. el-form>
    49. el-card>
    50. div>
    51. template>

    当输入框失去焦点时,会自动进行表单校验

             4.2登录验证进阶版 

                    ①在表单里绑定rules,直接在Login.vue页面的data中写校验规则,写法参考element-ui的form表单

    1. <template>
    2. <div class="login">
    3. <el-card class="box-card">
    4. <div slot="header" class="clearfix">
    5. <span>疫起健康后台管理系统span>
    6. div>
    7. <el-form
    8. :model="loginForm"
    9. ref="loginForm"
    10. label-width="100px"
    11. :rules="rules"
    12. >
    13. <el-form-item label="用户名" prop="username">
    14. <el-input v-model="loginForm.username" autocomplete="off">el-input>
    15. el-form-item>
    16. <el-form-item label="密码" prop="password">
    17. <el-input
    18. type="password"
    19. v-model="loginForm.password"
    20. autocomplete="off"
    21. >el-input>
    22. el-form-item>
    23. <el-form-item>
    24. <el-button type="primary" @click="login('loginForm')">登录el-button>
    25. <el-button @click="resetForm('loginForm')">重置el-button>
    26. el-form-item>
    27. el-form>
    28. el-card>
    29. div>
    30. template>
    31. <script>
    32. export default {
    33. data() {
    34. // rule 是校验规则,value是input用户输入的值,callback是回调函数 参考element-ui的api文档
    35. const validateName = (rule, value, callback) => {
    36. // 请输入4-10位昵称
    37. let reg = /(^[a-zA-Z0-9]{4,10}$)/;
    38. if (value === "") {
    39. callback(new Error("请输入用户名"));
    40. } else if (!reg.test(value)) {
    41. callback(new Error("请输入4-10位用户名"));
    42. } else {
    43. callback();
    44. }
    45. };
    46. const validatePass = (rule, value, callback) => {
    47. // 6-12位密码需要包含大小写字母和数字以及特殊符号
    48. let pass =
    49. /^\S*(?=\S{6,12})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[!@#$%^&*? ])\S*$/;
    50. if (value === "") {
    51. callback(new Error("请输入密码"));
    52. } else if (!pass.test(value)) {
    53. callback(new Error("6-12位密码需要包含大小写字母和数字及特殊符号"));
    54. } else {
    55. callback();
    56. }
    57. };
    58. return {
    59. loginForm: {
    60. username: "",
    61. password: "",
    62. },
    63. rules: {
    64. username: [{ validator: validateName, trigger: "blur" }],
    65. password: [{ validator: validatePass, trigger: "blur" }],
    66. },
    67. };
    68. },
    69. methods: {
    70. login(loginForm) {
    71. this.$refs[loginForm].validate((valid) => {
    72. if (valid) {
    73. console.log(this.loginForm);
    74. } else {
    75. console.log(this.loginForm);
    76. }
    77. });
    78. },
    79. resetForm(loginForm) {
    80. this.$refs[loginForm].resetFields();
    81. },
    82. },
    83. };
    84. script>
    85. <style lang="scss">
    86. .login {
    87. width: 100%;
    88. height: 100%;
    89. position: absolute;
    90. background: #88b2dc;
    91. .box-card {
    92. width: 450px;
    93. margin: 160px auto;
    94. .el-card__header {
    95. font-size: 34px;
    96. }
    97. .el-button {
    98. width: 30%;
    99. }
    100. }
    101. }
    102. style>

     效果:

    小技巧:使用写校验规则插件

     使用:按下f1(我的笔记本需要按下Fn+f1)

                    ②在表单里绑定rules,校验规则封装后,再在Login.vue页面导入校验规则(更推荐)

    在src下新建utlis文件夹,新建validate.js文件,把Login.vue页面data中的校验规则过来,修改为如下:

    1. // 用户名匹配
    2. export function nameRule(rule, value, callback) {
    3. // 请输入4-10位昵称
    4. let reg = /(^[a-zA-Z0-9]{4,10}$)/;
    5. if (value === "") {
    6. callback(new Error("请输入用户名"));
    7. } else if (!reg.test(value)) {
    8. callback(new Error("请输入4-10位用户名"));
    9. } else {
    10. callback();
    11. }
    12. }
    13. // 密码正则匹配
    14. export function passRule(rule, value, callback) {
    15. // 6-12位密码需要包含大小写字母和数字以及特殊符号
    16. let pass = /^\S*(?=\S{6,12})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[!@#$%^&*? ])\S*$/;
    17. if (value === "") {
    18. callback(new Error("请输入密码"));
    19. } else if (!pass.test(value)) {
    20. callback(new Error("6-12位密码需要包含大小写字母和数字及特殊符号"));
    21. } else {
    22. callback();
    23. }
    24. }

    在Login.vue页面修改为:

    1. <template>
    2. <div class="login">
    3. <el-card class="box-card">
    4. <div slot="header" class="clearfix">
    5. <span>疫起健康后台管理系统span>
    6. div>
    7. <el-form
    8. :model="loginForm"
    9. ref="loginForm"
    10. label-width="100px"
    11. :rules="rules"
    12. >
    13. <el-form-item label="用户名" prop="username">
    14. <el-input v-model="loginForm.username" autocomplete="off">el-input>
    15. el-form-item>
    16. <el-form-item label="密码" prop="password">
    17. <el-input
    18. type="password"
    19. v-model="loginForm.password"
    20. autocomplete="off"
    21. >el-input>
    22. el-form-item>
    23. <el-form-item>
    24. <el-button type="primary" @click="login('loginForm')">登录el-button>
    25. <el-button @click="resetForm('loginForm')">重置el-button>
    26. el-form-item>
    27. el-form>
    28. el-card>
    29. div>
    30. template>
    31. <script>
    32. import { nameRule, passRule } from '../utils/validate.js'
    33. export default {
    34. data() {
    35. return {
    36. loginForm: {
    37. username: "",
    38. password: "",
    39. },
    40. rules: {
    41. username: [{ validator: nameRule, trigger: "blur" }],
    42. password: [{ validator: passRule, trigger: "blur" }],
    43. },
    44. };
    45. },
    46. methods: {
    47. login(loginForm) {
    48. this.$refs[loginForm].validate((valid) => {
    49. if (valid) {
    50. console.log(this.loginForm);
    51. this.axios
    52. .post("http://1.116.64.64:5004/api2/login", this.loginForm)
    53. .then((res) => {
    54. console.log(res);
    55. if (res.data.status === 200) {
    56. localStorage.setItem("username", res.data.username);
    57. this.$message({ message: res.data.message, type: "success" });
    58. this.$router.push("/home");
    59. }
    60. })
    61. .catch((err) => {
    62. console.error(err);
    63. });
    64. } else {
    65. console.log(this.loginForm);
    66. }
    67. });
    68. },
    69. resetForm(loginForm) {
    70. this.$refs[loginForm].resetFields();
    71. },
    72. },
    73. };
    74. script>
    75. <style lang="scss">
    76. .login {
    77. width: 100%;
    78. height: 100%;
    79. position: absolute;
    80. background: #88b2dc;
    81. .box-card {
    82. width: 450px;
    83. margin: 160px auto;
    84. .el-card__header {
    85. font-size: 34px;
    86. }
    87. .el-button {
    88. width: 30%;
    89. }
    90. }
    91. }
    92. style>

    效果:

    5、登录页面连接后端

    第一种

    首先:使用mock准备模拟一下网络请求后端接口:

     ① 在vscode终端输入,ctrl+c结束正在运行的项目,再下载mock插件,输入

    npm i @shymean/mock-server -g

    ② 插件安装完成后,然后在磁盘中随便一个地方新建一个文件夹,命名为 mock; 在mock文件里面新建一个mock.js空文件;

    在终端进入mock文件夹,输入命令mock,启动本地mock服务器,默认端口为7654

    mock>mock server listen at 7654

    操作步骤如下图:

     打开mock.js这个文件,自己写一些测试数据如下:

    1. //登录接口
    2. Mock.mock(/login/, {
    3. code: 200,
    4. data: {
    5. access_token: "748_bef_246_test",
    6. expires_in: 7200,
    7. }
    8. })
    9. //用户信息
    10. Mock.mock(/userInfo/, {
    11. code: 200,
    12. user: {
    13. userName:'admin',
    14. password:'123456',
    15. role:'admim',
    16. }
    17. })

     第二种

    找一个自己或别人写好的后端接口,B站有很多,找一下直接用

     封装token

     在utils文件夹下新建setToken.js文件,内容如下:

    1. export function setToken(tokenKey, token) {
    2. return localStorage.setItem(tokenKey, token)
    3. }
    4. export function getToken(tokenKey) {
    5. return localStorage.getItem(tokenKey)
    6. }
    7. export function removeToken(tokenKey) {
    8. return localStorage.removeItem(tokenKey)
    9. }

    在Login.vue进行导入使用

    1. <template>
    2. <div class="login">
    3. <el-card class="box-card">
    4. <div slot="header" class="clearfix">
    5. <span>疫起健康后台管理系统span>
    6. div>
    7. <el-form
    8. :model="loginForm"
    9. ref="loginForm"
    10. label-width="100px"
    11. :rules="rules"
    12. >
    13. <el-form-item label="用户名" prop="username">
    14. <el-input v-model="loginForm.username" autocomplete="off">el-input>
    15. el-form-item>
    16. <el-form-item label="密码" prop="password">
    17. <el-input
    18. type="password"
    19. v-model="loginForm.password"
    20. autocomplete="off"
    21. >el-input>
    22. el-form-item>
    23. <el-form-item>
    24. <el-button type="primary" @click="login('loginForm')">登录el-button>
    25. <el-button @click="resetForm('loginForm')">重置el-button>
    26. el-form-item>
    27. el-form>
    28. el-card>
    29. div>
    30. template>
    31. <script>
    32. import { nameRule, passRule } from '../utils/validate.js'
    33. import { setToken } from '@/utils/setToken.js'
    34. export default {
    35. data() {
    36. return {
    37. loginForm: {
    38. username: "",
    39. password: "",
    40. },
    41. rules: {
    42. username: [{ validator: nameRule, trigger: "blur" }],
    43. password: [{ validator: passRule, trigger: "blur" }],
    44. },
    45. };
    46. },
    47. methods: {
    48. login(loginForm) {
    49. this.$refs[loginForm].validate((valid) => {
    50. if (valid) {
    51. console.log(this.loginForm);
    52. this.axios
    53. .post("http://1.116.64.64:5004/api2/login", this.loginForm)
    54. .then((res) => {
    55. console.log(res);
    56. if (res.data.status === 200) {
    57. // localStorage.setItem("username", res.data.username);
    58. setToken("username", res.data.username);
    59. this.$message({ message: res.data.message, type: "success" });
    60. this.$router.push("/home");
    61. }
    62. })
    63. .catch((err) => {
    64. console.error(err);
    65. });
    66. } else {
    67. console.log(this.loginForm);
    68. }
    69. });
    70. },
    71. resetForm(loginForm) {
    72. this.$refs[loginForm].resetFields();
    73. },
    74. },
    75. };
    76. script>
    77. <style lang="scss">
    78. .login {
    79. width: 100%;
    80. height: 100%;
    81. position: absolute;
    82. background: #88b2dc;
    83. .box-card {
    84. width: 450px;
    85. margin: 160px auto;
    86. .el-card__header {
    87. font-size: 34px;
    88. }
    89. .el-button {
    90. width: 30%;
    91. }
    92. }
    93. }
    94. style>

    连接后端登录接口,二次封装axios

     设置项目代理,修改vue.config.js文件如下: 

    1. const { defineConfig } = require('@vue/cli-service')
    2. module.exports = defineConfig({
    3. transpileDependencies: true,
    4. devServer: {
    5. open: true,
    6. host: 'localhost',
    7. proxy: {
    8. '/api': {
    9. target: 'http://1.116.64.64:5004/api2/',
    10. changeOrigin: true,
    11. pathRewrite: {
    12. '^/api': ''
    13. }
    14. }
    15. }
    16. }
    17. })

    项目根目录下新建service.js文件,进行封装axios

    1. import axios from 'axios'
    2. import { getToken } from '@/utils/setToken.js'
    3. import { Message } from 'element-ui'
    4. const service = axios.create({
    5. baseURL: '/api', // baseURL会自动加在请求地址上
    6. timeout: 3000
    7. })
    8. // 添加请求拦截器
    9. service.interceptors.request.use((config) => {
    10. // 在请求之前做些什么(获取并设置token)
    11. config.headers['token'] = getToken('token')
    12. return config
    13. }, (error) => {
    14. return Promise.reject(error)
    15. })
    16. // 添加响应拦截器
    17. service.interceptors.response.use((response) => {
    18. // 对响应数据做些什么
    19. let { status, message } = response.data
    20. if(status !== 200) {
    21. Message({message: message || 'error', type: 'warning'})
    22. }
    23. return response
    24. }, (error) => {
    25. return Promise.reject(error)
    26. })
    27. export default service

    使用二次封装的axios,依旧采用全局导入的方式,修改main.js文件如下:

    1. import Vue from 'vue'
    2. import App from './App.vue'
    3. import ElementUI from 'element-ui'
    4. import 'element-ui/lib/theme-chalk/index.css'
    5. // import '../plugins/element'
    6. import 'font-awesome/css/font-awesome.min.css'
    7. // import axios from 'axios'
    8. import service from '../service'
    9. import router from './router/index'
    10. //或者这样导入:会自动找到index文件
    11. //import router from './router'
    12. Vue.config.productionTip = false
    13. // Vue.prototype.axios = axios
    14. Vue.prototype.service = service
    15. Vue.use(ElementUI)
    16. new Vue({
    17. router,
    18. render: h => h(App),
    19. }).$mount('#app')

    修改Login.vue页面,注释掉引入的setToken文件

    1. <template>
    2. <div class="login">
    3. <el-card class="box-card">
    4. <div slot="header" class="clearfix">
    5. <span>疫起健康后台管理系统span>
    6. div>
    7. <el-form
    8. :model="loginForm"
    9. ref="loginForm"
    10. label-width="100px"
    11. :rules="rules"
    12. >
    13. <el-form-item label="用户名" prop="username">
    14. <el-input v-model="loginForm.username" autocomplete="off">el-input>
    15. el-form-item>
    16. <el-form-item label="密码" prop="password">
    17. <el-input
    18. type="password"
    19. v-model="loginForm.password"
    20. autocomplete="off"
    21. >el-input>
    22. el-form-item>
    23. <el-form-item>
    24. <el-button type="primary" @click="login('loginForm')">登录el-button>
    25. <el-button @click="resetForm('loginForm')">重置el-button>
    26. el-form-item>
    27. el-form>
    28. el-card>
    29. div>
    30. template>
    31. <script>
    32. import { nameRule, passRule } from '../utils/validate.js'
    33. // import { setToken } from '@/utils/setToken.js'
    34. export default {
    35. data() {
    36. return {
    37. loginForm: {
    38. username: "",
    39. password: "",
    40. },
    41. rules: {
    42. username: [{ validator: nameRule, trigger: "blur" }],
    43. password: [{ validator: passRule, trigger: "blur" }],
    44. },
    45. };
    46. },
    47. methods: {
    48. login(loginForm) {
    49. this.$refs[loginForm].validate((valid) => {
    50. if (valid) {
    51. console.log(this.loginForm);
    52. this.service.post('/login',this.loginForm)
    53. .then((res) => {
    54. console.log(res.data)
    55. })
    56. } else {
    57. console.log(this.loginForm);
    58. }
    59. });
    60. },
    61. resetForm(loginForm) {
    62. this.$refs[loginForm].resetFields();
    63. },
    64. },
    65. };
    66. script>
    67. <style lang="scss">
    68. .login {
    69. width: 100%;
    70. height: 100%;
    71. position: absolute;
    72. background: #88b2dc;
    73. .box-card {
    74. width: 450px;
    75. margin: 160px auto;
    76. .el-card__header {
    77. font-size: 34px;
    78. }
    79. .el-button {
    80. width: 30%;
    81. }
    82. }
    83. }
    84. style>

    ctrl+c关掉当前运行的项目,重新新建终端输入:npm run serve,修改了vue.config.js文件一定要重启项目,配置才会生效,再进行接口测试,否则会报错如下:访问的依旧是localhhost:8080端口

    如果重启服务还是没有用,那就再一一排查一下语法,拼写是否有误或者漏掉,以下为我调试过程发现的:

     axios封装分析(其实还可以更完善:axios发送的数据不能是对象,只能是字符串的形式,所以可以使用统一的工具类对axios发送请求的数据进行处理;以此类推,接收返回的请求,可以通过判断不同的状态码,进行不同的处理(500服务器内部错误、404访问地址不存在等)参考博文):

     测试结果:

     接下来是康康想一下,接口返回的数据,除了token还有什么是要存起来的===》username===》当登录成功,进入系统首页,需要显示用户名,所以:修改Login.vue页面的login方法为下:

    1. login(loginForm) {
    2. this.$refs[loginForm].validate((valid) => {
    3. if (valid) {
    4. console.log(this.loginForm);
    5. this.service.post('/login',this.loginForm)
    6. .then((res) => {
    7. if (res.data.status === 200) {
    8. setToken('username', res.data.username)
    9. setToken('token', res.data.token)
    10. this.$message({message: res.data.message, type: 'success'})
    11. this.$router.push('/home')
    12. }
    13. })
    14. } else {
    15. console.log(this.loginForm);
    16. }
    17. });
    18. },

    做到这一步,发现代码没问题,但是为了方便后续项目整理和维护,管理接口和方法,∴把登录方法可以再封装成api进行调用:

            在src下,新建api文件夹,新建api.js文件

    1. // 把对应的接口请求封装成api来调用
    2. import service from '../service.js'
    3. // 登录接口
    4. export function login(data) {
    5. return service({
    6. method: 'post',
    7. url: '/login',
    8. data
    9. })
    10. }

     在Login.vue页面进行使用:

     404页面

     在项目中准备好静态资源:

    在components下新建NotFound.vue

    1. <template>
    2. <div class="notfound">
    3. <div class="wrapper">
    4. <div class="big">页面不见了!div>
    5. <div>首页瞧瞧,点击<router-link to="/">这里router-link>进入首页.div>
    6. div>
    7. div>
    8. template>
    9. <script>
    10. export default {
    11. data() {
    12. return {};
    13. },
    14. };
    15. script>
    16. <style>
    17. .notfound {
    18. height: 100%;
    19. background-image: url('../assets/img/astronauta.jpg'), url('../assets/img/stars404.png');
    20. background-position: right top, center center;
    21. background-repeat: no-repeat, repeat;
    22. background-size: cover, auto;
    23. }
    24. .notfound .wrapper {
    25. position: absolute;
    26. top: 60%;
    27. right: 2%;
    28. color: #fff;
    29. width: 635px;
    30. font-size: 19px;
    31. line-height: 29px;
    32. -webkit-font-smoothing: antialiased;
    33. padding: 20px;
    34. font-family: 'Source Sans Pro', sans-serif;
    35. }
    36. .notfound .wrapper .big {
    37. font-size: 74px;
    38. font-weight: 700;
    39. line-height: 68px;
    40. margin-bottom: 48px;
    41. }
    42. .notfound .wrapper a {
    43. color: #ffcc00;
    44. text-decoration: none;
    45. font-weight: 700;
    46. cursor: pointer;
    47. }
    48. @media only screen and (max-width: 666px) {
    49. .notfound .wrapper {
    50. left: auto;
    51. right: 0;
    52. width: 100%;
    53. max-width: 450px;
    54. top: 35%;
    55. }
    56. .notfound .wrapper .big {
    57. font-size: 42px;
    58. line-height: 50px;
    59. margin-bottom: 15px;
    60. }
    61. }
    62. style>

     配置路由

     效果:

     分析:

  • 相关阅读:
    Flink学习10:使用idea编写WordCount,并打包
    SpringBoot整合RabbitMQ
    MST007 摩托车磁电机同步调压器控制IC
    10_Spring Boot 集成Dubbo + Mybatis + Redis
    npm:发布/迭代个人开发包到世界仓库
    OTA: Optimal Transport Assignment for Object Detection 论文和代码学习
    【Apache Hudi】一种基于增量日志文件数的压缩策略
    还没弄明白微服务数据架构事务管理+ACID+一致性+CAP+BASE理论吗,看完彻底解决疑惑
    Docker Swarm 部署界面 UI Portainer
    day19学习总结
  • 原文地址:https://blog.csdn.net/qq_45947664/article/details/127910950