手把手制作Vue3+Flask全栈项目 全栈开发之路实战篇 问卷网站(二)管理员后台

全栈开发一条龙——前端篇
第一篇:框架确定、ide设置与项目创建
第二篇:介绍项目文件意义、组件结构与导入以及setup的引入。
第三篇:setup语法,设置响应式数据。
第四篇:数据绑定、计算属性和watch监视
第五篇 : 组件间通信及知识补充
第六篇:生命周期和自定义hooks
第七篇:路由
第八篇:传参
第九篇:插槽,常用api和全局api。
全栈开发一条龙——全栈篇
第一篇:初识Flask&MySQL实现前后端通信
第二篇: sql操作、发送http请求和邮件发送
第三篇:全栈实现发送验证码注册账号
第四篇:图片验证码及知识补充
全栈开发一条龙——实战篇

第一篇:项目建立与login页面

本章我们进入后台管理员视图的开发

文章目录

  • 一、后端
    • set_app
    • main
    • sql_ex
    • sql_ex_blueprint
  • 二、前端
    • addquestion
    • editquestion
    • questionlist
  • 三、总结与预告

一、后端

在后端,我们会遇到循环引用的问题:我们在进行后端蓝图的编写的时候,一定会要用到app(flask对象)来操作数据库,但是app我们之前放在了main.py中,这就很吊诡了,我们启动main服务,就要调用蓝图程序,而蓝图程序又要调用main中初始化的app来进行上下文操作,这就造成了循环引用(死锁),所以我们要改进我们的后端代码结构。

set_app

我们使用set_app把建立app对象的过程独立出来

from flask import Flask,jsonify,request
#jsonify将py数据转换为json数据,传给前端接口
from flask_cors import CORS
#跨域,因为有浏览器的同源策略,不同协议、域名、端口不能通信,我们要用cors来通信
from sqlalchemy import text


from flask.views import MethodView


#建立对象
app = Flask(__name__)

#转码,老外跟我们用的不一样,不改会乱码,如果有中文你要加上
app.config["JSON_AS_ASCII"] = False

main

接下来修改一下main,使得在main里我们正确的初始化app

from flask import Flask,jsonify,request
#jsonify将py数据转换为json数据,传给前端接口
from flask_cors import CORS
#跨域,因为有浏览器的同源策略,不同协议、域名、端口不能通信,我们要用cors来通信
from sqlalchemy import text


from flask.views import MethodView

from set_app import app



from login.login_blueprint import login
app.register_blueprint(login)



from dataset_info import *
#导入数据库
from data_set import db
# 配置数据库
URI = "mysql://" + mysql_account + ":" + mysql_password + "@" + mysql_host + ":" + mysql_port + "/" + mysql_data_col+"?charset=utf8"
app.config["SQLALCHEMY_DATABASE_URI"] = URI
app.config["SQLALCHEMY_COMMIT_ON_TEARDOWN"] = True
#初始化操作
db.init_app(app)



#配置跨域,*表示所有人
CORS(app,cors_allowed_orgins = "*")

import sql_ex_blueprint
app.register_blueprint(sql_ex_blueprint.sqlex)



if __name__ == "__main__":
     #调试模式 这样每次修改代码不用每次重启服务
     app.run(debug=True, host = "0.0.0.0",port = 5000)

sql_ex

我们专门建立一个操作数据库的文件,防止我们的服务蓝图文件内容过多无法维护。
首先,我们要先建立一个数据库对象


    class sql_ex_object(db.Model):
        __tablename__ = 'questions'
        questions = db.Column(db.String(300))
        choice_a = db.Column(db.String(80))
        choice_b = db.Column(db.String(80))
        choice_c = db.Column(db.String(80))
        choice_d = db.Column(db.String(80))
        point_a  = db.Column(db.Integer)
        point_b  = db.Column(db.Integer)
        point_c  = db.Column(db.Integer)
        point_d  = db.Column(db.Integer)
        id       = db.Column(db.String(45),primary_key = True)

