微信小程序| AIGC之动手实现ChatGPT法律顾问小程序

news2024/11/20 6:30:06

在这里插入图片描述

一、需求背景

在资本退去后,现如今的互联网行情很差劲,很多创新业务都不得不砍除。再加上国内互联网时代进入到了一个增量犹显疲态,增量杀红了眼!阶段,各大互联网公司均有一种断臂求生的态势!各位互联网同行,大力发展第二职业已然变成了必要的生产力!

我们既要辩证的看待事物,也要符合规定去看待!作为法律门外汉的我们,从零去学习庞大的法律知识已然是不切实际!单独去聘专业的法律专家或许又流程繁琐!所以,就让我们拿起ChatGPT,做一个AI版的法律质询顾问,解答你的全部法律问题!


二、项目原理及架构

2.1 实现原理

CahtGPT的角色设置为专业法律顾问,让他根据我们所提供的实际案例来产生相应的专业法律内容的回复,所以核心的一点就是我们需要写好相应的Prompt提示词内容,根据Prompt提示词的设计原则:在OpenAI接口所允许的Tokens数量限制下,为AI模型提供尽可能丰富的内容引导,也就是使用Few-Shot机制完成AI模型角色的预设!具体使用如下:

你是一个研究劳动法的专业律师,从现在开始你需要根据我的问题从劳动法的角度来分析我的案件,并且给出我相应的专业建议。我的问题是:我被裁员了该怎么办?


在这里插入图片描述


2.2 技术架构

本程序的核心在于构建优值的Prompt提示词+优化Token的消费接口,剩余的都是我们的一些接口的增删改查以及前端流式数据的输出与展示。
在这里插入图片描述


2.3 技术栈

模块语言及框架涉及的技术要点
小程序前端基于VUE 2.0语法+Uni-app跨平台开发框架Http接口通信、Flex布局方式、uView样式库的使用、JSON数据解析、定时器的使用
小程序接口服务端Python + Flask WEB框架rest接口的开发、 ChatGPT API接口的数据对接 、 前后端websocket实时通信

2.4 数据交互原理

选择操作模式
数据交互
构造问题数据发送
通过API接口返回回答数据
用户
小程序
小程序后端服务
ChatGPT

三、项目功能的实现

3.1 ChatGPT API的接入

要接入ChatGPT API,需要按照以下步骤进行操作:

  1. 注册一个账号并登录到OpenAI的官网:https://openai.com/
  2. 在Dashboard页面上,创建一个API密钥。在“API Keys”选项卡下,点击“Generate New Key”按钮。将生成的密钥保存好,以备后续使用。
  3. 选择所需的API服务,例如“Completion” API,以使用OpenAI的文本生成功能。

在这里插入图片描述
使用Python调用ChatGPT API实现代码如下:

  • 方法一:使用request
import requests
import json

# 构建API请求
url = "https://api.openai.com/v1/engines/davinci-codex/completions"
headers = {"Content-Type": "application/json",
           "Authorization": "Bearer YOUR_API_KEY"}
data = {
    "prompt": "Hello, my name is",
    "max_tokens": 5
}

# 发送API请求
response = requests.post(url, headers=headers, data=json.dumps(data))

# 解析API响应
response_data = json.loads(response.text)
generated_text = response_data["choices"][0]["text"]

print(generated_text)


  • 方式二:使用openAI库
from flask import Flask, request
import openai

app = Flask(__name__)

openai.api_key = "YOUR_API_KEY_HERE"

@app.route("/")
def home():
    return "Hello, World!"

@app.route("/chat", methods=["POST"])
def chat():
    data = request.json
    response = openai.Completion.create(
        engine="davinci",
        prompt=data["message"],
        max_tokens=60
    )
    return response.choices[0].text

if __name__ == "__main__":
    app.run()


3.2 小程序端设计与实现

法律引导界面法律质询界面
在这里插入图片描述在这里插入图片描述
咨询历史付费质询记录
在这里插入图片描述在这里插入图片描述

3.3 小程序前端流式输出设计与实现