tablename是跟数据库中的column名一样,这里确保要和数据库中的一一对应。

   class sql_ex():

        def add(self,question,a,b,c,d,ap,bp,cp,dp,id):
            with app.app_context():
                question_add = sql_ex_object()
                question_add.questions = question
                question_add.choice_a = a
                question_add.choice_b = b
                question_add.choice_c = c
                question_add.choice_d = d
                question_add.point_a  = ap
                question_add.point_b  = bp
                question_add.point_c  = cp
                question_add.point_d  = dp
                question_add.id       = id
                try: 
                    db.session.add(question_add)
                    db.session.commit()
                    db.session.close()
                    print("\n\n\ncg\n\n\n")
                    return "添加成功"
                except:
                    return "题目已存在!"
                
        def delete(self,id):
            with app.app_context():
                question_delete = sql_ex_object.query.filter(sql_ex_object.id==id).first()
                try:
                    db.session.delete(question_delete)
                    db.session.commit()
                    db.session.close()
                    return "删除成功"
                except:
                    return "删除失败"
        def search(self):
            with app.app_context():

                raw_list = db.session.execute( text("select * from questions") ).fetchall()
                list = list_row2list_dic(raw_list)
                print(list)
                

这里的内容我们基本之前的内容都讲过,就是我们题目的增删改查的工具箱,唯一的问题是,请不要忘记在每个的开头加上with app.app_content()这是在声明我以下的代码是在flask的app环境下运行的,这样才能正确的使用flask的数据库。
完整代码如下

from set_app import app
from data_set import db
from flask import current_app
from sqlalchemy import text
with app.app_context():
# ctx = app.app_context()
# ctx.push()

    def list_row2list_dic(list_row):  
        dic_temp = {}
        list_dic = []
        for x in list_row:
            listda = []
            listidx= []
            for dx in x:    
                listda.append(dx)
            xx = x._key_to_index        
            for idx in xx:
                listidx.append(idx)
            dic_temp=dict(zip(listidx,listda))
            list_dic.append(dic_temp)
        return list_dic


    class sql_ex_object(db.Model):
        __tablename__ = 'questions'
        questions = db.Column(db.String(300))
        choice_a = db.Column(db.String(80))
        choice_b = db.Column(db.String(80))
        choice_c = db.Column(db.String(80))
        choice_d = db.Column(db.String(80))
        point_a  = db.Column(db.Integer)
        point_b  = db.Column(db.Integer)
        point_c  = db.Column(db.Integer)
        point_d  = db.Column(db.Integer)
        id       = db.Column(db.String(45),primary_key = True)



    class sql_ex():

        def add(self,question,a,b,c,d,ap,bp,cp,dp,id):
            with app.app_context():
                question_add = sql_ex_object()
                question_add.questions = question
                question_add.choice_a = a
                question_add.choice_b = b
                question_add.choice_c = c
                question_add.choice_d = d
                question_add.point_a  = ap
                question_add.point_b  = bp
                question_add.point_c  = cp
                question_add.point_d  = dp
                question_add.id       = id
                try: 
                    db.session.add(question_add)
                    db.session.commit()
                    db.session.close()
                    print("\n\n\ncg\n\n\n")
                    return "添加成功"
                except:
                    return "题目已存在!"
                
        def delete(self,id):
            with app.app_context():
                question_delete = sql_ex_object.query.filter(sql_ex_object.id==id).first()
                try:
                    db.session.delete(question_delete)
                    db.session.commit()
                    db.session.close()
                    return "删除成功"
                except:
                    return "删除失败"
        def search(self):
            with app.app_context():

                raw_list = db.session.execute( text("select * from questions") ).fetchall()
                list = list_row2list_dic(raw_list)
                print(list)
                

        
    # temp  = sql_ex()
    # print(1+temp.add(question="接口",a='a',b='b',c='c',d='d',pa=1,pb=2,pc=3,pd=4))

# ctx.pop()
    

sql_ex_blueprint

接下来我们来写操作数据库的蓝图文件,主要逻辑就是接收数据,然后调用刚刚做好的数据库操作,将数据存入。此处,我们先实现添加题目的功能。

from flask import Blueprint, jsonify, request
from flask.views import MethodView
import sql_ex


sqlex = Blueprint("sqlex", __name__)