通过查阅ChatGPT官网文档我们可以知道:·chatGPT是支持流式数据的返回·,而我们作为一个API的调用方,我们起到的只是一个接口数据的获取和处理的作用,ChatGPT所提供的流式数据返回也只是对于后端调用接口服务时有效,而对于我们的小程序前端就需要在数据返回接口中使用到数据流式响应的技术:正是由于Http是无状态的协议,前端在发送完请求之后,后端无法继续唤起上一次的调用方,也就无法保持流式数据的响应。所以我们这里使用WebSocket长链接技术以实现数据的流式响应!

  • CahtGPT法律咨询完整流式连接示例代码:
<template>
  <view class="content">
    <view class="body">
      <view v-for="(item, index) in arr" :key="index" :id="'message' + item.message_id">
        <view class="body_l" v-if="item.role == 'assistant'">
          <view class="body_lpic a">
            <image :src="now_model.icon" mode=""></image>
          </view>
          <view class="body_box">
            <view class="body_jt">
              <u-icon name="play-left-fill" color="#F6F7FB" size="20"></u-icon>
            </view>
            <!-- <view class="body_lcon pdg" v-html="item.content"></view> -->
            <view class="body_rcon pdg">
              <zero-markdown-view :markdown="item.content"></zero-markdown-view>
            </view>
            <view style="position: absolute;right: 0;bottom: 10rpx;">
              <u-icon @click="copy(item)" name="file-text-fill" size="30"></u-icon>
            </view>
          </view>
        </view>
        <view class="body_r" v-if="item.role == 'user'">
          <view class="body_box">
            <view class="body_rjt">
              <u-icon name="play-right-fill" color="#F6F7FB" size="20"></u-icon>
            </view>
            <!-- <view class="body_rcon pdg" v-html="item.content"> -->
            <view class="body_rcon pdg">
              <zero-markdown-view :markdown="item.content"></zero-markdown-view>
            </view>
          </view>
          <view class="body_rpic a">
            <!-- <image v-if="token != ''" :src="vals.avatar" mode="aspectFill"></image> -->
            <image :src="userInfo.avatar ? userInfo.avatar : '../../static/head.png'" mode="aspectFill">
            </image>
          </view>
        </view>
      </view>
    </view>
    <view class="body_l" v-if="loading" style="margin-left: 30rpx;" id="loading">
      <view class="body_lpic a">
        <image :src="now_model.icon" mode=""></image>
      </view>
      <view class="body_box ">
        <view class="body_lcon pdg" style="display: flex;overflow-x: hidden;">
          <u-loading-icon :show="loading"></u-loading-icon>
          <view v-if="!typeingText" style="padding: 30rpx;">{{ now_model.title }}思考中...</view>
          <!-- <zero-markdown-view v-if="!typeingText" style="padding: 0 20rpx;" :markdown="now_model.title">思考中...</zero-markdown-view> -->
          <!-- <view v-else style="padding: 30rpx;">{{ typeingText }}...</view> -->
          <zero-markdown-view v-else style="padding: 0 20rpx;" :markdown="typeingText"></zero-markdown-view>
        </view>
      </view>
    </view>
    <view class="flooer">
      <view class="flooer_l">
        <u--textarea v-model="prompt" placeholder="请输入内容,开始体验与人工智能交流吧" border="none" autoHeight
          style="background-color: #F6F7FB;" :maxlength="256" holdKeyboard :showConfirmBar="false"
          :cursorSpacing="28"></u--textarea>
        <!-- <u--input placeholder="请输入内容,开始体验与人工智能交流吧" border="none" clearable v-model="prompt"
					placeholderStyle="color: #7F8084"></u--input> -->
      </view>
      <view class="flooer_r pdg" @click="sendout">
        <view class="flooer_rpic a">
          <image src="../../static/fasong.png" mode=""></image>
        </view>
      </view>
    </view>
    <view style="height: 108rpx;"></view>
  </view>
</template>