class sqlex_(MethodView):
    def get(self):
        question = request.args.get("question",None)
        a = request.args.get("a",None)
        b = request.args.get("b",None)
        c = request.args.get("c",None)
        d = request.args.get("d",None)
        ap = request.args.get("ap",None)
        bp = request.args.get("bp",None)
        cp = request.args.get("cp",None)
        dp = request.args.get("dp",None)
        id = request.args.get("id",None)
        try:
            ob = sql_ex.sql_ex()
            res = ob.add(question=question,a=a,b=b,c=c,d=d,ap=ap,bp=bp,cp=cp,dp=dp,id=id)
            return jsonify( {"errcode":0,"msg":res} )
        except:
            return jsonify( {"errcode":1,"msg":res} )


        
    def post(self):
        pass

sqlex.add_url_rule("/sqlex/", view_func=sqlex_.as_view("sqlex"))

至此,我们后端已经提供了添加题目的接口,接下来我们要写前端,以至于可以正确的发出请求。

二、前端

先说一下我们这一部分前端的结构。上一章,我们做了login页面,登录成功会自动push到我们的home页面。于是我们把home作为管理员的根节点。我们将home分为左右两个部分,左边选择、查看题目,右边添加题目、编辑题目信息、删除题目
效果如下


由于目前我们只实现了添加题目的后端接口,我们左边的题目暂时使用静态数据。
下面我们来将如何来实现。

<template>
    <div class="container">
      <div class="sidebar">
        <QuestionList @selectQuestion="selectQuestion" :selectedQuestionId="selectedQuestion?.id" @refreshQuestions="refreshQuestions" ref="questionList" />
      </div>
      <div class="content">
        <AddQuestion v-if="!selectedQuestion" @refreshQuestions="refreshQuestions" />
        <EditQuestion v-if="selectedQuestion" :question="selectedQuestion" @refreshQuestions="refreshQuestions" @clearSelection="clearSelection" />
      </div>
    </div>
</template>

<script>
import QuestionList from '@/components/QuestionList.vue';
import AddQuestion from '@/components/AddQuestion.vue';
import EditQuestion from '@/components/EditQuestion.vue';

export default {
  components: {
    QuestionList,
    AddQuestion,
    EditQuestion
  },
  data() {
    return {
      selectedQuestion: null
    };
  },
  methods: {
    selectQuestion(question) {
      this.selectedQuestion = { ...question };
    },
    clearSelection() {
      this.selectedQuestion = null;
    },
    refreshQuestions() {
      this.clearSelection();
      this.$refs.questionList.fetchQuestions();
    }
  }
};
</script>

<style>
.container {
  display: flex;
  height: 100vh;
}

.sidebar {
  width: 500px;
  background-color: #f4f4f4;
  padding: 20px;
  box-shadow: 2px 0 5px rgba(0,0,0,0.1);
  overflow-y: auto;
}

.content {
  width: 750px;
  padding: 20px;
  overflow-y: auto;
}
</style>

先说我们的home组件,我们的home组件用于实现区分左右,制作两个容器,分别将左边的questionlist和右边的add和edit放入,其中,根据我左边是否选择了已有题目来区分是要add还是edit

addquestion

<template>
  <div>
    <h2>添加新题目</h2>
    <form @submit.prevent="addQuestion">
      <div>
        <label for="question_id">题目 ID</label>
        <input type="text" v-model="question.id" required />
      </div>
      <div>
        <label for="question_text">题干</label>
        <input type="text" v-model="question.question_text" required />
      </div>
      <div class="form-row">
        <label for="choice_a">选项 A</label>
        <input type="text" v-model="question.choice_a" required />
        <label for="score_a">分数</label>
        <input type="number" v-model="question.score_a" required />
      </div>
      <div class="form-row">
        <label for="choice_b">选项 B</label>
        <input type="text" v-model="question.choice_b" required />
        <label for="score_b">分数</label>
        <input type="number" v-model="question.score_b" required />
      </div>
      <div class="form-row">
        <label for="choice_c">选项 C</label>
        <input type="text" v-model="question.choice_c" required />
        <label for="score_c">分数</label>
        <input type="number" v-model="question.score_c" required />
      </div>
      <div class="form-row">
        <label for="choice_d">选项 D</label>
        <input type="text" v-model="question.choice_d" required />
        <label for="score_d">分数</label>
        <input type="number" v-model="question.score_d" required />
      </div>
      <button type="submit">添加题目</button>
    </form>
  </div>