<script>
import setting from "@/common/config";
//markdown相关插件
// import markdownFunc from '@/uni_modules/jo-markdown/components/jo-markdown/index.js';
// #ifdef H5
import axios from 'axios'
// #endif
import {
  mapState
} from "vuex"
var that;
export default {
  data() {
    return {
      prompt: '',
      arr: [],
      timer: null,
      loading: false,
      chat_id: '',
      typeingText: "",
      typeingId: "",
      now_model: {},
    }
  },
  computed: {
    ...mapState(['config', 'num', 'userInfo'])
  },
  onLoad(op) {
    if (op.model) {
      this.now_model = JSON.parse(op.model)
    } else {
      this.now_model = this.$store.state.main_model
    }
    uni.setNavigationBarTitle({
      title: this.now_model.title
    })
    this.arr.push({
      role: 'assistant',
      content: this.now_model.first_message,
      message_id: 'aa'
    })
    let that = this;
    if (op.chat_id) {
      this.chat_id = op.chat_id;
      this.getMessages()
    }
    let pong = '';
    let userInfo = uni.getStorageSync('userInfo')
    uni.connectSocket({
      url: setting.ws
    });
    uni.onSocketOpen(function (res) {
      console.log('chat页WebSocket连接已打开!');
      // 绑定UID
      sendMsg({
        type: 'login',
        uid: userInfo.member_id
        // uid: 3
      })
      // 设置心跳包
      pong = setInterval(() => {
        sendMsg({
          type: 'pong'
        })
      }, 20 * 1000);

    });
    uni.onSocketError(function (res) {
      console.log('WebSocket连接打开失败,请检查!');
    });
    uni.onSocketMessage(function (res) {
      // console.log('收到服务器内容:' + res.data);
      let json = JSON.parse(res.data)
      // console.log(json)
      if (json.hasOwnProperty('id')) {
        that.typeingId = json.id
        if (!json.choices[0].delta.finish_reason) {
          if (json.choices[0].delta.hasOwnProperty('content')) {
            that.typeingText += json.choices[0].delta.content
            // 此处自行斟酌是否替换
            // that.typeingText = that.typeingText.replace(/[cogptn]+/ig, "ChatGLM-6B")
          }
        }
      }

    });
    // socket断开时通知后端改变登录状态
    uni.onSocketClose(function (res) {
      console.log('WebSocket 已关闭!');
    });
    //上文中的sendMsg原型
    const sendMsg = function (data) {
      uni.sendSocketMessage({
        data: JSON.stringify(data)
      })
    }
  },
  onUnload() {
    uni.closeSocket()
  },
  onShow() {
    that = this;
    uni.getStorage({
      key: 'token',
      success: function (res) {
        that.token = res.data;

      },
      fail() {
        that.token = '';
      }
    });
  },
  onBackPress() {
    uni.hideLoading()
    clearInterval(this.timer);
  },
  onHide() {
    uni.hideLoading()
    clearInterval(this.timer);
  },
  methods: {
    getMessages() {
      uni.showLoading({

      })
      this.$request("/api/Message/index", "POST", {
        chat_id: this.chat_id,
        limit: 200,
        sort: 'message_id',
        order: 'asc',
      }).then((res) => {
        console.log(res);
        if (res.status == 200) {
          this.arr = this.arr.concat(res.data.data)
          this.$nextTick(() => {
            uni.pageScrollTo({
              selector: "#message" + this.arr[this.arr.length - 1].message_id,
              duration: 100
            });
          });
          uni.hideLoading()
        } else {
          this.$failToast('服务器繁忙,请稍后再试');
        }

      });
    },
    sendout() {
      if (!this.prompt) {
        this.$failToast("请输入内容");
        return;
      }

      this.loading = true;
      this.arr.push({
        role: 'user',
        content: this.prompt,
        message_id: this.arr.length + 1
      });
      let message = this.prompt;
      this.prompt = ""
      this.$nextTick(() => {
        uni.pageScrollTo({
          selector: "#loading",
          duration: 100
        });
      });
      setTimeout(() => {
        this.sub(message)
      }, 200);
    },
    sub(message) {
      // 条件编译处理,h5端uni.request与socket会互相阻塞
      // #ifndef H5
      this.$request("/api/Message/sendV2", "POST", {
        message: message,
        chat_id: this.chat_id,
        model_id: this.now_model.assistant_id
        // member_id: 3 // 调试之用,线上环境为token解码
      }).then((res) => {
        console.log(res);
        if (res.status == 200) {
          this.loading = false;
          this.typeingText = "";
          this.typeingId = "";
          this.arr.push({
            role: res.data.role,
            // 此处自行斟酌是否替换
            content: res.data.content,
            // content: res.data.content.replace(/[cogptn]+/ig, "ChatGLM-6B")
          });
          if (!this.chat_id) {
            this.chat_id = res.data.chat_id
          }
          this.$store.commit('useNum', 1);
          this.$nextTick(() => {
            uni.pageScrollTo({
              scrollTop: 20000,
              duration: 100
            });
          });
        } else if (res.status == 901) {
          this.loading = false;
          this.$failToast('服务器繁忙,请稍后再试');
        } else if (res.status == 411) {
          this.loading = false;
          uni.showModal({
            content: res.msg
          })
        } else {
          this.loading = false;
          this.$failToast(res.msg);
        }
      }).catch(err => {
        console.log(err)
        this.loading = false;
        this.$failToast(err.errMsg);
      })
      // #endif
      // #ifdef H5
      axios({
        method: 'post',
        url: setting.base_url + "/api/Message/sendV2",
        data: {
          message: message,
          chat_id: this.chat_id,
          model_id: this.now_model.assistant_id
        },
        headers: {
          'content-type': 'application/x-www-form-urlencoded;charset=utf-8',
          'Authorization': this.$store.state.token
        }
      }).then(response => {
        console.log(response)
        let res = response.data
        if (res.status == 200) {
          this.loading = false;
          this.typeingText = "";
          this.typeingId = "";
          this.arr.push({
            role: res.data.role,
            content: res.data.content
          });
          if (!this.chat_id) {
            this.chat_id = res.data.chat_id
          }
          this.$store.commit('useNum', 1);
          this.$nextTick(() => {
            uni.pageScrollTo({
              scrollTop: 20000,
              duration: 100
            });
          });
        } else if (res.status == 901) {
          this.loading = false;
          this.$failToast('服务器繁忙,请稍后再试');
        } else if (res.status == 411) {
          this.loading = false;
          uni.showModal({
            content: res.msg
          })
        } else {
          this.loading = false;
          this.$failToast(res.msg);
        }
      }).catch(error => {
        // reject(error);
      });
      // #endif

    },
    copy(item) {
      uni.setClipboardData({
        data: item.content,
        success() {
          uni.showModal({
            title: '提示',
            content: '内容已复制到系统剪贴板'
          })
        }
      })
    }
  }
}
</script>