</template>

<script setup>

      // const question= {
      //   id: null,
      //   question_text: '',
      //   choice_a: '',
      //   score_a: 0,
      //   choice_b: '',
      //   score_b: 0,
      //   choice_c: '',
      //   score_c: 0,
      //   choice_d: '',
      //   score_d: 0
      // }
      const question= {
        id: "22",
        question_text: '12fr',
        choice_a: 'a',
        score_a: 0,
        choice_b: 'b',
        score_b: 0,
        choice_c: 'c',
        score_c: 0,
        choice_d: 'd',
        score_d: 0
      }
    import axios from 'axios';

    async function addQuestion() {
      try{

      let result=await axios.get('http://127.0.0.1:5000/sqlex/',{params:{
          id:question.id,
          question:question.question_text,
          a:question.choice_a,
          b:question.choice_b, 
          c:question.choice_c,  
          d:question.choice_d,    
          ap:question.score_a,
          bp:question.score_b,
          cp:question.score_c,
          dp:question.score_d,
      }})

          window.alert(result.data.msg)

        }catch(error){alert(error)}


    }


</script>

<style scoped>
h2 {
  color: #2c3e50;
}

form div {
  margin-bottom: 15px;
}

.form-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

label {
  margin-right: 10px;
}

input[type="text"],
input[type="number"] {
  padding: 10px;
  margin-right: 10px;
}

button {
  padding: 10px 20px;
  background-color: #2c3e50;
  color: #fff;
  border: none;
  cursor: pointer;
}
</style>

add部分也不难理解,我们先制作出样式的页面,然后将各个输入做成ref响应式数据,在用户点击添加的时候,我们将这些数据发给后端,申请加入题目。

editquestion

编辑问题的原理与add类似,实际上没有什么差别,只不过要多实现一个展示选中题目的功能,这需要用到emit组件间通信,来与questionlist联动。

<template>
  <div>
    <h2>编辑题目</h2>
    <form @submit.prevent="editQuestion">
      <div>
        <label for="question_id">题目 ID</label>
        <input type="number" v-model="localQuestion.id" required />
      </div>
      <div>
        <label for="question_text">题干</label>
        <input type="text" v-model="localQuestion.question_text" required />
      </div>
      <div class="form-row">
        <label for="choice_a">选项 A</label>
        <input type="text" v-model="localQuestion.choice_a" required />
        <label for="score_a">分数</label>
        <input type="number" v-model="localQuestion.score_a" required />
      </div>
      <div class="form-row">
        <label for="choice_b">选项 B</label>
        <input type="text" v-model="localQuestion.choice_b" required />
        <label for="score_b">分数</label>
        <input type="number" v-model="localQuestion.score_b" required />
      </div>
      <div class="form-row">
        <label for="choice_c">选项 C</label>
        <input type="text" v-model="localQuestion.choice_c" required />
        <label for="score_c">分数</label>
        <input type="number" v-model="localQuestion.score_c" required />
      </div>
      <div class="form-row">
        <label for="choice_d">选项 D</label>
        <input type="text" v-model="localQuestion.choice_d" required />
        <label for="score_d">分数</label>
        <input type="number" v-model="localQuestion.score_d" required />
      </div>
      <button type="button">保存修改</button>
      <button type="button" @click="cancelEdit">取消</button>
      <button type="button" @click="deleteQuestion">删除</button>
    </form>
  </div>
</template>

<script>
export default {
  props: {
    question: {
      type: Object,
      required: true
    }
  },
  data() {
    return {
      localQuestion: { ...this.question }
    };
  },
  watch: {
    question: {
      handler(newQuestion) {
        this.localQuestion = { ...newQuestion };
      },
      deep: true
    }
  },
  methods: {
    editQuestion() {
      console.log('Editing question:', this.localQuestion);
      // 这里可以添加发送请求到后端的代码
      // axios.put(`/api/questions/${this.localQuestion.id}`, this.localQuestion)
      //   .then(response => {
      //     console.log(response.data);
      //     this.$emit('refreshQuestions');
      //     this.$emit('clearSelection');
      //   });
    },
    cancelEdit() {
      this.$emit('clearSelection');
    },
    deleteQuestion() {
      console.log('Deleting question:', this.localQuestion.id);
      // 这里可以添加发送请求到后端的代码
      // axios.delete(`/api/questions/${this.localQuestion.id}`)
      //   .then(response => {
      //     console.log(response.data);
      //     this.$emit('refreshQuestions');
      //     this.$emit('clearSelection');
      //   });

      // 暂时使用静态数据
      this.$emit('refreshQuestions');
      this.$emit('clearSelection');
    }
  }
};
</script>