<style>
@import '../../components/css/index.css';
</style>


3.4 法律小程序界面实现

<template>
	<view class="content">
		<!-- 图片区域 -->
		<view style="margin:0;padding:0;padding-top:-10rpx">
			<image src="/static/images/banner.png" mode="widthFix" style="width:100%;display: block;"></image>
		</view>
		<!-- 咨询区域 -->
		<u-row :gutter="0">
			<u-col :span="6">
				<u-card :show-head="false" :border-radius="18" box-shadow="7rpx 8rpx 20rpx #ddd">
					<view slot="body" @click="toChat">
						<view>
							<text class="consult">AI咨询</text>
						</view>
						<view>
							<u-row :gutter="0">
								<u-col :span="9" style="margin:0;padding:0;margin-bottom:20rpx;">
									<text class="consult-sub">CahtGPT智能AI咨询</text>
								</u-col>
								<u-col :span="2" style="margin:0;padding:0">
									<view style="position:absolute;right:5rpx;bottom:5rpx">
										<image src="/static/images/chat_consult.png" mode="widthFix"
											style="width:110rpx;"></image>
									</view>
								</u-col>
							</u-row>

						</view>
					</view>

				</u-card>
			</u-col>
			<u-col :span="6">
				<u-card :show-head="false" :border-radius="18" box-shadow="7rpx 8rpx 20rpx #ddd">
					<view slot="body">
						<view>
							<text class="consult">真人咨询</text>
						</view>
						<view>
							<u-row :gutter="0">
								<u-col :span="9" style="margin:0;padding:0;margin-bottom:20rpx">
									<text class="consult-sub">专业律师在线服务</text>
								</u-col>
								<u-col :span="2" style="margin:0;padding:0;">
									<view style="position:absolute;right:5rpx;bottom:5rpx">
										<image src="/static/images/phone_consult.png" mode="widthFix"
											style="width:110rpx;"></image>
									</view>
								</u-col>
							</u-row>

						</view>
					</view>

				</u-card>
			</u-col>
		</u-row>


		<!-- 按类型咨询版块 -->
		<u-row style="margin-top:15rpx">
			<u-col :span="12">
				<u-section font-size="35" lineColor="#5b80f6" title="按类型咨询" :right="false"></u-section>
			</u-col>
		</u-row>
		<view style="margin-left:2%;margin-right:2%;">
			<u-row gutter="0" style="margin-top:5rpx;">
				<u-col :span="3" v-for="(caseType,index) in caseTypeList" :key="index">
					<view class="case-type">
						<view style="margin-bottom:10rpx;">
							<image :src="caseType.caseTypeIcon" mode="widthFix" style="width:55rpx"></image>
						</view>
						<view>
							<text>{{caseType.caseTypeName}}</text>
						</view>
					</view>
				</u-col>
			</u-row>
		</view>


		<!-- 免费咨询 -->
		<view style="margin-top:30rpx;">
			<u-row>
				<u-col :span="12">
					<u-section font-size="35" lineColor="#5b80f6" title="免费咨询" sub-title="我要提问"></u-section>
				</u-col>
			</u-row>
		</view>
		<view style="margin-left:2%;margin-right:2%;margin-top:20rpx;">
			<u-cell-group>
				<u-cell-item title="法律问题"></u-cell-item>
				<u-cell-item title="法律问题"></u-cell-item>
			</u-cell-group>
		</view>

		<!-- 法律知识 -->
		<view style="margin-top:30rpx;">
			<u-row>
				<u-col :span="12">
					<u-section font-size="35" lineColor="#5b80f6" title="法律知识" sub-title="查看更多"></u-section>
				</u-col>
			</u-row>
		</view>
		<view style="margin-left:2%;margin-right:2%;margin-top:20rpx;">
			<u-cell-group>
				<u-cell-item title="法律知识"></u-cell-item>
				<u-cell-item title="法律知识"></u-cell-item>
			</u-cell-group>
		</view>

	</view>
</template>

<script>
	export default {
		data() {
			return {
				title: 'XX法律咨询',
				caseTypeList: [{
						id: 1,
						caseTypeName: "婚姻家庭",
						caseTypeIcon: "/static/images/casetype/married&family.png"
					},
					{
						id: 2,
						caseTypeName: "刑事案件",
						caseTypeIcon: "/static/images/casetype/married&family.png"
					},
					{
						id: 3,
						caseTypeName: "劳动工伤",
						caseTypeIcon: "/static/images/casetype/married&family.png"
					},
					{
						id: 4,
						caseTypeName: "债权债务",
						caseTypeIcon: "/static/images/casetype/married&family.png"
					},
					{
						id: 5,
						caseTypeName: "医疗赔偿",
						caseTypeIcon: "/static/images/casetype/married&family.png"
					},
					{
						id: 5,
						caseTypeName: "医疗赔偿",
						caseTypeIcon: "/static/images/casetype/married&family.png"
					},
					{
						id: 5,
						caseTypeName: "医疗赔偿",
						caseTypeIcon: "/static/images/casetype/married&family.png"
					},
					{
						id: 5,
						caseTypeName: "更多",
						caseTypeIcon: "/static/images/casetype/moreCaseType.png"
					}
				]
			}
		},
		onLoad() {


		},
		methods: {
			toChat() {
				uni.navigateTo({
					url: './chat/chat'
				})
			}
		}
	}
</script>

<style lang="scss" scoped>
	$consultTitleRpx: 40rpx;
	$consultTitleWeight: 700;

	$consultSubTitleRpx: 25rpx;
	$consultSubTitleColor: #888;

	.consult {
		font-size: $consultTitleRpx;
		font-weight: $consultTitleWeight;
	}

	.consult-sub {
		font-size: $consultSubTitleRpx;
		color: $consultSubTitleColor;
		margin-left: 0;
	}

	.card {
		margin-left: 5%;
		margin-right: 5%;
		width: 90%;
		box-shadow: 7rpx 8rpx 20rpx #eee;
	}



	.case-type {
		text-align: center;
		border: 1rpx solid transparent;
		background-color: #f8f8fa;
		padding-top: 30rpx;
		padding-bottom: 30rpx;
		border-radius: 10rpx;
		color: #555;
		width: 90%;
		margin-top: 20rpx;
		font-size: 25rpx;
	}
</style>

四、推荐阅读

🥇入门和进阶小程序开发,不可错误的精彩内容🥇 :

  • 《小程序开发必备功能的吐血整理【个人中心界面样式大全】》
  • 《微信小程序 | 借ChatGPT之手重构社交聊天小程序》
  • 《微信小程序 | 人脸识别的最终解决方案》
  • 《微信小程序 |基于百度AI从零实现人脸识别小程序》
  • 《吐血整理的几十款小程序登陆界面【附完整代码】》

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

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