<style scoped>
h2 {
  color: #2c3e50;
}

form div {
  margin-bottom: 15px;
}

.form-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

label {
  margin-right: 10px;
}

input[type="text"],
input[type="number"] {
  padding: 10px;
  margin-right: 10px;
}

button {
  padding: 10px 20px;
  background-color: #2c3e50;
  color: #fff;
  border: none;
  cursor: pointer;
  margin-right: 10px;
}
button[type="button"] {
  background-color: #2c3e50;
}
button[type="button"]:hover {
  background-color: rgb(4, 23, 44);
}
</style>

questionlist

我们接下来来实现questionlist,这一部分不仅需要将题目输出到左边的题目栏目中,还要将问题数据传递给我们的edit,问题数据我们暂时使用静态数据。

<template>
  <div>
    <h2>所有题目</h2>
    <ul>
      <li 
        v-for="question in questions" 
        :key="question.id" 
        @click="selectQuestion(question)"
        :class="{ selected: question.id === selectedQuestionId }"
      >
        <h3>ID: {{ question.id }} - {{ question.question_text }}</h3>
        <p>A. {{ question.choice_a }} ({{ question.score_a }} 分)</p>
        <p>B. {{ question.choice_b }} ({{ question.score_b }} 分)</p>
        <p>C. {{ question.choice_c }} ({{ question.score_c }} 分)</p>
        <p>D. {{ question.choice_d }} ({{ question.score_d }} 分)</p>
        <!-- <button @click.stop="deleteQuestion(question.id)">删除</button> -->
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  props: {
    selectedQuestionId: {
      type: Number,
      default: null
    }
  },
  data() {
    return {
      questions: []
    };
  },
  mounted() {
    this.fetchQuestions();
  },
  methods: {
    fetchQuestions() {
      // 这里可以添加从后端获取数据的代码
      // axios.get('/api/questions')
      //   .then(response => {
      //     this.questions = response.data;
      //   });

      // 暂时使用静态数据
      this.questions = [
        {
          id: 1,
          question_text: '题目 1',
          choice_a: '选项 A1',
          score_a: 1,
          choice_b: '选项 B1',
          score_b: 2,
          choice_c: '选项 C1',
          score_c: 3,
          choice_d: '选项 D1',
          score_d: 4
        },
        {
          id: 2,
          question_text: '题目 2',
          choice_a: '选项 A2',
          score_a: 1,
          choice_b: '选项 B2',
          score_b: 2,
          choice_c: '选项 C2',
          score_c: 3,
          choice_d: '选项 D2',
          score_d: 4
        },
        {
          id: 3,
          question_text: '题目 3',
          choice_a: '选项 A3',
          score_a: 1,
          choice_b: '选项 B3',
          score_b: 2,
          choice_c: '选项 C3',
          score_c: 3,
          choice_d: '选项 D3',
          score_d: 4
        }
      ];
    },
    selectQuestion(question) {
      this.$emit('selectQuestion', question);
    },
    deleteQuestion(questionId) {
      // 这里可以添加发送请求到后端的代码
      // axios.delete(`/api/questions/${questionId}`)
      //   .then(response => {
      //     console.log(response.data);
      //     this.fetchQuestions();
      //     this.$emit('refreshQuestions');
      //   });

      // 暂时使用静态数据
      this.questions = this.questions.filter(question => question.id !== questionId);
      this.$emit('refreshQuestions');
    }
  }
};
</script>

<style scoped>
h2 {
  color: #2c3e50;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  padding: 10px;
  cursor: pointer;
  border-bottom: 1px solid #ddd;
}
li:hover {
  background-color: #eaeaea;
}
li.selected {
  background-color: #d0e6f7;
}
h3 {
  margin: 0;
}
p {
  margin: 0;
}
button {
  margin-top: 10px;
  padding: 5px 10px;
  background-color: red;
  color: white;
  border: none;
  cursor: pointer;
}
button:hover {
  background-color: darkred;
}
</style>