相关文章

hadoop3.2.4集成flink 1.17.0

前言 flink安装部署有三种方式 local:单机模式&#xff0c;尽量不使用 standalone: flink自带集群&#xff0c;资源管理由flink集群管理&#xff0c;开发环境测试使用&#xff0c;不需要hadoop集群 flink on yarn: 把资源管理交给yarn实现&#xff0c;计算机资源统一由Haoop…

PCIe 载板设计资料原理图:382-基于FMC+的XCVU3P高性能 PCIe 载板

基于FMC的XCVU3P高性能 PCIe 载板 一、板卡概述 板卡主控芯片采用Xilinx UltraScale16 nm VU3P芯片&#xff08;XCVU3P-2FFVC1517I&#xff09;。板载 2 组 64bit 的DDR4 SDRAM&#xff0c;支持 IOX16或者 JTAG 口&#xff0c;支持PCIe X 16 ReV3.0以及 FMC 扩展接口。…

Hadoop基础学习---6、MapReduce框架原理

1、MapReduce框架原理 1.1 InputFormat数据输入 1.1.1 切片与MapTask并行度决定机制 1、问题引出 MapTask的并行度决定Map阶段的任务处理并发度&#xff0c;进而影响到整个job的处理速度。 2、MapTask并行度决定机制 数据块&#xff1a;Block是HDFS物理上吧数据分成一块一块。…

3D CAD模型的体素化

你有没有搜索过如何将 Cad 模型转换为 python 就绪的 numpy 数组&#xff0c;但没有得到任何明确的答案&#xff1f; 我也是。 经过长时间的研究并尝试了很多软件和 python 库&#xff0c;我终于能够将 3D STEP 文件转换为 3 维 numpy 数组。 如果你想做同样的事情或只是想知道…

线性表的总结

逻辑结构 逻辑结构 具有相同特性的数据元素的有限序列 特性 有穷性&#xff1a;一个线性表的元素个数是有限的 一致性&#xff1a;一个线性表的所有元素的性质相同&#xff0c;也就是具有相同的数据类型 序列性&#xff1a;所有元素之间的相对…

OJ练习第114题——T 秒后青蛙的位置

T 秒后青蛙的位置 力扣链接&#xff1a;1377. T 秒后青蛙的位置 题目描述 给你一棵由 n 个顶点组成的无向树&#xff0c;顶点编号从 1 到 n。青蛙从 顶点 1 开始起跳。规则如下&#xff1a; 在一秒内&#xff0c;青蛙从它所在的当前顶点跳到另一个 未访问 过的顶点&#xf…

十、数据仓库详细介绍(数据质量)流程与工具

上篇我们主要介绍了以下三部分内容。 第一部分&#xff0c;介绍了五种常见的数据管理知识体系&#xff0c;数据质量在所有的知识体系中都有非常重要的地位&#xff0c;数据应用体现数据价值&#xff0c;数据质量为应用提供支撑。 第二部分&#xff0c;我们介绍了数据质量评判的…

程序优化 - ABAP并行处理

SAP的并行方式有很多种&#xff1a; SPTA框架&#xff0c;参考debug可以看出这个核心也是异步bgRFC 异步RFC&#xff0c;使用CALL FUNCTION “XXXXXX” STARTING NEW TASK XXXX CALLING XXXX ON END OF TASK BANK_PP_JOBCTRL框架 拆分成多个后台JOB执行 这里只说SPTA框架…

【高危】Linux Kernel OverlayFS 权限提升漏洞(POC公开)

漏洞描述 Linux Kernel OverlayFS 是 Linux 内核提供的一种文件系统&#xff0c;允许将多个文件系统合并为一个单一的虚拟文件系统。 在 Linux Kernel OverlayFS 受影响版本中&#xff0c;当用户将具备特权的文件从 nosuid 的挂载点复制到另一个挂载点时&#xff0c;未授权的…

【严重】ejs 存在服务端模板注入漏洞(存在POC)

漏洞描述 EJS 是开源的 JavaScript 模板引擎&#xff0c;允许在HTML代码中使用JavaScript代码块&#xff0c;closeDelimiter 参数是 EJS 模板中的结束标记&#xff0c;用于指定结束分隔符。 由于对 CVE-2022-29078 漏洞修复不完全&#xff0c;当应用程序使用 EJS 模板引擎&am…

如何恢复已删除或丢失的音乐文件

您是否遇到过您或其他人不小心删除了您的音乐文件的情况&#xff1f;作为我自己的音乐爱好者&#xff0c;我知道这种感觉有多么毁灭性。听音乐让我们平静和放松&#xff0c;它可以帮助一些人在工作时提高工作效率或缓解他们感受到的压力。 这就是为什么如果您不小心丢失了您心…

springcloud-alibaba (04)Gateway与Nacos结合使用

Gateway与Nacos结合使用 &#x1f389;欢迎来到这里&#xff0c;今天我将为大家介绍如何将Spring Cloud Gateway和Nacos结合使用&#xff0c;实现一个高效稳定的服务网关&#xff01;在微服务架构中&#xff0c;API网关是必不可少的一部分&#xff0c;它提供了路由请求、负载均…

java版企业工程项目管理系统源代码-功能清单 图文解析

Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下&#xff1a; 首页 工作台&#xff1a;待办工作、消息通知、预警信息&#xff0c;点击可进入相应的列表 项目进度图表&#xff1a;选择&#xff08;总体或单个&#xff09;项目显示…

新手如何写新闻稿?一文带你了解记者稿的写作步骤与技巧

作为一名新手记者&#xff0c;写稿件是必须掌握的基本技能。记者稿的写作方式有很多种&#xff0c;但基本的步骤和技巧是相同的。在这篇文章中&#xff0c;我将向大家介绍记者稿的写作步骤和技巧&#xff0c;希望能对想要成为一名优秀记者的你有所帮助。 一、确定新闻价值 在写…

代码随想录训练营Day50| 123.买卖股票的最佳时机III 188.买卖股票的最佳时机IV

目录 学习目标 学习内容 123.买卖股票的最佳时机III 188.买卖股票的最佳时机IV 学习目标 123.买卖股票的最佳时机III 188.买卖股票的最佳时机IV 学习内容 123.买卖股票的最佳时机III 123. 买卖股票的最佳时机 III - 力扣&#xff08;LeetCode&#xff09;https://lee…

深度分析:智能照明百亿赛道,Yeelight易来如何做到智能照明和定制照明双C位

日前&#xff0c;艾瑞咨询发布了《2023年中国家用智能照明行业研究报告》&#xff0c;报告显示&#xff0c;中国家用智能照明市场迎来爆发式增长&#xff0c;市场占有率从2016年仅2.0%上升到2022年的20.4%&#xff0c;7年间占比增长20%。预计2023年家用智能照明市场规模将突破1…

千呼万唤始出来!从源码到架构的Spring全系列笔记,已全部分享

因粉丝强烈要求小编整理一套spring全系列资料集合&#xff0c;不然就要集体给小编寄刀片了&#xff0c;今天终于是千呼万唤始出来&#xff0c;给大家连夜整理这一套可以说是全网最全最细的Spring全系列资料&#xff0c;今天毫无保留的给大家分享出来一起学习&#xff01;一起牛…

【JavaSE】Java基础语法(七):二维数组

文章目录 &#x1fa82;1. 二维数组概述&#x1fa82;2. 二维数组动态初始化&#x1fa82;3. 二维数组访问元素的细节问题&#x1fa82;4. 二维数组静态初始化&#x1fa82;5. 二维数组遍历&#x1fa82;6. 二维数组求和 &#x1fa82;1. 二维数组概述 概述 : 二维数组也是一种…

数据库范式理论

目录 1、1NF 2、2NF 3、3NF 4、BCNF 5、4NF 1、1NF 在实际应用中&#xff0c;数据库表的每一列&#xff08;也称为属性&#xff09;都是不可分割的原子数据项&#xff0c;不能是集合&#xff0c;数组&#xff0c;记录等非原子数据项。即在实际应用中实体中的某个属性有多个…

直播电商迈入新周期,快手如何抢跑?

文 | 螳螂观察 作者 | 图霖 直播电商迈入第七个发展年头&#xff0c;来到了新周期的变革前夜。 行业竞争逐年加剧&#xff0c;但截至2022年已迅速攀升至35000亿元的直播电商市场交易规模&#xff0c;仍诱惑着新玩家挤进这张拥堵的牌桌。 美团方面&#xff0c;继今年1月底在…