三、总结与预告

本文我们实现了一些管理员视图的功能,并将它传递到后端存储了,接下来我们要实现获取数据的功能和一些更加有利使用者的操作,比如每次添加完题目或者修改完题目之后,左侧题目列表应该自动刷新等等

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AI写作:AI助力内容创作,让你的工作效率翻倍

工欲善其事&#xff0c;必先利其器。 随着AI技术与各个行业或细分场景的深度融合&#xff0c;日常工作可使用的AI工具呈现出井喷式发展的趋势&#xff0c;AI工具的类别也从最初的AI文本生成、AI绘画工具&#xff0c;逐渐扩展到AI思维导图工具、AI流程图工具、AI生成PPT工具、AI…

海外仓出库系统:智能处理订单,增加海外仓货物流转率的关键所在

对海外仓来说&#xff0c;怎么才能提升效益&#xff1f;这应该是很多海外仓企业都在关心的问题。想提升海外仓的收益主要是三个大方向&#xff1a;开源、节流、提效。 所谓的开源&#xff0c;就是扩展业务类型和业务模式&#xff0c;在拓展新客户上下功夫。这是能让海外仓进来…

【C++软件调试技术】什么是pdb文件?如何使用pdb文件?哪些工具需要使用pdb文件?

目录 1、什么是pdb文件&#xff1f; 2、如何配置生成pdb文件&#xff1f; 3、pdb文件的时间戳和文件名称 3.1、pdb文件的时间戳 3.2、pdb文件的文件名称 4、有pdb文件才能在Visual Studio中调试代码 5、在Windbg中使用pdb文件 5.1、使用lm命令查看二进制文件的时间戳&a…

第九篇 有限状态机

实验九 有限状态机 9.1 实验目的 学习有限状态机的组成与类型&#xff1b; 掌握有限状态机的设计方式&#xff1b; 学习有限状态机的编码方式&#xff1b; 掌握使用有限状态机进行设计的方法。 9.2 原理介绍 9.2.1 有限状态机的基本概念 有限状态机&#xff08;Finite …

【TPAMI-2024】EfficientTrain++帮你降低网络训练的成本

写在前面&#xff1a;本博客仅作记录学习之用&#xff0c;部分图片来自网络&#xff0c;如需引用请注明出处&#xff0c;同时如有侵犯您的权益&#xff0c;请联系删除&#xff01; 文章目录 前言论文更容易学习的模式:频域易于学习的模式:空间域统一的训练课程 EFFICIENTTRAIN计…

计算机网络-BGP路由优选原则概述

前面我们已经学习了BGP的基础概念、对等体建立、报文类型等&#xff0c;也通过实践完成了IBGP和EBGP的实验配置&#xff0c;其实这些路由协议都是理论比较复杂&#xff0c;但是配置其实比较简单的&#xff0c;今天我们来学习BGP的路由优选原则。 一、IGP路由优选 前面我们学习了…

数据结构与算法-10_阻塞队列

文章目录 1.单锁实现2.双锁实现 1.单锁实现 Java 中防止代码段交错执行&#xff0c;有两种锁选择 synchronized 代码块&#xff0c;属于关键字级别提供锁保护&#xff0c;功能少ReentrantLock 类&#xff0c;功能丰富 以 ReentrantLock 为例 ReentrantLock lock new Reent…

tomcat-memcached会话共享配置

目录 1、安装memcache服务 2、把依赖的jar包移至tomcat/lib目录下 3、配置tomcat/conf/context.xml 4、重启tomcat服务 1、安装memcache服务 具体安装步骤此处不详细说明&#xff0c;自行根据实际情况安装即可 2、把依赖的jar包移至tomcat/lib目录下 3、配置tomcat/conf/c…

自定义类型:联合体和枚举

1. 联合体类型的声明 2. 联合体的特点 3. 联合体大小的计算 4. 枚举类型的声明 5. 枚举类型的优点 6. 枚举类型的使用 欢迎关注 熬夜学编程 创作不易&#xff0c;请多多支持 感谢大家的阅读、点赞、收藏和关注 如有问题&#xff0c;欢迎指正 1. 联合体 1.1 联合体类型的声…

java自学阶段一:基础知识学习

《项目案例—黑马tlias智能学习辅助系统》 目录&#xff1a; 异常 一&#xff1a;学习目标&#xff1a; 异常&#xff1a;能够看懂异常信息&#xff0c;了解异常体系结构和分类&#xff0c;掌握异常的两种处理方式&#xff0c;自定义异常。 二、异常&#xff1a; 1.异常的概…

yolo-v8window环境运行

源码https://github.com/ultralytics/ultralytics 1.用pycharm打开YOLOv8文件夹&#xff0c;下载依赖项&#xff0c;依赖项已经以作者的名字来封装好&#xff0c;所以直接在终端输入&#xff1a;pip install ultralytics&#xff0c;安装好之后会默认安装的cpu版本的torch&am…

WannaMine4.0病毒应急处置

一、前言 某日&#xff0c;通过流量监测设备和EDR发现挖矿请求告警&#xff0c;并存在长期445端口扫描。 二、病毒排查 上机排查&#xff0c;发现该服务器存在WannaMine4.0病毒&#xff0c;通过网上文章了解&#xff0c;如果请求挖矿域名遭安全设备拦截&#xff0c;会导致挖矿…

AI大模型页面

自己做的AI&#xff0c;模仿GPT。 访问地址&#xff1a;欢迎 请大家给点意见&#xff0c;需要追加哪些功能。

《企业应用架构模式》学习指南

导读&#xff1a;企业应用包括哪些&#xff1f;它们又分别有哪些架构模式&#xff1f; 世界著名软件开发大师Martin Fowler给你答案 01什么是企业应用 我的职业生涯专注于企业应用&#xff0c;因此&#xff0c;这里所谈及的模式也都是关于企业应用的。&#xff08;企业应用还有…

做视频号小店什么类目最容易爆单?其实,弄懂这三点就会选品了

大家好&#xff0c;我是电商花花。 我们做视频号小店做什么类目最容易爆单&#xff1f; 其实任何类目都有属于自己的受众人群和客户&#xff0c;都非常容易爆单&#xff0c;我们想要爆单&#xff0c;就要选对类目&#xff0c;选对产品。 视频号上所有的类目基本上可以分为标…

塑料焊接机熔深对激光焊接质量有什么影响

塑料焊接机的熔深对焊接质量具有直接且显著的影响。以下是熔深对焊接质量影响的详细解释&#xff1a; 1. 焊接强度&#xff1a;熔深直接决定了焊缝的截面积&#xff0c;从而影响焊接接头的强度。较深的熔深意味着焊缝的截面积更大&#xff0c;可以提供更强的结合力&#xff0c;…

Apache DolphinScheduler 社区5月月报更新!

各位热爱 DolphinScheduler 的小伙伴们&#xff0c;社区5月份月报更新啦&#xff01;这里将记录 DolphinScheduler 社区每月的重要更新&#xff0c;欢迎关注&#xff0c;期待下个月你也登上Merge Star月度榜单哦~ 月度Merge Star 感谢以下小伙伴5月份为 Apache DolphinSchedu…

SpringBoot发送Gmail邮件

1. 登录Gmail Gmail网址 点击右上角“小齿轮”&#xff0c;然后点击"查看所有设置" 点击“转发和 POP/IMAP”&#xff0c;按图中设置&#xff0c;然后点击保存&#xff1a; 2. 启用两步验证(https://myaccount.google.com/security) 登录上述网址&#xff0c;找…

【MyBatis-plus】saveBatch 性能调优和【MyBatis】的数据批量入库

总结最优的两种方法&#xff1a; 方法1&#xff1a; 使用了【MyBatis-plus】saveBatch 但是数据入库效率依旧很慢&#xff0c;那可能是是因为JDBC没有配置&#xff0c;saveBatch 批量写入并没有生效哦&#xff01;&#xff01;&#xff01; 详细配置如下&#xff1a;批量数据入…

用 HTML+CSS 实现全屏爱心滴落的动画效果,中间可显示名字

需求 在页面上显示一行白色文字,同时有爱心滴落的动画效果。 效果 HTML 和 CSS 代码 <!DOCTYPE html> <html lang="en"> <head